java.time: самый простой способ получить разницу в часах между двумя объектами LocalTime - PullRequest
1 голос
/ 13 июня 2019

Я хочу получить разницу в часах между текущим временем в определенном часовом поясе и временем UTC.Я попробовал это:

 LocalTime time = LocalTime.now();
 System.out.println(time); //21:05:42:764

 LocalTime utcTime = LocalTime.now(ZoneId.of("UTC"));
 System.out.println(utcTime);  //18:05:42:769

 System.out.println(Duration.between(utcTime, time).getSeconds()/3600);  //2
 System.out.println(Duration.between(time, utcTime).getSeconds()/3600);  //-3

Почему разница между двумя последними результатами и есть ли лучшие способы сделать это?Мне нужно получить номер 3.

Ответы [ 2 ]

4 голосов
/ 13 июня 2019

Почему разница между двумя последними результатами

Причиной того, что вы получаете разные результаты для двух вычисленных длительностей, является сочетание того факта, что между двумя записями прошло какое-то крошечное время, и того факта, что продолжительность start time включен в диапазон, но продолжительность end time не указана.

Взгляните на эти времена: 6:00:00:001 против 8:00:00:000. Здесь совершенно очевидно, что мы находимся всего в одной миллисекунде от двух часов, но когда мы думаем о секундах, мы получим 7199 или -7200. Когда мы затем сделаем целочисленное математическое (т.е. разделим на 3600), мы получим 1 или -2.

Если бы не первая лишняя миллисекунда на первой отметке времени, абсолютное значение двух было бы идентичным.

4 голосов
/ 13 июня 2019

Duration неправильный класс. Существует нулевая продолжительность между «сейчас» в одном часовом поясе и «сейчас» в другом. Для забавного, но запоминающегося способа думать об этом см. здесь .

Похоже, вы пытаетесь узнать текущее смещение от UTC для данного часового пояса. Для этого вы можете использовать класс ZonedDateTime:

ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
ZoneOffset offset = zdt.getOffset();
int offsetMinutes = offset.getTotalSeconds() / 60;
double offsetHours = ((double) offsetMinutes) / 60;
System.out.println(offsetHours);  // 5.5

Вы также можете просто использовать ZonedDateTime.now() в первой строке, если хотите использовать текущий часовой пояс компьютера.

Что касается LocalTime - это только часть времени (часы, минуты, секунды и меньше). Поскольку дата не связана, вы не можете точно определить, к какому смещению часового пояса она относится. Существует более одной даты, что «сегодня» происходит в любой момент. Смещения часовых поясов варьируются от UTC-12 до UTC + 14, поэтому действительно есть значения, когда одно и то же время дня происходит в две разные даты где-то на планете.

Например, 08:00:00 на Гавайях (Pacific/Honolulu) на 2019-01-01 также 08:00:00 на Кирибати (Pacific/Kiritimati), но на 2019-01-02 - следующая дата! ( Ссылка здесь. ) Таким образом, если у вас был LocalTime объект с 08:00:00 и он был 08:00:00 в одной из этих двух зон, вы не смогли бы определить, какая это была или каким должно быть соответствующее смещение UTC.

Кроме того, имейте в виду, что смещения часовых поясов не ограничиваются целыми часами. Существуют современные часовые пояса со смещением в полчаса и 45 минут. Исторически были и другие.

Наконец, имейте в виду, что смещение не обязательно является достаточным для определения часового пояса. Многие часовые пояса имеют смещения в некоторые моменты времени, но отличаются в других. См. «Часовой пояс! = Смещение» в теге часового пояса вики .

О, и ваши результаты получают 2 в одном направлении и -3 в другом - это ошибка округления из-за вашего целочисленного деления. Если вы распечатаете значение секунд, вы заметите, что они на расстоянии одной секунды (10799, против -10800). Копайте ближе, и вы обнаружите, что «сейчас» включает доли секунды, которые были усечены при вызове getSeconds. (Вы звонили .now() дважды, поэтому они были в разное время.)

...