JVM 时区关闭一小时

JVM Timezone is off by one hour

在 Windows XP 机器上使用 Java 6 更新 30。更新 Java 或 Windows 不是一个选项。

我需要一种方法来将内部 Java 时钟调慢一小时以匹配系统时间。机器在俄罗斯,Windows 系统时间是正确的,但 Java 时间偏差一小时,可能是夏令时的缘故。

我试过 changing JVM parameters as well as modifying the deployment.properties file (to change the timezone), adding a variable to the environment/system variables path also did not work, and attempted the timezone updater tool Oracle 提供的。前三个不更改任何参数并且更新程序工具崩溃,并显示 "Cannot find JRE/JDK files".

有没有其他方法可以permanently/properly更改Java正在使用的时间。

示例: 当前时间:7:20:17 PM 时区:sun.util.calendar.ZoneInfo [id="Europe/Moscow",offset=14400000,dstSavings=0,useDaylight=false,transitions=78,LastRule=null]

所需时间:6:20:17 下午时区:sun.util.calendar.ZoneInfo [id="Europe/Moscow",偏移量=14400000,dstSavings=0,useDaylight=false,transitions=78,LastRule=null]

由于您的前两个选项 - 升级 JVM 和使用 tzupdater - 不可行,您将不得不使用变通方法。您可以使用 user.timezone 属性 设置 JVM 的默认时区。您需要将时区设置为与实际时区相差一小时的时区,以补偿 2014 年的变化。

可用的俄罗斯时区是

Europe/Kaliningrad
Europe/Moscow
Europe/Samara
Europe/Volgograd
Asia/Yekaterinburg
Asia/Novokuznetsk
Asia/Novosibirsk
Asia/Omsk
Asia/Krasnoyarsk
Asia/Irkutsk
Asia/Yakutsk
Asia/Sakhalin
Asia/Vladivostok
Asia/Anadyr
Asia/Kamchatka
Asia/Magadan

当尝试从 Glassfish Java Server 获取当前时间并收到不正确的时间戳时会出现此问题。要更改时区,必须找到 domain.xml 文件并添加新时区。

  1. 打开文件domain.xml
  2. 查找其他 标签
  3. 添加-Duser.timezone="Europe/Berlin"(或其他时区)
  4. 重新启动 Glassfish,希望它会有所改变。

tl;博士

ZonedDateTime.now( 
    ZoneId.of( "Europe/Moscow" )
)

他们的时代 A-Changin'

Java 6 更新 30 附带 Olson 时区数据版本 2011l,根据 Update Release Notes. FYI, the Olson database is now known as the ‘tz database’ 或‘tzdata’。

从那时起,俄罗斯对其时区定义进行了多次更改。这使得您的 Java 安装 out-of-date。因此,您必须更新时区数据库或使用替代方法。

您说您尝试更新时区数据但失败。

ThreeTen-Backport 项目

另一种选择是 back-port 来自 java.time 类 的大部分技术现在取代了麻烦的旧 date-time 类 例如DateCalendar。那些旧的 类 现在是遗留的,应该避免。在 ThreeTen-Backport project, and carries its own copy of tzdb. You can add this library to your project, and replace it as needed with future updates to the tzdata. See the documentation to update tzdb. By the way, the "ThreeTen" refers to JSR 310.

中找到 back-port

因此,就您的 Java 代码而言,您无需关心主机操作系统自身的时区数据是否为 ​​out-of-date,因为我们没有使用它。 JVM 自己的时区数据也是如此,我们没有使用它。通过仅使用 ThreeTen-Backport 类,我们使用作为该库的一部分提供的时区数据。而且我们可以轻松地使时区数据保持最新。

Instant

Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant instant = Instant.now();

instant.toString(): 2017-01-16T07:43:24.130Z

ZonedDateTime

应用 ZoneId 得到代表特定区域 wall-clock timeZonedDateTime 对象。

ZoneId z = ZoneId.of( "Europe/Moscow" );
ZonedDateTime zdt = instant.atZone( z );

zdt.toString(): 2017-01-16T10:43:24.130+03:00[Europe/Moscow]

作为快捷方式,您可以跳过处理 Instant,并调用 ZonedDateTime.now( z )

参见 live code in IdeOne.com

指定时区

Question: … Is there any other way to permanently/properly change the time that Java is using

始终传递特定的 ZoneId 而不是省略任何可选的时区参数。省略时,您将隐式依赖 JVM 当前的默认时区。 JVM 中任何应用程序的任何线程中的任何代码都可以随时更改该默认值。所以我强烈建议您始终明确指定您的desired/expected时区


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time类?

  • Java SE 8 and SE 9 及更高版本
    • Built-in。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
    • 许多 java.time 功能在 ThreeTen-Backport 中被 back-port 编辑为 Java 6 和 7。
  • Android
    • ThreeTenABP 项目专门为 Android 改编 ThreeTen-Backport(如上所述)。
    • 参见