@DateTimeFormat в Spring выдает ошибку на один день

#spring #datetime #spring-mvc #format

#весна #datetime #spring-mvc #формат

Вопрос:

В настоящее время я использую @DateTimeFormat в объекте домена следующим образом:

 @DateTimeFormat(pattern = "MM/dd/yyyy")
private Date startDate = new Date();
  

В контроллере Spring MVC я публикую сегодняшнюю дату: 19.10.2011 с помощью средства выбора даты пользовательского интерфейса jQuery, и я подтверждаю, что это отправляется в качестве параметра HTTP Post с помощью firebug следующим образом:

 startDate=10/19/2011
  

К сожалению, как только он попадает на Spring на сервере, он сохраняет дату как 18.10.2011 — возникает ошибка на один день.

В моем коде нет ничего, что даже отдаленно касалось бы даты — никаких вычислений или чего-либо еще не происходит в отношении этой даты.

Есть ли что-то в @DateTimeFormat, о котором я должен знать?

Может ли что-то в гибернации быть ответственным за изменение даты?

Я также просматриваю мою базу данных для этого приложения. Я сохраняю другую дату, creationDate которая называется фактической меткой времени и отличается от введенной пользователем. В большинстве случаев даты совпадают, но клиент хотел иметь возможность устанавливать их по-другому, чтобы это было то startDate , для чего нужно.

 Start Date              Creation Date (actual timestamp, not user input)
2011-04-17 19:00:00     2011-04-17 21:32:27
2011-04-18 19:00:00     2011-04-18 21:14:01
2011-04-20 19:00:00     2011-04-20 23:06:47
2011-04-26 19:00:00     2011-04-26 23:24:34
2011-04-28 19:00:00     2011-04-28 20:07:06
2011-05-01 19:00:00     2011-05-02 13:35:37
2011-06-21 19:00:00     2011-06-22 15:06:36
2011-07-28 19:00:00     2011-07-29 15:32:35
2011-09-03 19:00:00     2011-09-04 13:11:45
2011-10-11 19:00:00     2011-10-12 11:45:14
2011-10-11 19:00:00     2011-10-12 11:49:55
2011-10-18 19:00:00     2011-10-19 02:20:43
  

Сначала кажется, что это ошибка, запущенная в мае, но потом я понял, что дата верна, если она превышает 19:00:00, и она отключена, если она меньше 19:00:00.

Я ненавижу Java:(

Проблема, похоже, возникает, когда Spring создает заданную дату 10/19/2011 — похоже, она переводит этот пользовательский ввод и форматирует его 2011-10-18 19:00:00 .

Какое самое простое решение?

Спасибо

Ответ №1:

Мне кажется очень вероятным, что на самом деле это вопрос часовых поясов. Date Объект представляет момент времени — я подозреваю, что если вы посмотрите на точное значение, которое у вас есть (например, в UTC, чтобы все было ясно), вы получите лучшее представление о том, что происходит. Скорее всего, там, где вы видите «18.10.2011», вы интерпретируете его в другом часовом поясе.

Если Spring поддерживает преобразование в типы времени Joda, я бы предложил использовать это вместо этого — тогда вы можете использовать LocalDate , что действительно означает дату, а не момент времени.

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

1. Да, вы можете быть правы. Я не использую JodaTime, потому что он часто создает всевозможные проблемы с зависимостями в режиме гибернации. Мне не нужно делать никаких сложных вычислений, поэтому я избегал упрощения своих зависимостей. Как я могу это исправить, не используя время joda? Просто установите время так, чтобы оно всегда превышало 19:00:00?

2. @egervari: Трудно предложить исправление, не зная, в чем проблема. Вы отредактировали свой пост, чтобы показать «дату начала», но не показывая, как вы это получили. Например, может случиться так, что, используя UTC везде, вы решаете все свои проблемы.

3. Дата начала не является вычислением. Это пользовательский ввод. Система устанавливает текущую дату по умолчанию, и это дата, которая в конечном итоге была сохранена. Все в этой части приложения тривиально — контроллер, уровень обслуживания и dao. Я использую стандартный режим гибернации для его хранения, и я даже не устанавливаю тип — так что это, по сути, тип даты по умолчанию в режиме гибернации. Все по умолчанию — вот что я говорю. Это очень тривиально. Надеюсь, мне не нужно все преобразовывать в время Joda. Хотя я понимаю, что это лучше, я не хочу тратить столько времени.

4. Кроме того, мое исправление, которое я отредактировал, не работает на сервере… поэтому я бы предпочел не использовать его. Какое самое простое исправление я могу сделать, чтобы заставить Spring создать дату, которая не вызывает эту одноразовую ошибку? Очевидная проблема находится внутри Spring, а не в моем коде. @DateTimeFormat, похоже, является виновником.

5. @egervari: Я не думаю, что это вообще очевидно, в чем проблема. Вы усердно распределяли вину повсюду, но без фактической отладки того, что происходит, мы действительно не можем сказать, что не так. Возможно , Spring не устанавливает правильный часовой пояс для SimpleDateFormat того, который он использует для анализа. Возможно , в Linux JDK есть ошибка, хотя это кажется менее вероятным. Даже если проблема может быть не в коде вашего приложения, вы вызвали значительную путаницу, не показав код, который вы использовали для диагностики проблемы. (Продолжение)

Ответ №2:

Я обнаружил, что запуск вашей JVM с вашим местным часовым поясом, указанным в аргументах, решает эту проблему. Для меня это было просто добавление этой строки в конфигурацию запуска:

 -Duser.timezone="Asia/Dhaka"