Преобразовать строку ISO 8601 в UTC по местному времени - JodaTime добавляет противоположность местного часового пояса - PullRequest
0 голосов
/ 24 февраля 2019

Скажите, что у меня String равно 2019-02-23T07:58:21.Это время, полученное из системных часов в UTC.

Я хочу преобразовать время в то, что было бы в местном системном времени.

Я использую JodaTime, потому что онокажется, что он легко может делать то, что я хочу.


То, что я пробовал:

DateTimeFormatter dateParser = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();

DateTime dateTime;
LocalDateTime localDateTime;

dateTime = dateParser.parseDateTime("2019-02-22T01:03:23Z");
localDateTime = dateTime.toLocalDateTime();

System.out.println("UTC: " + dateTime.toDate());
System.out.println("Local: " + localDateTime.toDate());

Что выводит:

UTC: Thu Feb 21 18:03:23 MST 2019
Local: Fri Feb 22 01:03:23 MST 2019

Вопросы:

  • Часовой пояс по умолчанию, установленный для моей системы, - MST, то есть UTC-7: 00,Похоже, что на самом деле это добавление 7 часов к времени UTC - почему это так?

  • Кроме того, он думает, что оба времени в MST времени.Я думал, что .withZoneUTC() решит это.Почему он так думает?

  • Является ли этот метод «лучшим» для этого (при условии, что эти проблемы могут быть исправлены)?

1 Ответ

0 голосов
/ 24 февраля 2019

Я делаю это шаг за шагом:

  1. dateParser.parseDateTime("2019-02-22T01:03:23Z") дает вам 22 февраля в 01:03 UTC, как и ожидалось (тот же момент времени, что и 21 февраля в 18:03 по смещению -07:00).
  2. dateTime.toLocalDateTime() отбрасывает информацию о смещении UTC, поэтому вы получите 22 февраля в 01:03 без информации о часовом поясе.LocalDateTime - это дата и время дня без информации о часовом поясе, поэтому не соответствует ни одному моменту времени.
  3. dateTime.toDate() дает вам тот же момент времени, что и 22 февраля в 01:03.UTC без смещения или информации о часовом поясе.Date, несмотря на то, что его имя как-то противоположно LocalDateTime: это момент времени, но он не соответствует определенному часу дня.
  4. "UTC: " + dateTime.toDate() добавляет Date к строке.Для этого неявно вызывается Date.toString, чтобы получить строку для добавления к первой строке.Date.toString использует местный часовой пояс для рендеринга строки (такое поведение многих смущает).Таким образом, полученный вами момент времени печатается как Thu Feb 21 18:03:23 MST 2019, который является точным моментом времени и преобразуется только в стандартное горное время.
  5. localDateTime.toDate() проблематично.Вы говорите, что хотите преобразовать дату и время в определенный момент времени.LocalDateTime решает эту проблему, используя местный часовой пояс, поэтому вы получаете момент времени, равный 22 февраля в 01:03 MST (то же время, что и 08:03 UTC).
  6. "Local: " + localDateTime.toDate() снова вызывает toString и использует MST для рендеринга строки.

Похоже, что на самом деле добавление 7 часов к времени UTC - почему это так?

Поскольку вы отбрасываете информацию о том, что дата и время были в UTC, а затем интерпретируете их в формате MST.

Кроме того, он считает, что оба времени указаны в времени MST.... Почему он так думает?

Это не так.Это просто Date.toString действует сбивающе с толку.

Является ли этот метод «лучшим» для этого (при условии, что эти проблемы можно исправить)?

Если вы пишетеновый код, лучше использовать java.time, современный Java-интерфейс даты и времени.Если вы уже использовали Joda-Time, можно разработать хорошее решение с Joda-Time, и остается открытым вопрос, хотите ли вы перейти на java.time и когда.

У меня нет опытаJoda-Time, но вот фрагмент кода, использующий java.time на тот случай, если вы хотите, чтобы:

    String systemUtcString = "2019-02-22T01:03:23Z";
    Instant pointInTime = Instant.parse(systemUtcString);
    ZonedDateTime denverDateTime = pointInTime.atZone(ZoneId.of("America/Denver"));
    System.out.println(denverDateTime);

2019-02-21T18: 03: 23-07: 00 [Америка / Денвер]

В любом случае избегайте java.util.Date, если можете.Только если вам необходим Date для устаревшего API, который вы не можете изменить или не хотите изменять прямо сейчас, выполните преобразование перед вызовом этого API.В этом случае помните, что Date не имеет часового пояса, поэтому нет необходимости преобразовывать в MST перед преобразованием в Date.

    Date oldfashionedDateObject = Date.from(pointInTime);
    System.out.println(oldfashionedDateObject);

Чт 21 февраля 18:03: 23 MST 2019

Цитата

Обратите внимание, что Joda-Time считается в значительной степени «законченным» проектом.Никаких серьезных улучшений не планируется.При использовании Java SE 8 перейдите на java.time (JSR-310).

(с домашней страницы Joda-Time)

Ссылки

...