2013-08-30 2 views
1

У меня есть довольно неприятная проблема с некоторыми синтаксическими анализами даты и получением правильной даты/времени из моего форматирования. Вот код (сокращенный вариант) Thats делает форматированиеПроблема с часовым поясом Java с Joda Time

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd"); 
log.debug("Trying to convert {} using format {}.", val, "yyyy-MM-dd"); 
Date toDate = formatter.parseDateTime(inputText).toDate(); 
log.debug("Converted value to {}", toDate); 

Вот некоторый выход с неправильных значений. Часовой пояс здесь установлен на EDT. (Проверено с помощью команды date и/и т.д./МестноеВремя линке.

13:14:53.618 [http-bio-8080-exec-13] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd. 
13:14:53.619 [http-bio-8080-exec-13] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Sun Jul 07 20:00:00 EDT 2013 

Это работает на AWS-LINUX на Tomcat 7 с помощью OpenJDK 7. Мы имеем еще один экземпляр работает на AWS, и тот же код выдает этот :.

17:22:46.164 [http-bio-8080-exec-239] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd. 
17:22:46.165 [http-bio-8080-exec-239] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Mon Jul 08 00:00:00 UTC 2013 

Зонное на этой машине установлен в UTC

на моей локальной машине, выход тоже правильно (обратно EDT здесь работает оракулы JDK на OS X):

13:24:55.967 [ajp-bio-8009-exec-176] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd. 
13:24:56.089 [ajp-bio-8009-exec-176] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Mon Jul 08 00:00:00 EDT 2013 

Опять же, тот же код во всех трех местах. Я не могу для жизни понять, почему у нас есть пример, который не действует, как и все остальные. Я собираюсь добавить еще один отладочный вывод, чтобы попытаться сузить его, но на данный момент мне не повезло.

Кроме того, еще один интересный бит. Запуск вне Tomcat на машине, которая является неправильной, с тем же JDK и следующим кодом, который я получаю то, что ожидал:

DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd"); 
DateTime parseDateTime = f.parseDateTime("2013-07-08"); 
System.out.println(parseDateTime.toDate()); 

Выход:

Mon Jul 08 00:00:00 EDT 2013 

UPDATE

Это выглядит например, Joda не использует часовой пояс System default. Вот как я вывода данных:

log.debug("Using joda timezone of: {}", DateTimeZone.getDefault()); 
log.debug("Default timezone of: {}", TimeZone.getDefault()); 

И вот результат:

AbstractParamToObjectProvider - Using joda timezone of: UTC 
AbstractParamToObjectProvider - Default timezone of: sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]] 

Одна из этих вещей не совпадает с другой ... Любые идеи, почему?

РЕШЕНИЕ

Джон был в правильном направлении, с его ответом, но вот окончательный обыгрыш.

Как-то пользователь user.timezone был настроен на UTC, и Джода использовал это, в то время как TimeZone по умолчанию не был (используется системный часовой пояс). Для патча я сделал следующее:

DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); 

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

+0

Попробуйте распечатать часовой пояс анализируемого 'DateTime':' DateTime parsed = formatter.parseDateTime (inputText); System.out.println (parsed.getZone()); 'Кроме того, если вы анализируете дату, почему вы все равно разбираете ее в' DateTime', а не в LocalDate? –

+0

Кроме того, попробуйте распечатать 'DateTimeZone.getDefault' на каждой машине - интересно, не собирает ли это правильно, поэтому использует другой параметр по умолчанию, который имеет JDK. –

+0

@JonSkeet Это то, что мне интересно, и почему он делает это только в tomcat. Просто развернул некоторые изменения с дополнительной информацией об отладке (с выводом tz), так что посмотрим, что это говорит. –

ответ

3

Joda Время проходит через следующие этапы:

  • Используйте свойство user.timezone системы
  • Создать временную зону на основе идентификатора TimeZone.getDefault()
  • Падение назад к UTC

TimeZone.getDefault() может быть немного сложнее, хотя во многих случаях он также использует user.timezone.

Одним из вариантов было бы в явном виде установить часовой пояс по умолчанию для обоих TimeZone и DateTimeZone к UTC при запуске приложения вверх: для веб-серверов, это наиболее приемлемое значение по умолчанию для использования (хотя лично я предпочитаю, чтобы явно заявить часовой пояс, где это необходимо).

+0

Похоже, что свойство user.timezone вызывает проблему. Тем не менее, я понятия не имею, где это устанавливается, как для Tomcat (не может найти места, где он должен быть указан и фактически установлен). –

+0

Я согласен с советом Джона Скетса указать желаемый часовой пояс в вашем коде, а не зависеть от любого значения по умолчанию. Joda-Time предоставляет константу для UTC: 'DateTimeZone.UTC'. Например, 'DateTime dateTime = new DateTime (« 2013-07-08 », DateTimeZone.UTC); –

Смежные вопросы