【问题标题】:Joda Time gives wrong time zoneJoda Time 给出了错误的时区
【发布时间】:2009-11-11 10:23:37
【问题描述】:

我正在使用 Joda time (1.6) 库,它不断返回带有错误时区的 DateTime 对象,即英国夏令时而不是 GMT。

我的 Windows 工作站(运行 JDK 1.6.0_16)认为它在 GMT 中,如果我从 JDK 日期/时间类中获得默认时区,则它是正确的 (GMT)。我在我们的 Linux 服务器上也得到了相同的行为。我认为这可能是 Joda 中的时区数据库文件中的错误,所以我用最新的数据库重建了 jar,但没有任何变化。

import java.util.TimeZone;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

public class TimeZoneTest {

    public static void main(String[] args) {                
        DateTimeFormatter timeParser = ISODateTimeFormat.timeParser();
        TimeZone timeZone = TimeZone.getDefault();
        System.out.println(timeZone.getID()); // "Europe/London"
        System.out.println(timeZone.getDisplayName()); // "Greenwich Mean Time"

        DateTimeZone defaultTimeZone = DateTimeZone.getDefault();
        System.out.println(defaultTimeZone.getID()); //"Europe/London"
        System.out.println(defaultTimeZone.getName(0L)); //"British Summer Time"

        DateTime currentTime = new DateTime();
        DateTimeZone currentZone = currentTime.getZone();
        System.out.println(currentZone.getID()); //"Europe/London"
        System.out.println(currentZone.getName(0L)); //"British Summer Time"            
    }
}

通过org.joda.time.DateTimeZone 中的静态初始化程序进行调试我看到System.getProperty("user.timezone") 调用按预期给出了"Europe/London"

【问题讨论】:

  • 扩展答案以提供实际问题的解释

标签: java jodatime


【解决方案1】:

好的,要了解这个问题的根源,您必须熟悉英国夏令时的实际含义以及它的实施时间。简而言之,您将0L 传递给getName(),即1970-01-01T00:00:00Z,因此DefaultTimeZone 会在此时查找时区的名称。那是英国夏令时。

发件人:http://www.nmm.ac.uk/explore/astronomy-and-time/time-facts/british-summer-time

1968 年,时钟提前一小时 在 2 月 18 日格林威治标准时间之前和 一直如此,直到英国标准 时间,在此期间保持时钟 GMT 全年提前,进入 1968 年 10 月 27 日至 31 日之间的部队 1971 年 10 月。

如果您改为从1970-01-01T00:00:00Z 开始传递正确的毫秒数。例如通过做

defaultTimeZone.getName(new GregorianCalendar().getTimeInMillis())

你也会得到正确的字符串。基本上你只是给 getName() 方法提供了错误的参数,因此导致了意想不到的结果。

如果您想详细检查,请查看 joda 源的 org/joda/time/tz/src 中的文件,以了解 joda 如何确定时区。


而不是

defaultTimeZone.getName(0L)

你可以使用

defaultTimeZone.toTimeZone().getDisplayName()

这对我有用。

【讨论】:

  • 太棒了。谁能想到。我确实说过“1970 年 1 月 1 日不可能是英国夏令时”。更愚弄我。这也解释了导致问题的根本问题,即使用 ISODateTimeFormat.timeParser() 解析“10:00:00.0000000+00:00”导致 GMT+1 中的 DateTime。这是因为 Joda 没有独立的时间和日期概念,因此将这个时间解析为相对于 1970 年 1 月 1 日,正如您所指出的那样,它是 GMT+1!疯狂的。谢谢。
【解决方案2】:

您可能会对 1.6 中的 DateTimeZone 类的静态初始化程序感兴趣:

static {
    setProvider0(null);
    setNameProvider0(null);

    try {
        try {
            cDefault = forID(System.getProperty("user.timezone"));
        } catch (RuntimeException ex) {
            // ignored
        }
        if (cDefault == null) {
            cDefault = forTimeZone(TimeZone.getDefault());
        }
    } catch (IllegalArgumentException ex) {
        // ignored
    }

    if (cDefault == null) {
        cDefault = UTC;
    }
}

我的猜测是您定义了 user.timezone 属性(并设置为 BST)。否则,看起来 Joda 应该根据 JDK 时区创建自己的时区实例;我希望这个区域中的任何错误,尤其是转换 GMT 区域,现在都会被发现。

【讨论】:

  • user.timezone 给出“欧洲/伦敦”(我已将此添加到问题中)。
猜你喜欢
  • 2015-10-19
  • 1970-01-01
  • 2011-06-18
  • 2012-07-22
  • 1970-01-01
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
相关资源
最近更新 更多