使用两个Date对象

时间:2017-10-16 14:04:56

标签: java date dst date-difference

我班上有一个方法来计算两个日期的每小时持续时间。

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。知道这是怎么回事吗?

4 个答案:

答案 0 :(得分:2)

TL;博士

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

12小时

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

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的小时重复,如Answer by Hugo中所述。

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

使用Java 8中内置的java.time类来查看此code run live at IdeOne.com

java.time

Stack Overflow已经多次介绍过这个问题,所以请搜索更多信息。

...简言之

避免使用Date课程。仅使用java.time类。同样,当团队建议迁移到java.time类时,请避免使用Joda-Time项目进行新工作。

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

提示:以标准ISO 8601格式编写日期时间字符串,在解析/生成字符串时,默认情况下在java.time类中使用。

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

应用区域以生成每个时刻的ZonedDateTime对象。

计算实例化Duration对象或调用ChronoUnit.HOURS.between的已用时间。

大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport项目中的Java 7。 java.time类内置于Java 8和Java 9中。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

答案 1 :(得分:2)

DST在03:00切换

您说in the comments JVM default timezoneEurope/Berlin。在10月 28 th 2017年,柏林位于Daylight Saving Time (DST),因此偏移量为tableView(比UTC提前两小时)。当本地时间到达 29 th 2017 凌晨3点时,时钟将向后移动1小时,到凌晨2点(并且偏移量从+02:00+02:00)。

这意味着,在此时区中,凌晨2点到凌晨2点59分之间的所有当地时间都存在两次(在抵消+01:00+02:00中)。只是为了更好地说明一下,时间轴就是这个时区的时间轴,一小时一小时:

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

Date值等于+01:00的{​​{3}}对象对应第二 2 AM( not-in-DST date),那么差异将是13个小时。

如果我们将时间戳转换为getTime()(使用UTC),这会更加清晰:

1509238800000

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

答案 2 :(得分:1)

首先,read this,哭一点,然后很高兴你不需要写日期/时间库,因为其他人已经为你做了

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

如果您知道数据库中所有日期的时区,那么您应该可以使用DurationPeriodInterval,具体取决于您的需要。

答案 3 :(得分:1)

首先,我建议使用一个处理不同时区和时间变化的库(如夏季+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>