Joda-Time
Что касается добавления зависимости, я боюсь, что java.util.Date & .Calendar действительно настолько плохи, что первое, что я делаю в любом новом проекте, это добавляю библиотеку Joda-Time. В Java 8 вы можете использовать новый пакет java.time, вдохновленный Joda-Time.
Ядро Joda-Time - это класс DateTime
. В отличие от java.util.Date, он понимает свой назначенный часовой пояс (DateTimeZone
). При конвертации из j.u.Date присвойте зону.
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 framework. Вдохновленный 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" );
Мы применяем этот объект часового пояса к Instant
, чтобы получить 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 );