Недавно я наткнулся на 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?