13

我正在使用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"按预期给出。

4

2 回答 2

30

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

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

1968 年,时钟在 2 月 18 日比格林威治标准时间提前一小时,并且一直保持到英国标准时间,在此期间,时钟全年保持在格林威治标准时间之前,在 1968 年 10 月 27 日至 1971 年 10 月 31 日期间生效。

相反,如果您会传入正确的毫秒数,因为1970-01-01T00:00:00Z. 例如通过做

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

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

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


代替

defaultTimeZone.getName(0L)

你可以使用

defaultTimeZone.toTimeZone().getDisplayName()

这对我有用。

于 2009-11-11T10:40:31.020 回答
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 区域,现在都会被发现。

于 2009-11-11T10:34:40.233 回答