Joda时区不同于JDK的

时间:2010-12-07 08:36:09

标签: java jodatime

在我的客户端,我有这段代码:

System.out.println("Java tz: " + TimeZone.getDefault());
System.out.println("Joda tz: " + ISOChronology.getInstance());

这两条线一个接一个地运行。我从不手动设置时区或user.timezone,只需依靠从OS&读取的默认值。本地系统。

执行时,他们会产生:

Java tz: sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Joda tz: ISOChronology[America/Phoenix]

系统时区确实是凤凰城,而不是UTC。 Joda怎么能正确,JDK错了?

编辑:这是Windows 7 x64主机,JRE是1.6.22 x64。

编辑2 :不要尝试重现它。它只会在某些系统上失败,而不是所有系统(就像我们的3k用户群中的几十个)。我已经知道Joda检查user.timezone然后TimeZone.getDefault()。所以我正在寻找一个解释,说明我直接调用TimeZone和Joda自己调用它有什么不同。

1 个答案:

答案 0 :(得分:7)

当您说“从操作系统和本地系统读取默认值”时,没有一个明确定义的位置可以读取此默认值。甚至API文档本身都说

  

获取此主机的默认TimeZone。默认TimeZone的来源可能因实施而异。

所以简单的答案就是Joda和你的JVM从不同的信息源推断出默认时区。需要记住的是默认是猜测,而不是JVM可以最终获得访问权限的内容。

对于Linux上的Sun 1.5.0_06 JVM,使用以下顺序:

  1. 查看环境变量TZ
  2. 查找文件/ etc / sysconfig / clock并尝试查找“ZONE”条目。
  3. 递归地将/ etc / localtime的内容与/ usr / share / zoneinfo中的每个文件的内容进行比较。当内容匹配时,它返回从/ usr / share / zoneinfo。
  4. 引用的路径和文件名

    Joda 1.6.2使用:

    1. 系统属性user.timezone
    2. 如果以上是null或不是有效标识符,则使用JDK的TimeZone默认值。
    3. 如果失败,则使用UTC
    4. 所以如果你有以上版本的JDK和Joda,我建议你的环境中可以设置user.timezone属性。但是,其他版本可能会使用其他算法来获取默认值。

      编辑:在Sun的JDK 1.6.0_22中,默认搜索首先检查user.timezone属性,如果找不到,则查找user.country属性以获取默认值一个国家的价值。如果两者均未设置,则使用默认值GMT。因此,您观察到的结果可能会随JVM版本而改变。


      编辑2:如果您已获得两者的来源(实际上源都可用),那么您只需跟踪它!逐步执行Joda调用,看看它是否确实遵循java.util.TimeZone.getDefault(),并查看返回值是什么。然后直接调用JDK方法,看看你得到了什么。

      查看JDK源代码,似乎通过可继承的本地线程访问默认时区。因此,如果有人在某处调用TimeZone.setDefault(),它可能会在其他线程中显示,也可能不会显示,具体取决于他们是否已经查找了该版本。如果你通过调试调用得到明显异常的结果,很可能只是因为不同的线程可以有不同的默认时区