我正在创建3个GregorianCalendar对象:
第一天和第二天之间的天差为96天。第一天和第三个天之间的天差是... 96天。说吧?
为Scala代码道歉,但您的Java负责人应该能够了解正在发生的事情:
def test(): Unit = {
val start = new GregorianCalendar(2018, 11, 4)
val laterA = new GregorianCalendar(2018, 11, 4)
laterA.add(Calendar.DATE, 96)
val laterB = new GregorianCalendar(2018, 11, 4)
laterB.add(Calendar.DATE, 97)
println(ChronoUnit.DAYS.between(start.toInstant, laterA.toInstant))
println(ChronoUnit.DAYS.between(start.toInstant, laterB.toInstant))
}
上面显示了以下内容:
96
96
怎么了?
答案 0 :(得分:7)
您必须位于美国的语言环境(或与美国同时开始夏令时的语言环境)。在2019年,DST starts at 2:00 am Sunday, March 10, 2019。
从2018年12月4日开始增加96天,将产生2019年3月10日。从2018年12月4日开始增加97天,将产生2019年3月11日。
格式化并输出laterA
和laterB
会产生:
2019-03-10 00:00:00
2019-03-11 00:00:00
请注意,由于DST(在美国),这两个日期之间有23小时。
但是between
method会截断小数单位。
计算返回一个整数,代表两个时间点之间的完整单位数。例如,时间11:30到13:29之间的小时数将只有1小时,因为它比2小时少了1分钟。
因此,相差96天23小时(由于DST而不是97天)返回为96
。
答案 1 :(得分:2)
那是因为您所在的时区。如果您通过比较第二个值
System.out.println(ChronoUnit.SECONDS.between(start.toInstant(), laterA.toInstant()));
System.out.println(ChronoUnit.SECONDS.between(start.toInstant(), laterB.toInstant()));
您将看到Europe/London
会得到
8294400
8380800
但对于America/New_York
,它将是
8294400
8377200
秒差恰好为3600
秒,这意味着夏令时发生了变化。
答案 2 :(得分:2)
正如其他人已经说过的那样,请尽可能避免使用GregorianCalendar
类。它存在一些设计问题,现在已经过时了。
但是,您的特定问题不是GregorianCalendar
类。考虑到夏令时(DST)和其他所有因素,它可以在您的代码中很好地增加97天。正如其他人正确指出的那样,在今年12月4日之前增加97天可以使您在3月11日这一天,在使用夏令时的北美时区中,夏令时才刚刚开始(第11个月作为构造函数参数,意味着12月,另一件令人困惑的事情关于GregorianCalendar
)。因此添加的最后一天只有23小时。
您真正遇到的问题是ChronoUnit.DAYS
和Instant
的组合。 Instant
是没有时区的时间点,没有天数的概念。取而代之的是,您得到的结果与从小时数中得到的结果相同,除以24,然后舍去其余部分。很少有用。由于添加的最后一天只有23小时,因此不计算在内。取而代之的是在ZonedDateTime
或LocalDate
实例之间或者在名称上带有“ date”的其他java.time类之间计算天数。示例1(Java代码,您可以自己翻译吗?):
LocalDate start = LocalDate.of(2018, Month.DECEMBER, 4);
LocalDate laterB = start.plusDays(97);
System.out.println(ChronoUnit.DAYS.between(start, laterB));
输出:
97
如果您不能避免从无法立即升级的旧版API中获得GregorianCalendar
,则应该做的第一件事就是使用toZonedDateTime
对其进行转换以获取{{1} }。这将为您提供ZonedDateTime
中的所有相关信息,包括其时区和日历日期。换句话说,您不应像在问题代码中那样使用其GregorianCalendar
方法。示例2:
toInstant
现在输出是您期望的输出:
97
我都用America / New_York作为我的默认时区运行了这两个代码片段。
答案 3 :(得分:1)
jshell> System.out.println(laterB.toInstant()); 2019-03-11T04:00:00Z
jshell> System.out.println(laterA.toInstant()); 2019-03-10T05:00:00Z
请注意,相差不到24小时。为什么?您在3月10日越过了夏令时。