【问题标题】:JVM and timezonesJVM 和时区
【发布时间】:2011-10-27 07:43:10
【问题描述】:

如果有人可以帮助我,我遇到了 java 时区问题。

我有一个在 tomcat 5.5 上运行的 Web 应用程序(不确定这是否相关),使用以下 JVM 版本

[someuser@webserver bin]$ java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)
[someuser@webserver bin]$

系统日期是-

[someuser@webserver bin]$ date
Mon Aug 15 09:09:46 EST 2011

在 Web 应用程序中,我在某个时间点调用 Calendar.getInstance().getTime(),并在日志中打印此时间戳。

问题是这个时间戳在 EDT 中返回,尽管服务器的时间是在 EST 中。因此,返回的日期比应有的晚 1 小时。

我想要实现的是让Calendar.getInstance().getTime() 返回与系统在同一时区的日期。

我搜索了论坛,发现了一些关于 jvm 没有正确读取系统时区的建议。 我尝试使用-Duser.timezone=EST 参数启动tomcat,但系统不断返回EDT 时区的时间戳。请注意 - 尝试使用非 est 参数的 -Duser.timezone 似乎有效。 这些问题似乎具有不同的性质。

我的问题与this SO question 有点相似。但是,我只是想获取与系统所在时区相同的日期,没有任何特殊处理。

你能帮忙吗?

【问题讨论】:

  • 请记住,如果您只是在寻找具有当前时间的日期对象,您可以调用 new Date() 而不是使用日历。但是,您仍然需要按照 Mauricio 的建议设置默认时区。
  • 您可能已经知道,但 EDT 和 EST 是有/没有 DST 的同一时区。 8 月通常是 EDT,因此实际上在美国没有 8 月的 EST。 en.wikipedia.org/wiki/Eastern_Time_Zone
  • 是的,我认为这个问题可能与此有关,因为例如 -Duser.timezone=AET 有效。但是,我正在寻找解决此问题的永久方法,而不是解决方法。

标签: java timezone


【解决方案1】:

我有同样的问题。对我来说,Java 是在寻找 /etc/sysconfig/clock 文件而不是 /etc/localtime 文件。这是more info的评论

【讨论】:

    【解决方案2】:

    EST 和 EDT 非常具体,其中一个总是“错误”,具体取决于一年中的时间。尝试使用“America/New_York”时区来简单地了解“纽约的时间”。

    例如

        DateFormat formatterET = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
        formatterET.setTimeZone(TimeZone.getTimeZone("America/New_York"));
    
        String timestamp = formatterET.format(new Date());
    

    有用的时区列表:

    https://calendar.york.ac.uk/en/chcncpt.html#wp1056628

    【讨论】:

    • 您好,感谢您的回答。虽然我知道一些解决方法是可能的,但我想解决真正的问题。我的问题,总而言之是:“如何让 JVM 读取系统的时区并默认使用它”
    • 我明白你的意思;如果您找不到更明确的答案,也许可以考虑这是一种解决方法,它应该具有相同的效果。有兴趣看看有没有答案,目前不知道有这样的设置。
    【解决方案3】:

    这很简单,在你的应用程序主方法(或 servlet 上下文)中添加这个:

    TimeZone.setDefault( TimeZone.getTimeZone("GMT-4") );
    

    这会设置系统中所有日期的时区。

    【讨论】:

    • 注:请注意,此方法仅在 JVM 实例的生命周期内有效,例如将无法在 Tomcat 重新启动后继续存在。
    • 是的,这就是为什么你应该将它添加到 servlet 上下文监听器或类似的东西,确保它在你的应用程序加载时运行。
    • 您好,感谢您的回答。虽然我知道一些解决方法是可能的,但我想解决真正的问题。我的问题,总而言之是:“如何让 JVM 读取系统的时区并默认使用它”
    • fyi - 我刚刚了解到 TimeZone.setDefault() 的行为不同,具体取决于是否存在 SecurityManager(如 Tomcat 等),在这种情况下,设置默认时区的效果具有线程本地范围,并且JVM 的其余部分不会看到它。见:stackoverflow.com/a/9891971/516910
    【解决方案4】:

    我不确定这在 Java 中是否真的可行,但如果是这样,那肯定不是其他人所说的事实上的做事方式。请参阅 here 了解 Oracle 对此事的说明,特别是:

    Java SE 平台的时区数据不是从本地或主机操作系统 (OS) 读取的,因此操作系统时区补丁不会更新 JRE 软件的时区数据。

    【讨论】:

      【解决方案5】:

      我在 ubuntu 服务器上遇到了同样的问题,找不到 /etc/sysconfig/clock 文件。

      我解决了它使用timedatectl 设置时区。

      sudo timedatectl set-timezone America/New_York
      

      【讨论】:

        【解决方案6】:

        EDT 和 EST - 这是同一个地理区域。但是 EST 是标准时间,它只在冬季有效(在某些地方甚至在夏季),而 EDT 是夏令时对应的。 您的问题可能与夏令时运动有关,所以我会深入这个方向。 您还可以通过设置默认时区来指定特定时区(通常以国家/城市格式),但在这种情况下,您应该确保不会与您的服务器当前时区和您指定为默认时区发生任何冲突。

        【讨论】:

        • 抱歉,我认为它们之间有什么区别并不重要。我想要的只是 JVM 报告与系统时钟相同的时间/时区。
        【解决方案7】:

        在 Linux 上,这有点烦人,因为很长一段时间 Java(至少是 Oracle/Sun Java)都使用了错误的方法(好吧,我想它在开始时错误较少,但事情已经改变了。)

        我最好的建议是设置 TZ 环境变量,因为这是它首先要寻找的;它看起来的其他地方(例如/etc/sysconfig/clock、/etc/localtime)有故障。我在http://distracted-it.blogspot.co.nz/2014/09/dont-let-java-on-linux-determine-its.html 有一篇关于它的更详细的帖子,其中包括一些背景参考和验证步骤。

        -Duser.timezone=Pacific/Auckland 也可以,但是我试过了,不行。

        如果设置 TZ,您应该确保将其设置在适当的位置。例如,在 WebLogic 中间件容器中,您应该在 setDomainEnv.sh 中设置它,因为 WebLogic 将首先清理环境并且不会看到 TZ(我的帖子显示了如何验证 JVM 进程是否正在看到它。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-24
          • 1970-01-01
          • 2011-03-27
          • 2012-05-04
          • 2019-02-19
          • 1970-01-01
          • 2011-12-12
          相关资源
          最近更新 更多