当输入日期处于从PDT到PST的过渡期时,如何处理日期? [英] How to handle dates when the input dates are in the transition period from PDT to PST?

查看:72
本文介绍了当输入日期处于从PDT到PST的过渡期时,如何处理日期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am calling an API which takes two dates as input.The API checks if the difference between the two date is greater than 60 min, then it throws an exception.My input dates are startDate=11-06-2016T00:57:01 and endDate=11-06-2016T01:56:01.These two dates are saved in java.util.Date object. Now the issue is though the two dates have a difference of 59 min which is less than 60 min, still the API throws exception.Looks like this isssue is due to DayLightSaving.On Nov 6,once 2 am is reached , DayLightSaving ends (PDT time zone ends), time is moved backward by 1 hr due to which time again become 1 am but in PST time zone now.This means on Nov 6 , there would be 1-2 am twice one in PDT and one in PST zone. When this API is called on NOV 7, the time zone would be PST.So when the two dates are passed without the timezone specified, it takes the startDate in PDT zone and enddate in PST zone.Since PDT and PST itself have a difference of 1 hour, this would get added to the 59 min differnce and exception is being thrown. How to handle this case when the input dates are in the transition period from PDT to PST?

示例代码

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时区调用时,以上代码段引发异常.

The above snippet throws exception when called in PST time zone.

推荐答案

SimpleDateFormat 和底层的 Calendar 都没有指定在一段时间内解析不带时区的日期时间字符串时发生的情况在夏令时和标准时间之间的重叠小时内.

Neither SimpleDateFormat nor the underlying Calendar specifies what happens when parsing a datetime string without timezone for a time in the overlapping hour between daylight savings time and standard time.

您已经观察到它将返回较晚的时间,即,相对于夏令时,它似乎更喜欢标准时间.但是,行为是不确定的,所以...

You have observed that it will return the later time, i.e. it seems to prefer standard over daylight savings time. But, the behavior is undefined, so...

然而,新的 java.time 类确实确切指定了会发生什么,以及如何选择其他小时".重叠.

The new java.time classes do however specify exactly what happens, and how to choose the other "hour" of the overlap.

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

In the new API, since your datetime string is without timezone, you'd likely first parse using LocalDateTime, then apply time zone to get a ZonedDateTime, e.g.

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]

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

To see the overlap, you can try adding an hour:

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

行为是明确定义的,请参见

The behavior is well-defined, see javadoc of atZone():

在大多数情况下,本地日期时间只有一个有效偏移量.在重叠的情况下,如果时钟被调回,则有两个有效的偏移量.此方法使用通常与夏季" 相对应的早期偏移量.

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".

要在重叠期间获取更高的偏移量,请对该方法的结果调用 ZonedDateTime.withLaterOffsetAtOverlap() .要在存在间隙或重叠时引发异常,请使用 ZonedDateTime.ofStrict(LocalDateTime,ZoneOffset,ZoneId).

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().

As you can see, it will always return the earlier time in an overlap, which is opposite of the observed behavior of SimpleDateFormat. If you want the later time in an overlap, call withLaterOffsetAtOverlap().

如果您不想依赖已记录的默认设置,则可以始终保持明确:

If you don't want to rely on documented default, you can always be explicit:

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 时间而言,这没有什么区别,因为该时间不在重叠时间内.

As you can see, for the 00:57 time, it makes no difference, because that time is not in the overlap hour.

这篇关于当输入日期处于从PDT到PST的过渡期时,如何处理日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆