Статьи

Способы сравнения объектов Date в Java


Посмотрим правде в глаза, сопоставление объектов Date в Java является сложным и подверженным ошибкам.
Это имеет место в стандартном коде, но также и в тестируемом коде, где мы регулярно должны создавать объекты Date, которые указывают в определенный момент времени, чтобы быть нашей ссылкой для сравнения.

Старый добрый путь не рекомендуется

В тестовом коде я не сомневаюсь в использовании устаревших методов. Итак, я использовал старый
конструктор Date для инициализации дат:

Date date = new Date(112, 5, 3);

  Pro: это сжато. Против: это действительно не интуитивно понятно, и вам нужно хорошее знание API Java, чтобы знать, что первый параметр — это год минус 1900, а второй — количество месяцев (начиная с 0 для января). Почти неожиданно узнать, что последний параметр просто … день месяца.

Канонический путь

Начиная с Java 1.1,
Calendar был введен в Java API для разделения между моментом времени (дата) и его представлением в конкретной ссылке (календарь). Следующий фрагмент — наивный способ получить тот же результат, что и выше.

Calendar calendar = Calendar.getInstance();

calendar.set(YEAR, 2012);
calendar.set(MONTH, JUNE);
calendar.set(DAY_OF_MONTH, 3);

  Это не только более многословно, но и ошибка: часы, минуты и остальные не равны 0 (в зависимости от точного времени создания календаря), поэтому использование equals () здесь вернет false. Вот правильный код:

Calendar calendar = Calendar.getInstance();

calendar.set(YEAR, 2012);
calendar.set(MONTH, JUNE);
calendar.set(DAY_OF_MONTH, 3);
calendar.set(HOUR_OF_DAY, 0);
calendar.set(MINUTE, 0);
calendar.set(SECOND, 0);
calendar.set(MILLISECOND, 0);

  Это побеждает цель краткости, чтобы сказать наименее 😉

Apache Commons Lang

Apache Commons издавна предоставляет различные вспомогательные библиотеки, которые помогают разрабатывать на Java. Одной из таких библиотек является
Apache Commons Lang , целью которой является предоставление кода, который заслуживает того, чтобы быть частью Java API. В нашем случае
класс
DateUtils позволил нам сократить предыдущий код, сохранив его читабельность:

Calendar calendar = Calendar.getInstance();

calendar.set(YEAR, 2012);
calendar.set(MONTH, JUNE);
calendar.set(DAY_OF_MONTH, 3);
calendar = DateUtils.truncate(calendar, DAY_OF_MONTH);

Более того, DateUtils позволяет нам работать непосредственно с объектами Date, чтобы сделать возможной также следующую альтернативу:

Date date = new Date();

date = DateUtils.setYears(date, 2012);
date = DateUtils.setMonths(date, JUNE);
date = DateUtils.setDays(date, 3);
date = DateUtils.truncate(date, DAY_OF_MONTH);

Обратите внимание, что он оставляет параметры нетронутыми, обеспечивая неизменность, дорогую сторонникам функционального программирования. Pro: мы используем стандартный Java API. Против: нет. И все же, разве полноценный DSL не будет чувствовать себя более правильным?

Время йода

Последний вариант — использовать
Joda Time , который призван заменить дату и календарь. Он также породил
JSR-310 «новый и улучшенный API даты и времени для Java», который должен быть частью Java 8 (изначально он был запланирован для Java 7). Целая статья (или даже мини-руководство) может быть посвящена Joda Time. Для нашей нынешней озабоченности следующий фрагмент может выгодно заменить наш оригинальный:

DateMidnight dm = new DateMidnight(2012, 6, 3);

  Возвращаясь к исходной точке, кажется: ясно и кратко. И все же, параметры говорят сами за себя, нет реальной необходимости регулярно проверять JavaDocs, чтобы увидеть, как инициализировать год. Кроме того, семантика имени класса понятна. Наконец, метод toDate () позволяет нам соединиться со стандартным Java API.

Вывод

Вывод ваш. Что касается меня, я регулярно использую Apache Commons Lang, но в эти дни я склоняюсь к Joda Time. Код доступен
здесь как архив проекта Eclipse / Maven. Примечание: если вам нужно работать с рабочими днями, я недавно узнал об
ObjectLab Kit . Я еще не использовал его, и отзывы приветствуются.