Аннотация от переводчика
Статья вкратце затрагивает трудности работы с датами в Яве на простом примере сравнения дат. Рассчитана для начинающих программистов которые уже более менее знакомых с работой с датами в Java.Итак, давайте обрисуем проблему — сравнение объектов
Date в Java известный источник ошибок.Это появляется в стандартном коде, но также бывает и в тестирующем коде, где нам регулярно нужно создавать объекты
Date которые отмечают определенный момент времени на который потом будем ссылаться в сравнении.Старый добрый устаревший и не рекомендуемый путь
В тестирующем коде я не переживал что использую устаревшие (deprecated) методы. Поэтому я использовал старый конструктор Date чтобы инициализировать даты, после чего я сравнивал их с другим объектами дат через метод сравненияequals():Date date = new Date(112, 5, 3);
Date userCreatedDate = user.getCreatedDate();
if (userCreatedDate.equals(date)) { // Если даты равны…
// делаем что нибудь…
}
Преимущества: это лаконично. Недостатки: это весьма не очевидно и вам нужны хорошие знания Java API чтобы знать что первый параметр это год минус 1900 и второй это индекс месяца который начинается с ноля для Января. И это сюрприз когда вы узнаёте что последний параметр это просто… просто день месяца.Канонический способ
Начиная с Java 1.1 в Java API был добавлен классCalendar чтобы разделить момент во времени (т.е. дату) от её представления в специфическом справочнике (календарь). Следующий фрагмент кода (snippet) это способ получения такого же результата как выше.Calendar calendar = Calendar.getInstance(); calendar.set(YEAR, 2012); calendar.set(MONTH, JUNE); calendar.set(DAY_OF_MONTH, 3);
Это не только более многословно, тут также есть ошибка: часы, минут и остальное не равно нолю (берётся от момента непосредственного создания календаря), поэтому сравнение через
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);
Обратите внимание что он оставляет параметры нетронутыми, достигая неизменяемости (immutability) по принципа функционального программирования.
Преимущества: мы используем стандартное Java API.
Недостатки: да никаких. И ещё, не будет ли полностью своеобразный DSL казаться чем-то более подходящим?
Joda Time
Последний вариант это использование библиотеки Joda Time, которая нацелена стать заменой дляDate и Calendar. Она также породила JSR-310 — новый и улучшенный API для манипуляции с датой и временем, который должен стать частью Java 8 (он был изначально запланирован для Java 7). Joda Time стоит посвятить отдельную статью (или даже мини-руководство). Для наших текущих нужд следующий фрагмент кода может выгодно заменить наш изначальный:DateMidnight dm = new DateMidnight(2012, 6, 3);
Если сравнивать с первым примером, такой код кажется чище и лаконичней. И ещё, параметры самоописывающие, нет реальной нужды регулярно проверять JavaDocs чтобы узнать как инициализируется год. Кроме того, семантика имён классов ясна. И наконец, метод
toDate() даёт нам мост к стандартному Java API.Заключение
Вывод делайте сами. Лично я обычно использую Apache Commons Lang, но в последнее время склоняюсь к Joda Time. Архив с примерами кода доступен для скачивания тут в виде Maven проекта под Eclipse.Автор: Nicolas Fränkel
Оригинал Ways of comparing Date Objects in Java.
Комментариев нет:
Отправить комментарий