Joda 时间给出了错误的时区

2022-09-04 06:59:04

我正在使用Joda时间(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.DateTimeZoneSystem.getProperty("user.timezone")"Europe/London"


答案 1

好吧,要找到这个根源,你必须熟悉英国夏令时的实际含义以及它何时到位。为了缩短它,你传递到哪个,所以查找当时区的名称。那是英国的夏令时。0LgetName()1970-01-01T00:00:00ZDefaultTimeZone

寄件人: 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()

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


而不是

defaultTimeZone.getName(0L)

您可以使用

defaultTimeZone.toTimeZone().getDisplayName()

这为我做到了。


答案 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;
    }
}

我的猜测是,您定义了一个属性(并设置为BST)。否则,看起来Joda应该基于JDK时区创建自己的时区实例;我预计这个领域的任何错误,特别是转换GMT区域,现在都会被发现。user.timezone


推荐