我在PHP中遇到了奇怪的行为:
(strtotime("2017-11-05 00:00:00") - strtotime("2017-11-06 00:00:00")) / 24//3600
(strtotime("2017-11-06 00:00:00") - strtotime("2017-11-05 00:00:00")) / 24//3750
(strtotime("2017-11-07 00:00:00") - strtotime("2017-11-06 00:00:00")) / 24//3600
正如我所发现的那样,它与从夏季到冬季的时间变化有关(https://www.timeanddate.com/time/change/usa/new-york)。这是正确的行为吗?我无法在文档中看到任何与之相关的内容。有人有链接吗?
至少,在java中它可以正常工作:
System.out.println(((new Date(2017, 11, 6).getTime()) - (new Date(2017, 11, 5).getTime())) / 24);//3600000
现在有个问题了。我如何定义,这一天是25小时,我应该通过特殊方法处理这个日期?
答案 0 :(得分:1)
虽然我不能对你的问题的PHP部分说话,但我可以更正你的Java代码。
Duration.between(
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).atStartOfDay( ZoneId.of( "America/New_York" ) ) ,
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).plusDays( 1 ).atStartOfDay( ZoneId.of( "America/New_York" ) )
).toString()
PT25H
Duration.between(
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).atStartOfDay( ZoneOffset.UTC ) ,
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).plusDays( 1 ).atStartOfDay( ZoneOffset.UTC )
).toString()
PT24H
UTC中的一天总是24小时。 某些时区的某一天可能是23,24,25 或其他一些小时,甚至可能包括部分(小数)小时。
您使用的是错误的Java类,而您忽略了时区的关键问题。 java.util.Date
课程令人困惑,麻烦,幸运的是,现在已经遗产了。现代java.time类取代了那些旧的日期时间类。
您在示例代码中忽略了时区的关键问题。旧版Date
类始终采用UTC格式,但您关心的是America/New_York
时区。您的代码计算24小时通用24小时制(UTC),而实际2017-11-05 America/New_York
则为25小时而不是24小时。
Java的示例代码对我来说毫无意义,因为您正在计算持续时间(以毫秒为单位)然后除以24.我不知道该除法如何帮助。
一般24小时工作日内的毫秒数=(24 * 60 * 60 * 1,000)= 86400000.如果我们将除法除以24,则使用java.util.Date
代码返回的数字。
long millis = ((new Date(2017, 11, 6).getTime()) - (new Date(2017, 11, 5).getTime())) ;
System.out.println( millis );
86400000
LocalDate
LocalDate
类表示没有时间且没有时区的仅限日期的值。
LocalDate ld = LocalDate.of( 2017 , Month.NOVEMBER , 5 ) ;
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,Paris France午夜后的几分钟是Montréal Québec中仍然是“昨天”的新一天。
以continent/region
格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime
让java.time确定一天中的第一个时刻。不要假设这一天从00:00开始。诸如夏令时(DST)之类的异常意味着该日可以在诸如01:00的时间开始。
ZonedDateTime start = ld.atStartOfDay( z ) ;
通常,半开放式方法最适合定义时间跨度。在这种方法中,开头是包含,而结尾是独占。所以整整一天被定义为从一天的第一时刻开始,并且一直持续到第二天的第一时刻,但不包括第二时刻。
ZonedDateTime stop = ld.plusDays( 1 ).atStartOfDay( z ) ;
计算当天的长度,11月5日在纽约地区。
Duration d = Duration.between( start , stop ) ;
PT25H
所以,是的,我们看到由于DST切换而导致一天长达25小时。
请参阅此code run live at IdeOne.com。
Duration::toString
的输出位于standard ISO 8601 format。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。