Что случилось с API Java Date & Time?

Очень часто я сталкиваюсь с отрицательной обратной связью по Java Date и другим классам, связанным с датой. Будучи разработчиком .NET, я не могу полностью (без использования их) понять, что на самом деле не так с ними.

Может ли кто-нибудь пролить свет на это?

Ответ 1

А, класс Java Date. Возможно, один из лучших примеров того, как не делать что-либо на любом языке, где бы то ни было. С чего начать?

Чтение JavaDoc может заставить думать, что у разработчиков действительно есть хорошие идеи. Далее идет различие между UTC и GMT, несмотря на то, что разница между ними - это в основном прыжки секунд (которые происходят довольно редко).

Тем не менее, проектные решения действительно лежат в основе любой мысли о том, чтобы быть хорошо разработанным API. Вот некоторые из любимых ошибок:

  • Несмотря на то, что он был разработан в последнее десятилетие тысячелетия, он оценивает годы как две цифры с 1900 года. В результате этого банального решения буквально миллионы обходных решений, делающих 1900+ (или 1900-) в Java-мире.
  • Месяцы индексируются нулями, чтобы удовлетворить впечатляюще необычный случай наличия массива месяцев и не жить с тринадцатым массивом элементов, первый из которых содержит null. В результате у нас 0,11 (и сегодня это 11-й месяц 109-го года). Есть аналогичное число ++ и - в месяцы, чтобы преобразовать в строку.
  • Они изменяемы. В результате, в любое время, когда вы хотите дать дату назад (например, как структура экземпляра), вам нужно вернуть клон этой даты вместо самого объекта даты (так как иначе люди могут мутировать вашу структуру).
  • Calendar, предназначенный для "исправления" этого, фактически совершает те же ошибки. Они все еще изменяемы.
  • Date представляет a DateTime, но для того, чтобы отложить до тех, кто на землях SQL, есть еще один подкласс java.sql.Date, который представляет собой один день (хотя без связанного с ним часового пояса).
  • Нет TimeZone, связанного с Date, поэтому диапазоны (например, "целый день" ) часто представлены как полночь-полночь (часто в какой-то произвольный часовой пояс).

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

Ответ 2

JSR 310, который вытеснил старые классы времени с java.time в Java 8, оправдывает себя в исходном JSR следующим образом:

2.5 Какую потребность сообщества Java будет решать предлагаемая спецификация?

В настоящее время Java SE имеет два отдельных API-интерфейсы даты и времени - java.util.Date и java.util.Calendar. Оба API последовательно описывается как трудно использование разработчиками Java в блогах и форумы. Примечательно, что оба используют нулевой индекс в течение нескольких месяцев, что является причиной многих ошибок. Календарь также пострадал от много ошибок и проблем с производительностью лет, прежде всего из-за хранения его состояние двумя разными способами внутри.

Одна классическая ошибка (4639407) предотвращена определенные даты от создания в Объект календаря. Последовательность кода может быть написано, что может создать дата в несколько лет, но не в других, имеющих эффект предотвращения некоторых пользователи вводят правильные даты рождения. Это было вызвано Календарный класс, позволяющий переход на летнее время на один час летом, когда исторически это было плюс 2 часа вокруг времени вторая мировая война. Хотя эта ошибка теперь зафиксировано, если в какой-то момент будущее страна выбрала переход на летнее время плюс три часа летом, затем Класс календаря снова будет нарушен.

Существующий API Java SE также страдает в многопоточных средах. Известно, что неизменяемые классы по сути поточно-безопасные, поскольку их состояние невозможно изменить. Однако, как дата, так и Календарь изменен, что требует программистам рассмотреть вопрос о клонировании и потоки явно. В дополнение отсутствие безопасности потока в DateTimeFormat не широко известен, и было причиной многих трудностей, отслеживать проблемы с потоками.

Как и проблемы с классы, которые Java SE имеет для datetime, он не имеет классов для моделирования других концепции. Даты, не относящиеся к часам или времени, продолжительности, периодов и интервалы не имеют представления класса в Java SE. В результате разработчики часто используют int для представления длительность времени, с javadoc указав блок.

Отсутствие всеобъемлющей даты и временная модель также приводит к операции сложнее, чем они должно быть. Например, вычисление количество дней между двумя датами является особенно трудной проблемой при присутствует.

Этот JSR будет решать проблему полная модель даты и времени, включая даты и время (с без часовых поясов), продолжительности и периоды времени, интервалы, форматирование и разбор.

Ответ 3

  • Примерами даты являются изменчивые, что почти всегда неудобно.
  • Они имеют двойную природу. Они представляют собой временную метку и календарную дату. Оказывается, это проблематично при выполнении расчетов по датам.
  • Числовые представления данных календаря во многих случаях являются интуитивно понятными. Например: getMonth() основано на нуле, getYear() составляет 1900 (т.е. 2009 год представлен как 109).
  • В классе Date отсутствуют функции, которые вы ожидаете от нее.

Ответ 4

Я чувствую к вам... как бывший .NET-программист, я задавал одни и те же вопросы, API времени в .NET(timespans, перегрузка оператора) очень удобен.

Во-первых, чтобы создать определенную дату, вы используете либо устаревший API, либо:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

Чтобы вычесть день, вы делаете злые вещи, такие как

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

или хуже

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

Чтобы узнать, сколько времени прошло между двумя датами (в днях/неделях/месяцах)... это становится еще хуже

Однако DateUtils из apache (org.apache.commons.lang.time.DateUtils) предлагает некоторые удобные методы, и я обнаружил, что использую только их в последнее время

Как писал Брабстер, Joda Time также является хорошей внешней библиотекой, но apache кажется более "распространенным", чем что-либо еще...

Ответ 5

Я считаю Java Date API пригодным для использования, если честно. Большинство проблем, которые я видел и слышал, касаются многословия, необходимо задействовать несколько классов, чтобы сделать что-нибудь полезное (Calendar, Date, DateFormat/SimpleDateFormat) и отсутствие простых аксессуаров, таких как getDayOfWeek().

Joda Time - это уважаемый альтернативный API на Java, а в разделе Why Why Joda Time дается еще несколько аргументов в пользу того, почему это жизнеспособная альтернатива, которая может представлять интерес.