Я знаю, что есть похожие вопросы, но я хотел прояснить, в чем именно проблема.
В основном я пытаюсь сохранить дату в своей базе данных Oracle. Я хочу, чтобы он хранился по всемирному координированному времени. Столбец в базе данных - это TIMESTAMP, я не сохраняю информацию о часовом поясе.
Глядя на класс поддержки JodaTime Hibernate PersistentDateTime, кажется, что метод nullSafeGet () просто вызывает DateTime.toDate (), который возвращает java.util.Date. Это дата, сохраненная в базе данных.
Я не понимаю ... почему getDate () не сохраняет часовой пояс существующего DateTime? Я отправляю ему DateTime (скажем, 17:00) в UTC, и после вызова getDate () он переключается на мой часовой пояс, CET (18:00). Я хочу сохранить 17:00, а не 18:00.
Я понимаю, что это (вероятно) получение TimeZone из среды, в которой я запускаю Java, и что одна из возможностей - изменить это с помощью параметра командной строки. Но я не хочу этого делать, к тому же мне все равно не разрешено работать на производственной машине.
Моя текущая идея состоит в том, чтобы реализовать класс, который расширяет PersistentDateTime и переопределяет метод nullSafeGet (), чтобы он поддерживал часовой пояс передаваемого ему DateTime. Не знаете точно, как это сделать ... возможно, в API JodaTime есть метод, который делает это элегантно?
Во всяком случае, мне было просто любопытно, удивлен ли кто-нибудь еще таким поведением или это только я. И хорошая ли моя идея или есть ли у кого-то получше. Изменение серверов (приложения или базы данных) или другой конфигурации не является вариантом, мне нужно исправить это с помощью кода.
ИЗМЕНИТЬ
Ради потомков и чтобы ответить полезным комментаторам, я хотел бы прояснить, в чем конкретно заключалась моя проблема.
Я думал, что проблема в том, что мой сервер приложений и мой сервер db имеют разные часовые пояса. Оказывается, проблема не в этом. Проблема скорее в том, что сервер приложений или JVM имеет другой часовой пояс, чем тот, который я использую в своем приложении. Позволь мне объяснить.
Мое веб-приложение управляет событиями. У событий есть дата начала и окончания. Это столбцы TIMESTAMP (без часового пояса) в базе данных Oracle. Кроме того, в приложении вы должны указать, какой часовой пояс вы используете. Это не зависит от часового пояса, используемого сервером приложений (а затем JVM) или сервером базы данных.
Но, конечно, у сервера приложений есть есть часовой пояс. В моем случае это CST, центральное стандартное время (GMT-6). Проблема возникает, когда часовой пояс, используемый в приложении, не совпадает с часовым поясом, используемым на уровне JVM. В моем случае часовой пояс, определенный в приложении, - EST, Eastern Standard Time (GMT-5).
Так что же происходит? Что происходит, я создаю событие из панели веб-администратора, например:
- Дата начала: 15 января 2014 г., 09:00
- Дата окончания: 20 января 2014 г., 23:00
Эти даты создаются с использованием Joda DateTime и им назначается правильный часовой пояс (с помощью DateTime.withZoneRetainFields ()), а именно тот, который я использую в приложении, EST. Итак, мое событие выглядит так:
- Название события: Событие 1
- Дата начала: 15.01.2014 09:00 EST
- Дата окончания: 20.01.2014 23:00 EST
Все идет нормально. Однако, когда я сохраняю его, даты сохраняются следующим образом:
- Дата начала: 15.01.2014 08:00
- Дата окончания: 20.01.2014 22:00
Что случилось? Произошло то, что, поскольку сервер приложений / JVM работает в CST, из обеих дат был вычтен час. Я думал, что это ошибка, но, как полагают комментаторы, это особенность. Драйверы JodaTime Hibernate просто вызывают DateTime.toDate (), который создает java.util.Date, который сам по себе не имеет часового пояса, но автоматически меняет час в соответствии с часовым поясом, используемым JVM.
Как мне этого избежать? Что ж, я мог бы запустить JVM с параметром -Duser.timezone и убедиться, что он всегда совпадает с часовым поясом, используемым в приложении. Это один из вариантов.
Еще я мог бы сделать, вместо того, чтобы избежать проблемы, поработать с ней. Другими словами, на уровне Hibernate / базы данных всякий раз, когда я загружаю событие, убедитесь, что полям даты начала и окончания назначен часовой пояс, определенный приложением, и, таким образом, часы будут преобразованы обратно в часовой пояс, используемый в приложении. Таким образом, даже если они сохранены как 08:00 и 22:00, в приложении они будут отображаться как 09:00 и 23:00. Это, очевидно, лучшее и более точное решение. Но я просто не уверен, стоит ли это всей работы. Я видел различные способы сделать это с помощью Hibernate в Интернете - с использованием типа доступа к свойству или настраиваемого типа пользователя Hibernate. Не уверен, работают ли они должным образом или нет, и кажется, что это много работы и очень навязчиво. Мне нужно перейти от использования DateTime к Calendar (я думаю, не уверен) и / или сделать специальные сопоставления в моем POJO.
По правде говоря, у нас есть java.util.Dates по всему приложению, и во многих случаях просто выполняется new Date () для их создания без учета часового пояса. Все они в конечном итоге должны быть изменены на DateTime и явно созданы с использованием часового пояса, определенного приложением.
Но это большая работа. На данный момент я решил просто использовать параметр -Duser.timezone и посмотреть, как это получится. Опять же, не лучшее решение, но я думаю, что пока оно отвечает нашим потребностям.
Большое спасибо всем комментаторам за то, что они «открыли мне глаза».