简体   繁体   English

几分钟之间的差异 - 不同月份 - Java

[英]Difference Between two dates in minutes - different months - Java

I want to find the difference in minutes between 2 dates. 我想找出2个日期之间的分钟差异。 My code works well if the 2 dates are in the same month(and year) but it seems like the difference considers every month to be 31 days long so for the dates: 如果2个日期在同一个月(和年份),我的代码运行良好,但似乎差异考虑每个月为31天,所以对于日期:

 2016-02-29 12:21
 2016-03-1 12:21

I get 4320 minutes or 72 hours 我得到4320分钟或72小时

for: 对于:

 2016-04-30 12:21
 2016-05-01 12:21

I get 2880 minutes or 48 hours 我得到2880分钟或48小时

my code where d1 and d2 are Date objects: 我的代码,其中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;
}

tl;dr TL;博士

Parse your input strings. 解析输入字符串。

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

Assign the time zone or offset-from-UTC intended but omitted from the inputs. 分配时间区域或与UTC有关的偏移但从输入中省略。 I assume you intended UTC itself (an offset of zero). 我假设您打算使用UTC本身(零偏移)。

OffsetDateTime start = startLdt.atOffset( ZoneOffset.UTC );
OffsetDateTime stop = stopLdt.atOffset( ZoneOffset.UTC ) ;

Calculate elapsed time on the scale of days (24-hour chunks of time), hours, minutes, seconds, and nanoseconds. 计算以天为单位(24小时时间段),小时,分钟,秒和纳秒的经过时间。

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

d.toString(): PT24H d.toString():PT24H

Your first example results in 24 hours, as seen when code runs live at IdeOne.com . 您的第一个示例将在24小时内生成,如代码在IdeOne.com上运行时所示

Your second example also results in 24 hours, as seen in IdeOne.com . 您的第二个示例也会导致24小时,如IdeOne.com中所示

Details 细节

The Question and other Answers all use the troublesome old date-time classes or the Joda-Time library. 问题和其他答案都使用麻烦的旧日期时间类或Joda-Time库。 Both are supplanted by the java.time classes. 两者都被java.time类取代。

Using java.time 使用java.time

Convert your Date objects to Instant objects, the equivalent in java.time. Date对象转换为Instant对象,即java.time中的等价对象。 The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。

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

Use Duration (or Period ) for the span of time in between. 使用Duration (或Period )表示其间的时间跨度。

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

Extract the total number of minutes across the entire span-of-time. 提取整个时间跨度内的总分钟数。

long minutes = d.toMinutes() ;

Time zone 时区

You do not mention the time zone intended for example date-time values. 您没有提及用于示例日期时间值的时区。 Is their context UTC ? 他们的背景是UTC吗? Or did you intend some particular time zone. 或者你打算某个特定的时区。 In various time zones, anomalies such as Daylight Saving Time (DST) means days are not always 24 hours long. 在不同的时区,夏令时(DST)等异常意味着天数并不总是24小时。 So time zone is crucial. 所以时区至关重要。

Let's look at UTC. 我们来看看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-02-29T12:21Z / 2016-03-01T12:21Z = PT24H

2016-04-30T12:21Z/2016-05-01T12:21Z = PT24H 2016-04-30T12:21Z / 2016-05-01T12:21Z = PT24H

The string generated by toString is in standard ISO 8601 format for durations . toString生成的字符串是标准ISO 8601格式的持续时间 The P marks the beginning, the T separates any years-months-days portion from any hours-minutes-seconds portion. P标志着开始, T将任何年 - 月 - 日的部分与任何小时 - 分 - 秒部分分开。

In both cases the result is twenty-four hours. 在这两种情况下, 结果都是二十四小时。 This is correct because in each case you chose to go from the last day of one month to the first day of the following month. 这是正确的,因为在每种情况下,您都选择从一个月的最后一天到下一个月的第一天。 UTC has no anomalies, so we expect exactly 24 hours elapsed. UTC没有异常,因此我们预计会过去24小时。

You can compare the Duration objects by calling compareTo . 您可以通过调用compareTo来比较Duration对象。 And you can do math to get the difference between them. 你可以做数学来区分它们。 In this case we expect a different of zero. 在这种情况下,我们期望零的不同。

Duration difference = d1.minus( d2 );

difference.toString(): PT0S difference.toString():PT0S

See this code run live at IdeOne.com . 请参阅IdeOne.com上的代码


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参阅Oracle教程 And search Stack Overflow for many examples and explanations. 并搜索Stack Overflow以获取许多示例和解释。 Specification is JSR 310 . 规范是JSR 310

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用符合JDBC 4.2或更高版本的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 从哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目是未来可能添加到java.time的试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

Your result is very weird with me. 你的结果对我来说很奇怪。 So I tried it: 所以我试了一下:

    @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.
}

it returned exactly 24 hours. 它准确地返回了24小时。

I think order of date objects is not important, so I used Math.abs() 我认为日期对象的顺序并不重要,所以我使用了Math.abs()

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

  return TimeUnit.MILLISECONDS.toMinutes(millis);
}

This method returns 1440 minutes for your test cases which are: 对于您的测试用例,此方法返回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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM