java Joda Time 给出了错误的时区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1714300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:42:05  来源:igfitidea点击:

Joda Time gives wrong time zone

javajodatime

提问by matthewKizoom

I'm using the Joda time(1.6) libraries and it keeps returning DateTime objects with the wrong time zone, British Summer Time instead of GMT.

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

My Windows workstation (running JDK 1.6.0_16) thinks it's in GMT and if I get the default time zone from the JDK date/time classes it is correct (GMT). I get the same behaviour on our Linux servers as well. I thought it could be an error in the time zone database files in Joda so I rebuilt the jar with the latest database but with no change.

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

Debugging through the static initialiser in org.joda.time.DateTimeZoneI see that the System.getProperty("user.timezone")call gives "Europe/London"as expected.

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

回答by jitter

Ok, to get to the root of this you have to familiarize with what British Summer Time actually means and when it was in place. To make it short you pass 0Lto getName()which is 1970-01-01T00:00:00Zso DefaultTimeZonelooks up the name of the timezone at that moment. Which was British Summer Time.

好的,要找到这个问题的根源,您必须熟悉英国夏令时的实际含义以及它何时到位。为了简短起见,您传递0LgetName()which is 1970-01-01T00:00:00ZsoDefaultTimeZone查找当时时区的名称。那是英国夏令时。

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

In 1968 clocks were advanced one hour ahead of GMT on 18 February and remained so until British Standard Time, during which clocks were kept in advance of GMT all year, came into force between 27 October 1968 and 31 October 1971.

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

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

If you instead would pass in the right amount of milliseconds since 1970-01-01T00:00:00Z. e.g. by doing

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

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

You would get the correct string too. Basically you just fed the getName()method the wrong parameter thus ended up with an unexpected result.

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

If you want to check in detail check the files in org/joda/time/tz/srcof joda source to see how joda determines time zones.

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



Instead of

代替

defaultTimeZone.getName(0L)

you could use

你可以用

defaultTimeZone.toTimeZone().getDisplayName()

which does it for me.

这对我有用。

回答by Andrzej Doyle

It may interest you to see the static initialiser for the DateTimeZone class in 1.6:

您可能会对 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;
    }
}

My guess is that you have a user.timezoneproperty defined (and set to BST). Otherwise, it looks like Joda should create its own timezone instance based on the JDK time zone; and I'd expect any bugs in this area, especially converting a GMT zone, would have been picked up by now.

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