繁体   English   中英

使用新的java.util.Date()返回使用DST的一小时

[英]Using new java.util.Date() Returns An Hour Behind With DST

我有一个在Linux虚拟机上运行的Java程序作为cron作业。 目前存在一个问题,以下行用作记录存储当前日期和时间的一部分:

String date = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date());

在今天夏令时之后,确定系统日期未正确设置,因为它没有更新。 使用以下命令修复此问题并重新启动Linux环境后,日期现在正确并更新为夏令时。

ln -s /usr/share/zoneinfo/America/New_York /etc/localtime

但是,当Java程序作为cron作业的一部分执行时,日期仍然落后一小时。 这会导致内部发生计时问题,因为new Date()用于获取当前系统时间,从而导致进程中的后续问题。 例如,在下午5:00,Java程序输出4:00 PM。 这个实现还有其他考虑因素吗? new Date()不应该总是返回当前的系统日期吗?

将调试行添加到cron作业,这将执行预期的正确时间。

TL;博士

  • Instant.now()
  • 更新您的JVM的tzdata
  • 以UTC工作,特别是您的日志记录
  • 序列化为ISO 8601格式

Date

新的Date()不应该总是返回当前的系统日期吗?

是的, Date类始终以UTC格式捕获当前时刻。 让我再说一遍: Date以UTC记录时刻。

问题来自该类' toString方法的善意但不幸的“特性”,其中JVM的当前默认时区应用于生成该字符串 避免这种过时和麻烦的课程的众多原因之一。

我怀疑您的“tzdata”时区数据文件已过时,无法识别DST切换的新日期。

重启JVM

Java实现通常在启动时从主机OS获取其当前的默认时区。 在JVM之后,更改主机操作系统的时区对JVM没有影响。

重新启动JVM以在主机操作系统中选择新的区域设置。

在服务器上使用UTC

最佳做法通常是将服务器设置为UTC。 那你就不用担心夏令时废话了。

以UTC工作

您的编程,日志记录,计算机作业,数据交换和数据序列化的大部分应该是UTC。

请注意,例如,Stack Overflow如何使用UTC报告“今天”和“昨天”的活动。 学会将UTC视为真正的时间; 所有区域都是该主题的变体。

仅在关键时刻应用时区,例如向期望某个区域的用户进行演示。

请记住,您的问题不是由于时空的弯曲造成的。 按UTC计算,秒,分钟和小时数继续正常增加,滴答滴答滴答声。 您的问题在于误译为时区,其中包含过时的时区规则更改数据。

在Java代码中指定所需的区域

您的Java应用程序应始终明确指定其所需/预期的时区。 如果省略,则隐式应用JVM的当前默认时区。

JVM默认值可以随时由JVM中任何应用程序的任何线程中的任何代码更改,并立即影响该JVM中的所有其他代码。 因此,永远不要依赖于当前的默认值。 与用户确认,并在您的代码中明确指定。

避免遗留日期时间类

旧日期时间类包括DateCalendar是一个血腥的混乱。 避免他们。 它们现在已经遗留下来,取而代之的是java.time类。

Instant类是时间线上的一个时刻,分辨率为纳秒,始终为UTC。

Instant instant = Instant.now() ;

要生成标准的ISO 8601格式化字符串,请调用toString 最后的Z是Zulu的缩写,意思是UTC。

String output = instant.toString() ;

2017-01-23T12:34:56.123456789Z

使用这两行简单的代码可以避免您的整个问题。

但是你应该经常更新tzdata:

  • 主机操作系统
  • JVM
  • 数据库系统(Postgres等)
  • 像Joda-Time这样的图书馆

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM