Разница между двумя датами в минутах - разные месяцы - Java
Я хочу найти разницу в минутах между 2 датами. Мой код работает хорошо, если 2 даты находятся в одном и том же месяце (и году), но кажется, что разница считает, что каждый месяц будет длиться 31 день, поэтому для дат:
2016-02-29 12:21
2016-03-1 12:21
Я получаю 4320 минут или 72 часа
за:
2016-04-30 12:21
2016-05-01 12:21
Я получаю 2880 минут или 48 часов
мой код, где d1 и d2 являются объектами Date:
long getDateDiff(Date d1, Date d2, TimeUnit timeUnit) {
long diff = d2.getTime() - d1.getTime(); //in millisec
long diffMinutes = TimeUnit.MILLISECONDS.toMinutes(diff);
return diffMinutes;
}
3 ответа
Ваш результат очень странный со мной. Итак, я попробовал это:
@Test
public void differenceDateTest() throws ParseException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
Date date = dateFormat.parse("2016-02-29 12:21");
Date date2 = dateFormat.parse("2016-03-01 12:21");
System.out.println(date2.getTime() - date.getTime());
long mili = date2.getTime() - date.getTime();
System.out.println(TimeUnit.MILLISECONDS.toHours(mili)); // 24 hours.
}
он вернулся ровно через 24 часа.
ТЛ; др
Разобрать ваши входные строки.
LocalDateTime startLdt = LocalDateTime.parse( "2016-04-30T12:21" ) ;
LocalDateTime stopLdt = LocalDateTime.parse( "2016-05-01T12:21") ;
Присвойте часовой пояс или смещение от UTC, предназначенные, но пропущенные на входах. Я предполагаю, что вы предполагали само UTC (смещение нуля).
OffsetDateTime start = startLdt.atOffset( ZoneOffset.UTC );
OffsetDateTime stop = stopLdt.atOffset( ZoneOffset.UTC ) ;
Рассчитать прошедшее время по шкале дней (24-часовой период времени), часов, минут, секунд и наносекунд.
Duration d = Duration.between( start , stop ) ;
d.toString (): PT24H
Ваш первый пример приводит к 24 часам, как видно, когда код запускается вживую на IdeOne.com.
Ваш второй пример также приводит к 24 часам, как видно на IdeOne.com.
подробности
В Вопросе и других ответах используются старые классные классы даты и времени или библиотека Joda-Time. Оба вытесняются классами java.time.
Использование java.time
Конвертировать ваши Date
возражает против Instant
объекты, эквивалент в java.time. Instant
класс представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).
Instant start = d1.toInstant();
Instant stop = d2.toInstant();
использование Duration
(или же Period
) за промежуток времени между ними.
Duration d = Duration.between( start , stop );
Извлечь общее количество минут за весь промежуток времени.
long minutes = d.toMinutes() ;
Часовой пояс
Вы не упоминаете часовой пояс, предназначенный, например, для значений даты и времени. Является ли их контекст UTC? Или вы намеревались какой-то конкретный часовой пояс. В разных часовых поясах аномалии, такие как переход на летнее время (DST), означают, что дни не всегда продолжительностью 24 часа. Так что часовой пояс имеет решающее значение.
Давайте посмотрим на UTC.
// of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)
OffsetDateTime odtStart1 = OffsetDateTime.of ( 2016 , 2 , 29 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime odtStop1 = OffsetDateTime.of ( 2016 , 3 , 1 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
Duration d1 = Duration.between ( odtStart1 , odtStop1 );
OffsetDateTime odtStart2 = OffsetDateTime.of ( 2016 , 4 , 30 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime odtStop2 = OffsetDateTime.of ( 2016 , 5 , 1 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
Duration d2 = Duration.between ( odtStart2 , odtStop2 );
System.out.println ( odtStart1 + "/" + odtStop1 + " = " + d1 );
System.out.println ( odtStart2 + "/" + odtStop2 + " = " + d2 );
2016-02-29T12: 21Z / 2016-03-01T12: 21Z = PT24H
2016-04-30T12: 21Z / 2016-05-01T12: 21Z = PT24H
Строка, сгенерированная toString
в стандартном формате ISO 8601 для продолжительности. P
знаменует начало, T
отделяет любую часть лет-месяцев-дней от любой части часов-минут-секунд.
В обоих случаях результат составляет двадцать четыре часа. Это правильно, потому что в каждом случае вы выбираете переход с последнего дня одного месяца на первый день следующего месяца. UTC не имеет аномалий, поэтому мы ожидаем, что прошло ровно 24 часа.
Вы можете сравнить Duration
объекты по вызову compareTo
, И вы можете сделать математику, чтобы получить разницу между ними. В этом случае мы ожидаем отличное от нуля.
Duration difference = d1.minus( d2 );
разность.toString(): PT0S
Смотрите этот код в прямом эфире на IdeOne.com.
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
Где взять классы java.time?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11 и более поздние версии - часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
Я думаю, что порядок объектов даты не важен, поэтому я использовал Math.abs()
public long getMinuteDifference(Date date1, Date date2) {
long millis = Math.abs(date2.getTime() - date1.getTime());
return TimeUnit.MILLISECONDS.toMinutes(millis);
}
Этот метод возвращает 1440 минут для ваших тестов, которые:
Date d1 = convert(new org.joda.time.LocalDateTime(2016, 4, 30, 12, 0, 0, 0));
Date d2 = convert(new org.joda.time.LocalDateTime(2016, 5, 1, 12, 0, 0, 1));
assertEquals(1440, getMinuteDifference(d1, d2));
Date d3 = convert(new org.joda.time.LocalDateTime(2016, 2, 29, 12, 0, 0, 0));
Date d4 = convert(new org.joda.time.LocalDateTime(2016, 3, 1, 12, 0, 0, 1));
assertEquals(1440, getMinuteDifference(d3, d4));