我班上有一个方法来计算两个日期的每小时持续时间。
public static double getDuration(Date startDate, Date endDate){
return (endDate.getTime()-startDate.getTime()) / (1000.0 * 60 * 60);
}
我的输入日期为28-10-2017 14:00
和29-10-2017 02:00
。在夏令时期间,持续时间为13.0
,这是错误的。
如果我用这个输入写一个简单的程序,我得到了正确的结果。所以只需检查Date
对象。在我的应用程序输入中,它以dayofWeek为7开始日期,1为结束日期。但我的简单程序将其作为开始日期为1,结束日期为2。知道这是怎么回事吗?
答案 0 :(得分:2)
对于Java 6和Java 7,请使用 ThreeTen-Backport 项目。
在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
要查看计划在柏林时间凌晨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。
Stack Overflow已经多次介绍过这个问题,所以请搜索更多信息。
...简言之
避免使用Date
课程。仅使用java.time类。同样,当团队建议迁移到java.time类时,请避免使用Joda-Time项目进行新工作。
将输入字符串解析为LocalDateTime
值,因为它们缺少时区指示符或与UTC的偏移量。 LocalDateTime
不代表时间轴上的实际时刻,但我们会到达那里;请继续阅读。
提示:以标准ISO 8601格式编写日期时间字符串,在解析/生成字符串时,默认情况下在java.time类中使用。
定义用于这些值的时区(ZoneId
)。以continent/region
格式指定专有名称的区域,例如Africa/Casablanca
或Europe/Berlin
。切勿使用3-4个伪区域名称,例如PST
或CST
。
应用区域以生成每个时刻的ZonedDateTime
对象。
计算实例化Duration
对象或调用ChronoUnit.HOURS.between
的已用时间。
大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport项目中的Java 7。 java.time类内置于Java 8和Java 9中。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
答案 1 :(得分:2)
您说in the comments JVM default timezone是Europe/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添加到您的项目中。
如果您知道数据库中所有日期的时区,那么您应该可以使用Duration,Period或Interval,具体取决于您的需要。
答案 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>