Почему «12:00», преобразованное в UTC, становится «11:00»?

#java #jodatime

#java #jodatime

Вопрос:

Я думал 2011-10-23 12:00:00 , что останется таким же, как UTC и то, что Converted date будет 2011-10-23 17:00:00 .

 DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dt = formatter.parse("2011-10-23 12:00:00");
LocalDateTime ldt = new DateTime(dt).withZone(DateTimeZone.UTC).toLocalDateTime();
LOGGER.warn("Original date: "   ldt.toDateTime().toDate().toString());
DateTime cvtldt = ldt.toDateTime(DateTimeZone.forID("-05:00"));
LOGGER.warn("Converted date: "   cvtldt.toLocalDateTime().toDateTime().toDate().toString());
 

Я не понимаю, почему результат равен минус одному часу?

 Original date: Sun Oct 23 11:00:00 BST 2011
Converted date: Sun Oct 23 11:00:00 BST 2011    
 

Комментарии:

1. Переход на летнее время или что-то в этом роде? (дикое предположение)

Ответ №1:

Вы используете Date.toString() which всегда использует местный часовой пояс. Посмотрите, как ваша строка содержит «BST»? По британскому летнему времени.

В идеале придерживайтесь только времени Joda столько времени, сколько сможете:

  • Разбор с помощью форматеров времени Joda
  • Не конвертируйте обратно Date , если вам не нужно
  • Не используйте Date.toString() , если вы можете этого избежать; вы не можете контролировать его формат.

Неясно, чего вы на самом деле пытаетесь достичь, но вы почти наверняка не хотите делать так много преобразований. Например, вы вызываете toLocalDateTime() followed by toDateTime() again — это означает, что он использует системный часовой пояс по умолчанию, после того как вы тщательно указали UTC в предыдущем преобразовании…

Ваш код содержит следующие преобразования (в этом порядке):

  • Строка для даты
  • Дата в DateTime
  • От даты и времени до даты и времени в UTC
  • DateTime в LocalDateTime (*)
  • LocalDateTime в DateTime
  • Дата Время Дата
  • Дата в строку
  • (Из результатов в *) LocalDateTime в DateTime
  • DateTime в LocalDateTime
  • LocalDateTime в DateTime
  • Дата Время Дата
  • Дата в строку

Как вы думаете, каковы шансы на то, что все эти преобразования будут как необходимыми, так и правильно заданными? 😉

Комментарии:

1. Мне нужно сохранить преобразованную дату в хранилище данных App Engine как Date объект — вот почему мне нужно преобразовать обратно в a java.util.Date — это единственный доступный тип данных. Я пытаюсь преобразовать дату клиента (местный часовой пояс) в эквивалент сервера (всегда UTC).

2. @zippy: Верно, это нормально, но вы должны сделать это с как можно меньшим количеством преобразований. Я предполагаю, что вы начинаете со строки — в каком часовом поясе она указана? Вам следует избегать всех преобразований, которые неявно используют часовой пояс по умолчанию, IMO — если вы хотите использовать часовой пояс по умолчанию, вы должны указать его явно.

3. Упс, вы редактировали свой комментарий в тот же момент. Вы говорите «местный часовой пояс» — локальный для чего? Это часовой пояс по умолчанию в системе, в которой выполняется ваш код?

4. Часовой пояс клиента отличается от одного пользователя приложения к другому.

5. Я пытаюсь сделать приблизительную оценку эквивалентной даты и времени сервера в UTC.

Ответ №2:

Оригинал изменился, потому что преобразование в UTC выполняется с учетом часового пояса хоста, поэтому оно должно измениться.

Преобразованный изменился, на самом деле это проблема метода доступа. Вы получаете базовое время, а модификатор сохраняется в другом поле.

Попробуйте перейти в режим отладки, и вы увидите, что после преобразования cvtldt имеет toString с модификатором.

Regards, Grzesiek