使用两个 Date 对象的持续时间计算问题

Hours duration calculation issue using two Date objects

我的 class 中有一个方法可以计算两个日期的小时持续时间。

public static double getDuration(Date startDate, Date endDate){
    return (endDate.getTime()-startDate.getTime()) / (1000.0 * 60 * 60);
}

我输入的日期是 28-10-2017 14:0029-10-2017 02:00。在夏令时期间,持续时间给出 13.0 这是错误的。

如果我用这个输入编写一个简单的程序,我会得到正确的结果。所以只检查了 Date 对象。在我的应用程序输入中,开始日期为 dayofWeek,开始日期为 7,结束日期为 1。但是我的简单程序将开始日期设为 1,结束日期设为 2。知道这是怎么回事吗?

首先,read this,哭一下,然后庆幸你不需要编写 date/time 库,因为其他人已经为你完成了

然后将 Joda-Time 添加到您的项目中。

如果您知道数据库中所有日期的时区,那么您应该能够根据需要使用Duration, Period or Interval

首先,我建议使用一个库来处理不同的时区和时间变化(如夏季 +1 小时等)。为此,我建议使用 JodaTime。

 Hours hoursDiff =  Hours.hoursBetween(start.toLocalDate(), end.toLocalDate()).getDays())

然后你可以做

hoursDiff.getHours(); //returns and int

您可以像这样将日期转换为日期时间(参数中需要):

Date date = new Date();
DateTime dateTime = new DateTime(date);

<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.7</version>
</dependency>

tl;博士

对于 Java 6 和 Java 7,使用 ThreeTen-Backport 项目。

12 小时

在这些日期的 Europe/Berlin 时区,下午 2 点到凌晨 2 点之间是十二个小时。

org.threeten.bp.temporal.ChronoUnit.HOURS.between( 

    org.threeten.bp.LocalDateTime
        .parse( "2017-10-28T14:00:00" )
        .atZone( org.threeten.bp.ZoneId.of( "Europe/Berlin" ) ) ,  // Producing a `ZonedDateTime` instance. 

    org.threeten.bp.LocalDateTime
        .parse( "2017-10-29T02:00:00" )
        .atZone( org.threeten.bp.ZoneId.of( "Europe/Berlin" ) )  // Producing another `ZonedDateTime` instance. 

)

12

13 小时

要查看计划在柏林时间凌晨 3 点进行的 Daylight Saving Time (DST) 切换的效果,请将您的起停时间更改为下午 3 点和凌晨 3 点,以获得 13 小时而不是 12 小时。

02:00-03:00 的时间重复,如 中所述。

org.threeten.bp.temporal.ChronoUnit.HOURS.between( 

    org.threeten.bp.LocalDateTime
        .parse( "2017-10-28T15:00:00" )
        .atZone( org.threeten.bp.ZoneId.of( "Europe/Berlin" ) ) ,  // Producing a `ZonedDateTime` instance. 

    org.threeten.bp.LocalDateTime
        .parse( "2017-10-29T03:00:00" )
        .atZone( org.threeten.bp.ZoneId.of( "Europe/Berlin" ) )  // Producing another `ZonedDateTime` instance. 

)

13

看到这个 code run live at IdeOne.com,使用 java.time classes 内置于 Java 8.

java.time

这已在 Stack Overflow 上多次介绍,因此请搜索更多信息。

简单地说……

避免 Date class。仅使用 java.time classes。同样,避免将 Joda-Time 项目用于新工作,因为团队建议迁移到 java.time classes.

将您的输入字符串解析为 LocalDateTime 值,因为它们缺少时区指示符或与 UTC 的偏移量。 LocalDateTime 而不是 代表时间轴上的实际时刻,但我们会到达那里;继续阅读。

提示:以标准 ISO 8601 格式编写日期时间字符串,在 java.time classes 中默认使用 parsing/generating 字符串。

定义用于这些值的时区 (ZoneId)。通过 continent/region 格式的专有名称指定区域,例如 Africa/CasablancaEurope/Berlin。切勿使用 3-4 个伪区域名称,例如 PSTCST.

应用区域为每个时刻生成一个 ZonedDateTime 对象。

通过实例化 Duration 对象或调用 ChronoUnit.HOURS.between.

计算运行时间

许多 java.time 功能被反向移植到 ThreeTen-Backport 项目中的 Java 6 和 Java 7。 java.time classes 内置于 Java 8 和 Java 9.



关于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 classes.

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

在哪里获取 java.time classes?

DST 在 03:00

切换

你说 your JVM default timezone is Europe/Berlin. In October 28th 2017, Berlin is in Daylight Saving Time (DST), so the offset is +02:00 (two hours ahead of UTC)。当当地时间到达 2017 年 10 月 29th 3 AM 时,时钟向后拨 1 小时, 到凌晨 2 点(偏移量从 +02:00 变为 +01:00)。

这意味着,在这个时区,凌晨 2 点到 2:59 之间的所有本地时间都存在 两次 (偏移 +02:00+01:00).只是为了更好地说明这一点,这就是时间线在这个时区中每小时的样子:

  • 2017-10-29T01:00+02:00(夏令时凌晨 1 点 - 偏移量 +02:00
  • 2017-10-29T02:00+02:00(1 小时后,夏令时 2 AM - 偏移量 +02:00
  • 2017-10-29T02:00+01:00(1 小时后,凌晨 2 点 夏令时 - 偏移量 +01:00
  • 2017-10-29T03:00+01:00(1 小时后,夏令时凌晨 3 点 不是 - 偏移量 +01:00

您的 Date object with its getTime() 值等于 1509238800000 对应于 second 凌晨 2 点(not-in-DST date),则相差13小时。


如果我们将时间戳转换为 UTC (using the ,这会变得更加清晰):

Timestamp (getTime()) | Europe/Berlin timezone              | UTC
----------------------|-------------------------------------|------------------
1509192000000         | 2017-10-28T14:00+02:00 (in DST)     | 2017-10-28T12:00Z
1509238800000         | 2017-10-29T02:00+01:00 (not in DST) | 2017-10-29T01:00Z

请注意,当转换为 UTC 时,很明显差异实际上是 13 小时。