Joda-Time
Що стосується додавання залежності, я боюся, що java.util.Date & .Calendar насправді настільки поганий, що перше, що я роблю до будь-якого нового проекту, - це додати бібліотеку Joda-Time. У Java 8 ви можете використовувати новий пакет java.time, натхненний Joda-Time.
Ядром Joda-Time є DateTimeклас. На відміну від java.util.Date, він розуміє призначений йому часовий пояс ( DateTimeZone). При перетворенні з juDate призначте зону.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );
LocalDate
Один із способів переконатися, що два дати-раз приземляються на одну і ту ж дату - це перетворення на LocalDateоб’єкти.
Ця конверсія залежить від призначеного часового поясу. Для порівняння LocalDateоб'єктів вони повинні бути перетворені з однією зоною.
Ось невеликий корисний метод.
static public Boolean sameDate ( DateTime dt1 , DateTime dt2 )
{
LocalDate ld1 = new LocalDate( dt1 );
// LocalDate determination depends on the time zone.
// So be sure the date-time values are adjusted to the same time zone.
LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) );
Boolean match = ld1.equals( ld2 );
return match;
}
Краще було б ще одним аргументом, що вказує часовий пояс, а не передбачає використання часового поясу першого об'єкта DateTime.
static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 )
{
LocalDate ld1 = new LocalDate( dt1.withZone( zone ) );
// LocalDate determination depends on the time zone.
// So be sure the date-time values are adjusted to the same time zone.
LocalDate ld2 = new LocalDate( dt2.withZone( zone ) );
return ld1.equals( ld2 );
}
Струнне представлення
Інший підхід полягає у створенні рядкового подання частини дати кожної дати, а потім порівняння рядків.
Знову ж таки, призначений часовий пояс є вирішальним.
DateTimeFormatter formatter = ISODateTimeFormat.date(); // Static method.
String s1 = formatter.print( dateTime1 );
String s2 = formatter.print( dateTime2.withZone( dt1.getZone() ) );
Boolean match = s1.equals( s2 );
return match;
Проміжок часу
Узагальнене рішення - визначити проміжок часу, а потім запитати, чи містить цей проміжок ціль. Цей приклад код знаходиться в Joda-Time 2.4. Зауважте, що класи, пов'язані з "опівночі", застарілі. Замість цього використовуйте withTimeAtStartOfDayметод. Joda-Time пропонує три класи, які представляють проміжок часу різними способами: інтервал, період та тривалість.
Використовуючи підхід "напіввідкрито", коли початок проміжку є інклюзивним, а закінчення ексклюзивним.
Часовий пояс цілі може бути різним, ніж часовий пояс інтервалу.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone );
DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay();
DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay();
Interval interval = new Interval( start, stop );
boolean containsTarget = interval.contains( target );
java.time
Java 8 і пізніші версії поставляються з java.time . Натхненний Joda-Time, визначений JSR 310, і розширений проектом ThreeTen-Extra. Дивіться Підручник .
Творці Joda-Time доручили нам усі перейти на java.time, як тільки зручно. Тим часом Joda-Time продовжується як активно підтримуваний проект. Але очікуйте, що майбутня робота відбуватиметься лише у java.time та ThreeTen-Extra, а не Joda-Time.
Підводячи підсумок java.time у двох словах… InstantМомент на часовій шкалі в UTC. Застосуйте часовий пояс ( ZoneId), щоб отримати ZonedDateTimeоб’єкт. Для переходу від тимчасової шкали, щоб отримати неясне невизначене уявлення про дату-часу, використовувати «локальні» класів: LocalDateTime, LocalDate, LocalTime.
Логіка, обговорювана в розділі Joda-Time у цій відповіді, стосується java.time.
Старий клас java.util.Date має новий toInstantметод перетворення в java.time.
Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.
Визначення дати потребує часового поясу.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
Ми застосовуємо цей об’єкт часового поясу до параметра Instanta ZonedDateTime. Виходячи з цього, ми отримуємо значення (а LocalDate) лише для дати, оскільки нашою метою є порівняння дат (а не годин, хвилин тощо).
ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );
Зробіть те саме з другим java.util.Dateоб'єктом, який нам потрібен для порівняння. Я просто використаю замість цього поточний момент.
ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );
Використовуйте спеціальний isEqualметод для тестування на однакове значення дати.
Boolean sameDate = localDate1.isEqual( localDate2 );