以分钟为单位的两个日期之间的差异 - 不同的月份 - Java

Difference Between two dates in minutes - different months - Java

我想找出两个日期之间的分钟差。如果这两个日期在同一个月(和同一年),我的代码运行良好,但似乎差异认为每个月有 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;
}

你的结果对我来说很奇怪。所以我试了一下:

    @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 小时。

我认为日期对象的顺序并不重要,所以我使用了Math.abs()

public long getMinuteDifference(Date date1, Date date2) {
  long millis = Math.abs(date2.getTime() - date1.getTime());

  return TimeUnit.MILLISECONDS.toMinutes(millis);
}

此方法 returns 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));

tl;博士

解析您的输入字符串。

LocalDateTime startLdt = LocalDateTime.parse( "2016-04-30T12:21" ) ;
LocalDateTime stopLdt = LocalDateTime.parse( "2016-05-01T12:21") ;

指定时区或 offset-from-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 小时内产生结果,正如 code runs live at IdeOne.com.

时所见

您的第二个示例的结果也是 24 小时,如 seen in IdeOne.com

详情

问题和其他答案都使用麻烦的旧 date-time 类 或 Joda-Time 库。两者都被 java.time 类.

所取代

使用java.time

将您的 Date 对象转换为 Instant 对象,相当于 java.time。 Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant start = d1.toInstant();
Instant stop = d2.toInstant();

使用 Duration(或 Period)作为两者之间的时间跨度。

Duration d = Duration.between( start , stop );

提取整个 span-of-time.

的总分钟数
long minutes = d.toMinutes() ;

时区

您没有提到 date-time 值的时区。他们的上下文是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 format for durationsP 标记开始,T 将任何 years-months-days 部分与任何 hours-minutes-seconds 部分分开。

在这两种情况下,结果都是 twenty-four 小时。这是正确的,因为在每种情况下您都选择从一个月的最后一天到下个月的第一天。 UTC 没有异常,因此我们预计恰好 24 小时过去了。

您可以通过调用 compareTo 来比较 Duration 个对象。你可以做数学来找出它们之间的区别。在这种情况下,我们期望差异为零。

Duration difference = d1.minus( d2 );

difference.toString(): PT0S

看到这个code run live at IdeOne.com


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

在哪里获取java.time类?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.