Joda Time给出了错误的时区

时间:2009-11-11 10:23:37

标签: java jodatime

我正在使用Joda time(1.6)库并且它使用错误的时区(英国夏令时而不是GMT)继续返回DateTime对象。

我的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"

2 个答案:

答案 0 :(得分:30)

好的,要了解这一点,你必须熟悉英国夏令时的实际意义以及它何时到位。为简短起见,您将0L传递给getName() 1970-01-01T00:00:00Z DefaultTimeZone,以便1970-01-01T00:00:00Z在此时查找时区名称。这是英国夏令时。

  

来自:http://www.nmm.ac.uk/explore/astronomy-and-time/time-facts/british-summer-time

     

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

如果您从defaultTimeZone.getName(new GregorianCalendar().getTimeInMillis()) 开始传递适当的毫秒数。例如通过做

getName()

你也会得到正确的字符串。基本上你只是用org/joda/time/tz/src方法输入了错误的参数,结果出现了意想不到的结果。

如果您想详细检查joda源代码defaultTimeZone.getName(0L) 中的文件,请查看joda如何确定时区。


而不是

defaultTimeZone.toTimeZone().getDisplayName()

你可以使用

{{1}}

这适合我。

答案 1 :(得分:0)

您可能会感兴趣的是在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区域,现在都会被接收。