Разница между двумя датами в минутах - разные месяцы - 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?

Проект 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));
Другие вопросы по тегам