使用 new java.util.Date() Returns 比 DST 晚一个小时
Using new java.util.Date() Returns An Hour Behind With DST
我有一个 Java 程序作为 cron 作业在 linux 虚拟机上运行。当前存在问题,以下行用作日志记录的一部分以存储当前日期和时间:
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 PM,Java 程序输出 4:00 PM。这个实现是否有额外的考虑? new Date()
不应该总是 return 当前系统日期吗?
向 cron 作业添加调试行,这会在预期的正确时间执行。
tl;博士
Date
class
Shouldn't new Date() always return the current system date?
是的,Date
class 始终捕获 UTC 中的当前时刻。让我重复一遍:Date
以 UTC 捕捉瞬间。
问题来自 class' toString
方法的一个善意但不幸的“特性”,其中 JVM 当前的默认时区用于生成该字符串。避免这种过时且麻烦的众多原因之一 class.
我怀疑您的“tzdata”时区数据文件已过时,无法识别 DST 转换的新日期。
重新启动 JVM
Java 实现通常在启动时从主机 OS 中获取它们当前的默认时区。在JVM之后,更改主机OS'时区对JVM没有影响。
重新启动 JVM 以获取主机 OS 中的新区域设置。
在服务器上使用 UTC
最佳做法通常是将您的服务器设置为 UTC。那么你不必担心夏令时的废话。
在 UTC 工作
您的大部分编程、日志记录、cron 作业、数据交换和数据序列化都应该使用 UTC。
请注意,例如,Stack Overflow 如何使用 UTC 报告 "today" 和 "yesterday" 的 activity。学会将 UTC 视为唯一真实时间;所有区域都是该主题的变体。
仅在关键时应用时区,例如在向期望特定时区的用户进行演示时。
请记住,您的问题不是由于 space 时间弯曲造成的。秒、分和小时继续正常递增,就 UTC 而言,滴答滴答。您的问题在于错误翻译成具有过时时区规则更改数据的时区。
在 Java 代码中指定您想要的区域
您的 Java 应用应始终明确指定其 desired/intended 时区。如果省略,则隐式应用 JVM 当前的默认时区。
JVM 中的任何应用程序的任何线程中的任何代码都可以随时更改 JVM 默认设置,并立即影响该 JVM 中的所有其他代码。所以永远不要依赖当前的默认值来做任何重要的事情。与用户确认,并在您的代码中明确指定。
避免遗留日期时间 classes
包括 Date
和 Calendar
在内的旧日期时间 classes 真是一团糟。避开他们。它们现在是遗留的,被 java.time classes 取代。
Instant
class 是时间线上的一个时刻,分辨率以纳秒为单位,始终采用 UTC。
Instant instant = Instant.now() ;
要生成标准 ISO 8601 格式的字符串,请调用 toString
。最后的 Z
是 Zulu 的缩写,表示 UTC。
String output = instant.toString() ;
2017-01-23T12:34:56.123456789Z
使用这两行简单的代码就可以避免整个问题。
但是您应该定期更新以下位置的 tzdata:
- 主机OS
- JVM
- 数据库系统(Postgres等)
- Joda-Time 等库
我有一个 Java 程序作为 cron 作业在 linux 虚拟机上运行。当前存在问题,以下行用作日志记录的一部分以存储当前日期和时间:
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 PM,Java 程序输出 4:00 PM。这个实现是否有额外的考虑? new Date()
不应该总是 return 当前系统日期吗?
向 cron 作业添加调试行,这会在预期的正确时间执行。
tl;博士
Date
class
Shouldn't new Date() always return the current system date?
是的,Date
class 始终捕获 UTC 中的当前时刻。让我重复一遍:Date
以 UTC 捕捉瞬间。
问题来自 class' toString
方法的一个善意但不幸的“特性”,其中 JVM 当前的默认时区用于生成该字符串。避免这种过时且麻烦的众多原因之一 class.
我怀疑您的“tzdata”时区数据文件已过时,无法识别 DST 转换的新日期。
重新启动 JVM
Java 实现通常在启动时从主机 OS 中获取它们当前的默认时区。在JVM之后,更改主机OS'时区对JVM没有影响。
重新启动 JVM 以获取主机 OS 中的新区域设置。
在服务器上使用 UTC
最佳做法通常是将您的服务器设置为 UTC。那么你不必担心夏令时的废话。
在 UTC 工作
您的大部分编程、日志记录、cron 作业、数据交换和数据序列化都应该使用 UTC。
请注意,例如,Stack Overflow 如何使用 UTC 报告 "today" 和 "yesterday" 的 activity。学会将 UTC 视为唯一真实时间;所有区域都是该主题的变体。
仅在关键时应用时区,例如在向期望特定时区的用户进行演示时。
请记住,您的问题不是由于 space 时间弯曲造成的。秒、分和小时继续正常递增,就 UTC 而言,滴答滴答。您的问题在于错误翻译成具有过时时区规则更改数据的时区。
在 Java 代码中指定您想要的区域
您的 Java 应用应始终明确指定其 desired/intended 时区。如果省略,则隐式应用 JVM 当前的默认时区。
JVM 中的任何应用程序的任何线程中的任何代码都可以随时更改 JVM 默认设置,并立即影响该 JVM 中的所有其他代码。所以永远不要依赖当前的默认值来做任何重要的事情。与用户确认,并在您的代码中明确指定。
避免遗留日期时间 classes
包括 Date
和 Calendar
在内的旧日期时间 classes 真是一团糟。避开他们。它们现在是遗留的,被 java.time classes 取代。
Instant
class 是时间线上的一个时刻,分辨率以纳秒为单位,始终采用 UTC。
Instant instant = Instant.now() ;
要生成标准 ISO 8601 格式的字符串,请调用 toString
。最后的 Z
是 Zulu 的缩写,表示 UTC。
String output = instant.toString() ;
2017-01-23T12:34:56.123456789Z
使用这两行简单的代码就可以避免整个问题。
但是您应该定期更新以下位置的 tzdata:
- 主机OS
- JVM
- 数据库系统(Postgres等)
- Joda-Time 等库