Путаница с Java Time parsing UTC
Я смущен обработкой времени в java time. Я так долго работал в предположении, что если метка времени указана как зулусское время, java позаботится о смещении относительно местного времени.
для иллюстрации. В настоящее время я нахожусь в BST, который имеет смещение UTC +1. Имея это в виду, я ожидал бы этого зулусского времени:
2016-09-12T13:15:17.309Z
на
2016-09-12T14:15:17.309
LocalDateTime после его анализа. Это потому, что мое системное время по умолчанию установлено в BST и вышеуказанная метка времени (время zulu) указывает, что это время UTC.
вместо этого, однако, рассмотрим этот пример:
String ts = "2016-09-12T13:15:17.309Z";
LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
System.out.println(parse);
это будет напечатано:
2016-09-12T13:15:17.309
таким образом, метка времени, анализируемая как LocalDateTime, не распознается как время UTC и вместо этого обрабатывается как локальное время напрямую. Поэтому я подумал, что, возможно, мне нужно проанализировать его как ZonedDateTime и преобразовать его в LocalDateTime специально, чтобы получить правильное местное время. С этим тест:
String ts = "2016-09-12T13:15:17.309Z";
ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
System.out.println(parse);
System.out.println(parse.toLocalDateTime());
Я получаю выходы:
2016-09-12T13:15:17.309Z
2016-09-12T13:15:17.309
одинаковый вывод для обеих дат.
единственный способ правильно разобрать это, что я мог найти, это:
String ts = "2016-09-12T13:15:17.309Z";
Instant instant = Instant.parse(ts); // parses UTC
LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(instant);
System.out.println(ofInstant);
печатается:
2016-09-12T13:15:17.309Z
2016-09-12T14:15:17.309
что верно.
Итак, вопрос(ы):
- не стоит времени Java узнать время UTC и разобрать его на правильный системы по умолчанию?
- как я могу использовать
LocalDateTime#parse
подход чтобы получить правильный результат? - должен ли я использовать
Instant
для всего сейчас и отказаться от разбора?
проблема в том, что jersey/jackson
модули времени java анализируют временные метки, используя формат ISO и обычный LocalDateTime#parse
методы. Я понял, что мои времена не прочь, так как они рассматриваются как LocalTime
хотя на самом деле они находятся в зулусском времени.
2 ответов
вы неправильно поняли цель LocalDateTime
.
чтобы процитировать документацию класса:
дата-время без часового пояса в календарной системе ISO-8601, например {@code 2007-12-03T10:15:30}.
...
этот класс не хранит и не представляет часовой пояс. Это описание момента, как на дни рождения, в сочетании с местным временем, как видно на настенные часы. Он не может представлять мгновенный на линии времени без дополнительной информации, такой как смещение или часовой пояс.
таким образом, это явная цель - просто представить дату и время без часовой пояс. Программ, это не для представления даты и времени в местном часовом поясе.
поэтому каждое преобразование просто удаляет часовой пояс.
так что для ваших целей вам нужен ZonedDateTime
С ZoneId.systemDefault()
как вы уже использовали в своей третий пример.
для вашего второго примера это может быть:
String ts = "2016-09-12T13:15:17.309Z";
ZonedDateTime parse =
ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME)
.withZoneSameInstant(ZoneId.systemDefault());
System.out.println(parse);
System.out.println(parse.toLocalDateTime());
tl; dr
- Do не использовать
LocalDateTime
. - использовать
Instant
&ZonedDateTime
.
пример:
Instant.parse( "2016-09-12T13:15:17.309Z" )
.atZone( ZoneId.of( "Europe/London" ) )
.toString();
2016-09-12T14:15:17.309+01:00[Европа/Лондон]
подробности
на ответ Krüske является правильным. Вы неправильно поймите значение LocalDateTime
класса. Это не представляют дату-время конкретной местности. Как раз наоборот, это делает не представляют собой фактический момент вообще.
предлагаю подумать о Instant
как ваш основной класс строительного блока в java.время. The Instant
класс представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) знаков после запятой фракция.)
входная строка соответствует формату ISO 8601, используемому по умолчанию в Instant
класс как для синтаксического анализа, так и для генерации строковых представлений. The Z
на конце сокращенно от Zulu
и означает UTC. Нет необходимости указывать шаблон форматирования.
Instant instant = Instant.parse( "2016-09-12T13:15:17.309Z" );
как программист вы должны научиться думать и работать в UTC в первую очередь. Забудь о своем часовом поясе. Подумайте о UTC как о единственном истинном времени. Применить часовой пояс как вариацию и только как необходимый.
указать правильное название часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте аббревиатуру из 3-4 букв, такую как BST
или EST
или IST
поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны(!). Если BST
вы имели в виду британское летнее время, тогда фактическое название часового пояса было бы Europe/London
. Ява.классы времени будут определять, как отрегулировать для всех аномалий включая летнее время (DST).
ZoneId z = ZoneId.of( "Europe/London" );
ZonedDateTime zdt = instant.atZone( z );
о java.время
на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют беспокойных старых наследие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
на Joda Времени, теперь ремонт режим, советует миграцию на java.время.
чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений. Спецификация JSR 310.
где получить java.время занятий?
-
Java SE 8 и SE 9 и позже
- встроенный.
- часть стандартного Java API с комплектной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
-
Java SE 6 и SE 7
- большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
-
Android
- в ThreeTenABP проект приспосабливается ThreeTen-Backport (упомянуто выше) для Android конкретно.
- посмотреть как использовать....
на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.