我正在测试"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/