Почему я не должен использовать date4j вместо joda java.util.Calendar или jsr 310?

Недавно я наткнулся на date4j, чрезвычайно простую библиотеку (по сути, один класс) для работы с даты в Java. Концептуально мне очень нравится «идея» date4j. На самом деле, прочитав и весь основной сайт, и документацию в javadoc, я практически согласен со всем изложенным.

Теперь может быть несколько причин, по которым я не должен использовать date4j - ошибки, производительность, отсутствие пользователей и т. д. Я не спрашиваю об этом. Я спрашиваю, концептуально, что не так с идеей date4j (для большинства приложений)? Конечно, могут быть некоторые приложения, которым нужно что-то вроде joda или threeten, но я считаю, что их меньшинство.

Обычный совет, который люди дают пользователям, имеющим дело с датами/временем (почти все, кто пишет Java-приложение), выглядит примерно так:

  • Используйте joda-time вместо java.util.Calendar
  • Настройте свой веб-сервер на UTC
  • Установите сервер базы данных в UTC
  • Храните дату и время в формате UTC

На самом деле, последние три пункта иллюстрируют проблемы с текущей ментальной моделью, с которой сталкиваются люди при работе с датами. Люди пытаются управлять часовыми поясами как на уровне приложения, так и на уровне базы данных (не говоря уже о том, что ORM-фреймворки добавляют еще один уровень абстракции, что еще больше усложняет ситуацию).

Вы не должны делать эти вещи. Например, если вы используете java.util.Calendar и манипулируете временем в определенном пользователем часовом поясе:

Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
c.set(Calendar.YEAR, 2011);
c.set(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, 1);
c.set(Calendar.HOUR_OF_DAY, 3);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);

Это представляет собой «мгновение» во времени независимо от часового пояса. Вы должны быть в состоянии сохранять это время в базе данных и из нее, не беспокоясь о каких-либо «преобразованиях». Не имеет значения, находится ли база данных в часовом поясе Шанхая, а веб-сервер — в часовом поясе Лос-Анджелеса — независимо от того, момент времени один и тот же.

Одна проблема заключается в том, что некоторые базы данных пытаются управлять часовыми поясами для вас (я смотрю на вас, Postgres! grr!) и, что еще хуже, поведение на уровне драйвера JDBC зависит от поставщика - т.е. PreparedStatement.setDate/getDate.

Ментальная модель, которую использует date4j, кажется, избавляет от всей путаницы. Например, явное принудительное использование для указания часового пояса при вызове now(). На сайте есть несколько очень хороших рекомендаций по использованию библиотеки (эти вещи я уже делал в своем собственном приложении ранее), например:

  • не используйте тип базы данных, который пытается управлять часовыми поясами
  • сохранить часовой пояс в виде отдельного столбца (при необходимости)

Почему все больше людей не используют такую ​​библиотеку, как date4j?


person nogridbag    schedule 25.08.2011    source источник


Ответы (2)


Я никогда не смотрел на date4j до сих пор, но я прочитал документацию, и у меня есть одна конкретная проблема и одно мнение о том, что с ней не так.

Во-первых, конкретная проблема. Он не поддерживает часовой пояс внутри. Таким образом, существует двусмысленность по поводу перехода на летнее время. Рассмотрим переходное воскресенье, когда 1:59:59 (по восточному поясному времени) становится 1:00:00 (по восточному поясному времени). Ясно, что в этот день говорить 1:30 ночи двусмысленно. Это время происходит дважды. Так что неоднозначно следующее

new DateTime("2011-11-06 01:30:00")

Во-вторых, мое мнение. Проблема с Date заключалась в том, что он не поддерживал часовой пояс. К тому времени, как появился Календарь, ущерб был уже нанесен. Кроме того, сам Calendar не сделал себе никаких одолжений, будучи изменчивым. Но по сути решение должно включать не только момент, но и то, где оно было воспринято — часовой пояс, культура, местность и тому подобное. Затем их необходимо поддерживать вместе с моментом, когда они сохраняются в базе данных, сериализуются, передаются и т. д. Тот же самый личный принцип заставляет меня смиренно предположить, что даже xsd:dateTime терпит неудачу, потому что он просто позволяет выражать дату и время относительно UTC, он не имеет никаких условий, чтобы указать, например, соблюдается ли переход на летнее время.

person Dilum Ranatunga    schedule 25.08.2011
comment
Кажется, есть двусмысленность в обоих направлениях. Например, если вы пишете приложение календаря, такое как Google Calendar, и пользователь планирует событие в 1:30 ночи, какой момент вы сохраняете в базе данных? - person nogridbag; 25.08.2011
comment
Я не говорю, что сейчас кто-то справляется идеально, просто говорю, что нет надежды справиться с проблемой, не сохраняя дополнительные детали в экземплярах DateTime. - person Dilum Ranatunga; 25.08.2011
comment
Кстати, я с вами не спорю. Я считаю, что ваш ответ правильный, но буду ждать, пока другие напишут. Если вы делаете что-то простое, например регистрируете конкретный момент, когда произошло какое-то событие - было опубликовано сообщение, элемент был удален, то кажется, что date4j может не работать по указанной вами причине. - person nogridbag; 25.08.2011
comment
Этот новый DateTime(2011-11-06 01:30:00) не является двусмысленным. Это эквивалентно новому DateTime(2011-11-06 01A:30:00), а второй раз, когда он снова 01:30, является новым DateTime(2011-11-06 01B:30:00), однако я не уверен где нужно поставить А и Б. - person Angel O'Sphere; 25.08.2011
comment
О, теперь я понимаю, что ты имел в виду. Этот DateTime не учитывает високосные часы согласно документации: ■ игнорирует все нелинейности: летние часы, високосные секунды и переход от юлианского календаря к григорианскому. Это довольно глупо и делает его непригодным именно в тех случаях, когда я не хочу использовать java.util.Date. - person Angel O'Sphere; 25.08.2011
comment
Да, в основе дела - календарь и время сложны. Там нет обойти это. В то же время мы не можем ожидать, что все будут экспертами по темам. Таким образом, API-интерфейсы должны быть предписывающими по своей природе — (ненавязчиво) заставлять пользователей следовать шаблонам, которые решают проблемы, лежащие в основе. В частности, такие вещи, как високосные секунды, неинтересны большинству людей, даже при расчете временных интервалов. Но из-за отсутствия профилей предпочтений и внутренней поддержки сложностей страдает либо код, либо результат. - person Dilum Ranatunga; 25.08.2011

Прошло четыре года, и я столкнулся с этим вопросом. Для меня проблема №1 с date4j — это баги. Я знаю, что вы специально не спрашивали об этом, но это серьезная проблема.

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

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

person kralyk    schedule 01.07.2015
comment
Четыре года спустя мы, наконец, можем начать использовать новый Java 8 Date and Time API... :) Возможно, еще через 4 года я смогу использовать новые классы изначально в своем проекте Grails, не изменяя свое собственное сопоставление пользовательских типов или используя сторонняя библиотека сопоставления... - person nogridbag; 01.07.2015
comment
Для информации: Date4J теперь находится на GitHub, где можно сообщать о проблемах. github.com/johanley/date4j - person Chris Knight; 09.01.2016