java不正确的时区

时间:2010-01-21 02:31:38

标签: java timezone

我有一个Java实例,它似乎使用了一个完全不正确的时区。它使用的是美国/加拉加斯时区,而不是使用Windows正在使用的澳大利亚/悉尼时区。

我首先通过系统时钟检查了Windows时间,然后检查了HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ControlSet001ControlSet002。所有都设在悉尼时区。

有人知道这是Java中的错误,还是指其他地方设置的时间?

Java版本是1.6.0_06

10 个答案:

答案 0 :(得分:12)

确保在启动应用程序时设置JVM的时区:

-Duser.timezone="Australia/Sydney"

答案 1 :(得分:6)

检查以下链接的信息: http://techtavern.wordpress.com/2010/04/15/java-and-incorrect-timezone-on-windows-xp/
 它表明,JVM中存在一个错误,导致从Windows注册表中读取不正确的默认时区。还没有错误修复。

答案 2 :(得分:5)

您应该更新JRE/SDK,但TZUpdater可能就足够了。

答案 3 :(得分:2)

尝试使用您的应用获取默认时区,或手动设置时区(注释行)。

我的小例子:

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Locale locale = Locale.getDefault();
        TimeZone localTimeZone = TimeZone.getDefault(); 
        //TimeZone localTimeZone = TimeZone.getTimeZone("Australia/Sydney");
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale);
        dateFormat.setTimeZone(localTimeZone);
        Date rightNow = new Date();
        System.out.println(locale.toString() + ": " + dateFormat.format(rightNow));
    }
}

答案 4 :(得分:2)

我最近遇到了同样的问题,显然这是由于Windows在注册表中代表其时区设置以及Java无法正确解释它的模糊性造成的。

可以在this article中找到更多详细信息,其中还介绍了受影响计算机的“治愈方法”:

  
      
  • 手动更改日期/时间,然后再更改回原始正确时间。
  •   
  • 更改时区,然后返回原始时区。
  •   
  • 请求从时间服务器自动更新时间。
  •   

答案 5 :(得分:1)

有这样的问题的历史来来往往,没有合理的解决方案。点击此处:Java incorrect time zone bug on Windows

编辑:回答Tom和francis:简而言之,Java运行时很难正确地找到计算机上当前时区的工作。

关于时区的Windows注册表信息不可靠,对于依赖于msvcrt.dll和各种msvcrxx.dll的本机Windows API也是如此。还有Managed(.NET)API需要安装某个版本的.NET Framework,这与Java的可移植性相矛盾。

因此,Java运行时的开发人员很难在Windows上使用当前时区,这可能会持续到微软有一些合作的理由。

如果您希望Java应用程序在任何时区正常工作,请让用户通过GUI更正时区。

答案 6 :(得分:0)

我有同样的错误,当我将我的时区设置为马来半岛标准时间时,JVM给了我委内瑞拉时间时区。

以下修复程序适用于我:

在注册表编辑器中,将您的时区编辑到另一个时区(我试图添加另一个文本,如“新加坡时间”。您可以在此处找到注册表:

HKEY_LOCAL_MACHINE /系统/ CurrentControlSet /控制/ TimeZoneInformation

然后,我使用“控制面板”,“日期和时间”设置将其重置回我想要的时区。 当我回到注册表编辑器时,我可以看到它被恢复为马来半岛标准时间。我的JVM现在正确读取它......

答案 7 :(得分:0)

tl; dr

Java程序员切勿依赖JVM当前的默认时区。

  • 始终以Continent/Region的格式指定proper time zone name,例如Africa/Casablanca
  • 重要时始终与用户确认期望/期望的区域。

正确的时区名称

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如CSTESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。例如,如果您将IST用作爱尔兰标准时间,则可能会获得令人惊讶的印度标准时间。

ZoneId z = ZoneId.of( "America/Montreal" ) ; // Or "Pacific/Auckland", "Africa/Tunis", etc. 

指定时区

从不依赖JVM当前的默认时区。该默认值可以更改。

  • 正如其他答案所解释的那样,大多数JVM默认情况下会在启动JVM时使用主机操作系统的默认时区。
  • 或者启动JVM的脚本可能会传递一个标志,以在启动时指定默认时区。
  • 并且在运行时(!)期间,可以通过JVM中调用TimeZone.setDefault的任何应用程序的任何线程中的任何代码来设置JVM当前的默认时区。 (顺便说一下,TimeZoneZoneId已使ZoneOffset被过时了,除了那个setter方法,除非在最极端的情况下才应该调用它。)
  • 当然,用户或sysadmin可以更改主机操作系统上当前的默认时区,据我所知,在大多数实现中,运行JVM无法检测到它们的

因此,由于所有这些原因,JVM的当前默认时区完全不在程序员的掌握范围内,更糟糕的是,它可以在运行时动态更改。因此,使用当前默认值是不可靠的。

仅出于最偶然的目的使用JVM当前的默认时区。对于任何重要的事情,您只需与用户确认目标区域。这是一个经常被程序员抵制的不便的事实,但是仍然如此。


语言环境

提示:Locale的同上。 JVM的当前默认语言环境可能与主机OS的语言环境匹配,也可能不匹配,可以随时更改,因此不可靠。始终与用户确认所需的{/ {1}}。


关于 java.time

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

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

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

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要Locale类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 8 :(得分:0)

如果时区似乎已完全消失,至少就我而言,在旧系统上使用Java 5而言,请确保%JAVA_HOME%\ jre \ lib \ zi文件夹中存在正确的文件。例如,对我而言,我无法让Europe / Athens终身为我服务。原来文件%JAVA_HOME%\ jre \ lib \ zi \ Europe \ Athens丢失了(那些指向各大洲的目录在我使用的JDK中是完全空的..)-与新下载的JDK 1.5进行了比较Oracle的.0_22。

答案 9 :(得分:0)

我解决了将其添加到我的数据库 URL 中的错误:

?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC