【问题标题】:JVM Timezone is off by one hourJVM 时区关闭一小时
【发布时间】:2023-03-24 19:17:01
【问题描述】:

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

我需要一种方法将内部 Java 时钟改回一小时以匹配系统时间。机器在俄罗斯,Windows 系统时间正确,但 Java 时间差一小时,可能是由于 DST。

我尝试了changing JVM parameters 以及修改deployment.properties 文件(更改时区),在环境/系统变量路径中添加变量也不起作用,并尝试了Oracle 提供的timezone updater tool。前三个不更改任何参数,更新工具崩溃,并显示“找不到 JRE/JDK 文件”。

有没有其他方法可以永久/正确更改 Java 使用的时间。

示例: 当前时间:晚上 7:20:17 时区: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", offset=14400000, dstSavings=0, useDaylight=false, transitions=78, LastRule=null]

【问题讨论】:

  • 在您的“当前”和“必需”示例中,TimeZone 对象没有任何区别。如果问题出在时区,应该会有一些差异。
  • 您是对的,因为去年俄罗斯时间发生了变化,您需要更新您的时区文件。所以你需要弄清楚你使用 tzupdater 有什么问题。你究竟是如何运行它的,结果如何?
  • 当我运行 tzupdater 工具时,我得到的唯一输出是找不到 JRE/JDK 文件。
  • iana.org/time-zones/repository/releases/tzcode2014f.tar.gz 该工具似乎只适用于 linux 机器,因为它必须使用 make。
  • Java 使用 tzdata 但不使用 tzcode。它使用自己的时区信息格式,因此需要 tzupdater 等工具。

标签: java datetime jvm hour


【解决方案1】:

由于您的前两个选项 - 升级 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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      tl;博士

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

      他们正在改变的时代

      根据Update Release Notes,Java 6 Update 30 随附 Olson 时区数据版本 2011l。仅供参考,Olson 数据库现在称为‘tz database’ 或“tzdata”。

      从那时起,俄罗斯的时区定义经历了多次变化。这会使您的 Java 安装过时。因此,您必须更新时区数据库或使用替代方法。

      您说您尝试过但未能更新时区数据。

      ThreeTen-Backport 项目

      另一种方法是将 java.time 类中的大部分技术向后移植,这些类现在取代了麻烦的旧日期时间类,例如 DateCalendar。那些旧的类现在是遗留的,应该避免。反向端口位于ThreeTen-Backport 项目中,并带有自己的tzdb 副本。您可以将此库添加到您的项目中,并根据需要将其替换为 tzdata 的未来更新。请参阅documentation to update tzdb。顺便说一句,“ThreeTen”指的是JSR 310

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

      Instant

      Instant 类表示UTC 中时间轴上的时刻,分辨率为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[欧洲/莫斯科]

      作为一种捷径,您可以跳过处理Instant,直接调用ZonedDateTime.now( z )

      live code in IdeOne.com

      指定时区

      问题:……有没有其他方法可以永久/正确更改 Java 使用的时间

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


      关于java.time

      java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

      Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      从哪里获得 java.time 类?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-26
        • 2021-01-17
        • 1970-01-01
        • 2011-10-27
        • 2018-04-26
        • 2016-08-21
        • 2017-04-09
        相关资源
        最近更新 更多