gpt4 book ai didi

java - 输入日期处于PDT到PST过渡期的日期如何处理?

转载 作者:行者123 更新时间:2023-11-30 10:35:27 27 4
gpt4 key购买 nike

我正在调用一个将两个日期作为输入的 API。API 检查两个日期之间的差异是否大于 60 分钟,然后它会抛出异常。我的输入日期是 startDate=11-06-2016T00:57 :01 和 endDate=11-06-2016T01:56:01。这两个日期保存在 java.util.Date 对象中。现在的问题是,虽然这两个日期相差 59 分钟,小于 60 分钟,但 API 仍然抛出异常。看起来这个问题是由于夏令时造成的。11 月 6 日,一旦到了凌晨 2 点,夏令时结束(PDT时区结束),时间向后移动 1 小时,因此时间再次变为凌晨 1 点,但现在在 PST 时区。这意味着在 11 月 6 日,PDT 和 PST 时区将有两次凌晨 1-2 点。在11月7日调用此API时,时区将为PST。因此,当两个日期在没有指定时区的情况下传递时,它采用PDT时区的startDate和PST时区的enddate。由于PDT和PST本身有差异1 小时,这将添加到 59 分钟的差异中并抛出异常。输入日期处于太平洋夏令时到太平洋夏令时的过渡期如何处理?

示例代码

SimpleDateFormat formatter1 = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");
String start="11-06-2016 00:57:01";
String end ="11-06-2016 01:56:01";
Date startdate = formatter1.parse(start);
Date enddate = formatter1.parse(end);
System.out.println("startDate is :" + startdate);
System.out.println("endDate is :" +enddate);
long dateRange = enddate.getTime() - startdate.getTime();
//if the difference between the two dates is > than 60 min i.e 3600000 ms, then throw exception.
System.out.println(dateRange);
if (dateRange > (60 * 60 * 1000)){
throw new Exception("Date time range cannot be greater than 60 minutes.(calculated using millisecond difference)");
}

输出

[Date Range is = 7140000
Exception in thread "main" java.lang.Exception: Date time range cannot be greater than 60 minutes.(calculated using millisecond difference).
at Datetest.main(Datetest.java:28)][1]

以上代码片段在 PST 时区调用时抛出异常。

最佳答案

无论是 SimpleDateFormat 还是底层的 Calendar 都没有指定在分析一个没有时区的日期时间字符串时会发生什么,时间在夏令时和标准时间之间的重叠小时。

您已经观察到它会在较晚的时间返回,即它似乎更喜欢标准时间而不是夏令时。但是,行为是未定义的,所以...

然而,新的 java.time 类确实指定了具体发生的事情,以及如何选择重叠的其他“小时”。

在新 API 中,由于您的日期时间字符串没有时区,您可能首先使用 LocalDateTime 进行解析,然后应用时区以获得 ZonedDateTime,例如

LocalDateTime ldtEnd = LocalDateTime.parse("2016-11-06T01:56:01");
ZonedDateTime zdtEnd = ldtEnd.atZone(ZoneId.of("America/Los_Angeles"));
// zdtEnd is now: 2016-11-06T01:56:01-07:00[America/Los_Angeles]

要查看重叠部分,您可以尝试添加一个小时:

ZonedDateTime zdtEnd2 = zdtEnd.plusHours(1);
// zdtEnd2 is now: 2016-11-06T01:56:01-08:00[America/Los_Angeles]

行为定义明确,参见 atZone() 的 javadoc :

In most cases, there is only one valid offset for a local date-time. In the case of an overlap, where clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".

In the case of a gap, where clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".

To obtain the later offset during an overlap, call ZonedDateTime.withLaterOffsetAtOverlap() on the result of this method. To throw an exception when there is a gap or overlap, use ZonedDateTime.ofStrict(LocalDateTime, ZoneOffset, ZoneId).

如您所见,它总是会返回重叠的较早时间,这与观察到的 SimpleDateFormat 行为相反。如果您希望以后时间重叠,请调用withLaterOffsetAtOverlap()

如果你不想依赖记录的默认值,你总是可以明确的:

ZoneId PT = ZoneId.of("America/Los_Angeles");

LocalDateTime ldtStart = LocalDateTime.parse("2016-11-06T00:57:01");
ZonedDateTime zdtStartEarly = ldtStart.atZone(PT).withEarlierOffsetAtOverlap();
ZonedDateTime zdtStartLater = ldtStart.atZone(PT).withLaterOffsetAtOverlap();
System.out.println(zdtStartEarly); // 2016-11-06T00:57:01-07:00[America/Los_Angeles]
System.out.println(zdtStartLater); // 2016-11-06T00:57:01-07:00[America/Los_Angeles]

LocalDateTime ldtEnd = LocalDateTime.parse("2016-11-06T01:56:01");
ZonedDateTime zdtEndEarly = ldtEnd.atZone(PT).withEarlierOffsetAtOverlap();
ZonedDateTime zdtEndLater = ldtEnd.atZone(PT).withLaterOffsetAtOverlap();
System.out.println(zdtEndEarly); // 2016-11-06T01:56:01-07:00[America/Los_Angeles]
System.out.println(zdtEndLater); // 2016-11-06T01:56:01-08:00[America/Los_Angeles]

如您所见,对于 00:57 时间,它没有任何区别,因为那个时间不在重叠时间。

关于java - 输入日期处于PDT到PST过渡期的日期如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41135822/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com