Java ZonedDateTime到即时转换

时间:2018-03-04 19:53:13

标签: java java-8 jodatime

我打算按照以下逻辑将ZonedDateTime转换为即时。

说,我在PST时区,目前的时间是11A.M.如果我现在转换(截至2018年3月4日没有夏令时),toInstant将是7 P.M。

对于相同的11 A.M,toInstant将在2018年4月4日返回6 P.M,因为将观察到夏令时。

因此,以下代码正确返回。

ZonedDateTime dateTime = ZonedDateTime.now();  --->>> March 04th 2018 at 11 A.M PST
dateTime.plusMonths(1).toInstant(); -->> returns April 04th 2018 at 6 PM PST as daylight saving will be observed

但是,

如果我转换为Instant然后再添加一个月,结果会有所不同。

Instant dateTime = ZonedDateTime.now().toInstant();  --->>> March 04th 2018 at 7 P.M UTC
dateTime.plus(1,ChronoUnit.MONTHS).toInstant(); -->> returns April 04th 2018 at 7 PM UTC ( but the actual time should be 6 PM UTC ). 

这没关系,因为我们已经转换为UTC,它只是从那里添加。

因此,要包含夏令时,我需要将天数,月数或年数....添加到ZonedDateTime,然后转换为Instant。

ZonedDateTime dateTime = ZonedDateTime.now();   ---> March 04th 2018 at 11A.M
dateTime.plusDays(10).toInstant();     ---> March 14th 2018 at 6P.M
dateTime.plusMonths(1).toInstant();     ---> April 04th 2018 at 6P.M

上面的代码按预期工作。但是下面的一个没有返回6 P.M,但它返回7 P.M。

dateTime.plusSeconds(org.joda.time.Period.days(1).multipliedBy(10).toStandardSeconds().getSeconds())
         .toInstant())  --> ---> March 14th 2018 at 7P.M

不确定,这有什么问题,以及如何使它工作几秒钟。

2 个答案:

答案 0 :(得分:3)

原因可在ZonedDateTime类的文档中找到。对于方法plusDays,我们在方法文档中看到了这一点:

  

这在当地时间线上运行,为当地日期时间增加了几天。然后使用区域ID将其转换回ZonedDateTime以获取偏移量。

     

当转换回ZonedDateTime时,如果本地日期时间处于重叠状态,则如果可能,将保留偏移量,否则将使用较早的偏移量。如果在间隙中,则本地日期时间将按间隙的长度向前调整。

但是,在plusSeconds方法的文档中,我们看到了这一点:

  

这在即时时间线上运行,使得增加一秒将始终是一秒之后的持续时间。这可能导致本地日期时间改变不超过一秒的量。请注意,这与日,月和年使用的方法不同。

因此,这两种方法的行为方式不同,在选择使用哪种方法以满足您的目的时需要考虑这一点。

答案 1 :(得分:0)

据我了解您的要求,您可以在几分钟或几小时内添加时间,例如

    long minutesToAdd = Duration.ofDays(10).toMinutes();

我正在使用java.time,因为我没有使用Joda-Time的经验。如果你愿意的话,也许你可以将我的想法转化为Joda-Time。

正如我进一步了解的那样,添加上述分钟的结果应该是一个分钟后的分钟。相反,它应该与添加10天相同。因此,如果它在加利福尼亚州的晚上9点,那么10天后你想在加利福尼亚州的晚上9点。我建议您在添加分钟或小时之前转换为LocalDateTime来解决此问题,然后再转换回ZonedDateTime

    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
    System.out.println(now);
    System.out.println(now.toInstant());
    Instant inTenDays = now.toLocalDateTime()
            .plusMinutes(minutesToAdd)
            .atZone(now.getZone())
            .toInstant();
    System.out.println(inTenDays);

这只是打印

2018-03-04T21:16:19.187690-08:00[America/Los_Angeles]
2018-03-05T05:16:19.187690Z
2018-03-15T04:16:19.187690Z

由于夏令时(DST)于3月15日(今年3月11日起)生效,因此您不会在UTC中获得相同的小时,而是在同一时段获得相同的时间。你的时区。