java - 使用LocalDateTIme和ZonedDateTime从日期中减去一天后得到错误的结果

标签 java dst java-time zoneddatetime

我正在测试"2016-03-28T02:00:00+0200"(UTC秒中为1459123200)

减去1天后,应用夏令时,输出应为:


  “ 2016-03-27T03:00:00 + 0200”


但是我得到这个:


  2016-03-26T01:00 + 01:00 [欧洲/斯德哥尔摩]


码:

public class DateFormatSampleCode {
    public static void main(String[] args) 
    {
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(1459123200, 0, ZoneOffset.UTC);

        System.out.println(localDateTime);
        localDateTime = localDateTime.minusDays(1);
        System.out.println(localDateTime);

        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Europe/Stockholm"));

        System.out.println(zonedDateTime);
    }
}


请检查并指出我要去哪里。

最佳答案

好的,您找到了解决方案,我只想补充一些见解,并提出对your answer的一些改进。

使用TimeZone.setDefault设置JVM默认时区不是实现此目的的最佳方法。尽管它可能在大多数情况下都可以工作,但是如果您认为此代码在更复杂的环境中运行,则可能会有些冒险并且容易出错。

这是因为TimeZone.setDefault更改了整个JVM的默认时区。在同一JVM中运行的任何其他应用程序都将受到它的影响。同一应用程序的其他部分也会受到影响,即使在多个线程中运行的同一代码也可能会给您错误的结果(和race conditions are hard to debug)。

我注意到您正在使用TimeZone.setDefault(TimeZone.getTimeZone(timezone));。这意味着您已经在使用特定时区,因此无需依赖JVM的默认时区。如果您有特定的时区名称,请使用它代替默认名称。因此,我建议您addDays方法应如下所示:

public ZonedDateTime addDays(long myUTCTimeInSeconds, int days, String timezone) {
    // get the instant from the UTC seconds
    Instant instant = Instant.ofEpochSecond(myUTCTimeInSeconds);
    // get the instant at the specified timezone
    ZonedDateTime z = instant.atZone(ZoneId.of(timezone));

    // add days
    return z.plusDays(days);
}


所做的改进:


如果将plusDays传递给-1,则它已经减去1天。无需检查该值并使用abs方法。
不要使用JVM默认时区:使用现有的ZoneId.systemDefault()代替timezone(在setDefault方法中使用的那个)
instant.atZone等效于ZonedDateTime.ofInstant。 IMO,atZone更具“可读性”,但是在这种情况下,这取决于选择和代码风格。最终结果没有区别。


这样,您可以执行以下操作:

// call directly, no need to change the default timezone
System.out.println(addDays(1459123200, -1, "Europe/Stockholm"));


这将打印:


  2016-03-27T03:00 + 02:00 [欧洲/斯德哥尔摩]

关于java - 使用LocalDateTIme和ZonedDateTime从日期中减去一天后得到错误的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42386060/

相关文章:

java - 在数据库中创建空对象或稍后保存

java - 搜索小部件,NullPointer?

PostgreSQL:无法使带 DST 的时区正常工作

java - 使用 Java 8 计算两个日期之间的天数,同时忽略一周中的某些天数

java - 将 Instant 从大纪元时间转换为微秒

java - 传递当前日期

java - Docker 创建巨大的图像大小

java - 如何向日历对象添加一天并考虑夏令时?

java - Java Spring 应用程序的巴西时区

kotlin - 将 period 添加到 startDate 不会产生 endDate