繁体   English   中英

ZonedDateTime 的 GMT 和 UTC 是否相同?

[英]Is GMT and UTC same for ZonedDateTime?

我已经实现了一个供国际使用的 API,我正在尝试以 ISO 8601 格式返回 GMT 时间的对象日期。 现在我这样做

ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)

但我确实知道 UTC 和 GMT 不是一回事。

稍后我将为每个用户分配他们首选的语言环境并返回他们的语言环境,但现在我想以 GMT 执行此操作,但我不知道如何以正确的方式进行操作

TL;博士

对于ZonedDateTime ,UTC 和 GMT 具有不同的名称,但区域规则相同,因此 UTC 和 GMT 的时间将始终相同。

理论

最初 GMT 和 UTC 的定义不同。 UTC 时间和 GMT 时间之间从来没有超过一秒。 由于 UTC 已成为无处不在的时间锚,GMT 有时被松散地用来表示 UTC,因此区分更加模糊。

练习:ZonedDateTme

ZonedDateTime使用ZoneId作为其时区,因此您的问题等于询问ZoneId GMT 和 UTC 是否相同。 让我们首先看看它们的外观:

    ZoneId utc = ZoneId.of("Etc/UTC");
    System.out.println("Etc/UTC:        " + utc);

    ZoneId gmt = ZoneId.of("Etc/GMT");
    System.out.println("Etc/GMT:        " + gmt);

    ZoneId utcNormalized = utc.normalized();
    System.out.println("UTC normalized: " + utcNormalized);

    ZoneOffset utcAsOffset = ZoneOffset.UTC;
    System.out.println("UTC as offset:  " + utcAsOffset);

    ZoneId gmtNormalized = gmt.normalized();
    System.out.println("GMT normalized: " + gmtNormalized);

Output 是:

 Etc/UTC: Etc/UTC Etc/GMT: Etc/GMT UTC normalized: Z UTC as offset: Z GMT normalized: Z

前两行告诉我们ZoneId确实可以区分 GMT 和 UTC。 它们都是具有各自时区 ID 的有效时区。

如果时区使用恒定偏移量,我用于第 3 行和第 5 行的normalized()方法承诺将ZoneId转换为ZoneOffset 在这两种情况下,我们都会得到零偏移。 所以这里ZoneId不区分。

要更仔细地检查此事:

    System.out.println("Are GMT and UTC the same? " + utc.equals(gmt));
    System.out.println("Are GMT and UTC the same? "
            + utcNormalized.equals(gmtNormalized));
    System.out.println("Are GMT and UTC the same? "
            + utc.getRules().equals(utcAsOffset.getRules()));
 Are GMT and UTC the same? false Are GMT and UTC the same? true Are GMT and UTC the same? true

所以ZoneId对象不相等,使用这两者的ZonedDateTime对象也不相等,即使它们具有相同的日期和时间。 但是我们从它们那里得到相同的偏移量并且它们具有相同的区域规则,也就是说,它们总是具有相同的时间。

Java 代码中的后果

此行来自您的问题:

ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)

这是正确的,没有令人信服的理由让您不这样做。 如果您愿意,由于 Java 将 UTC 视为区域偏移,您可以改为转换为OffsetDateTime 我以某种方式认为它不如ZonedDateTime

如果您希望ZonedDateTime以 GMT 而不是 UTC 打印,请使用ZoneId.of("Etc/GMT") 在这里,我使用的是在持有该时区之前的变量:

    ZonedDateTime zdtGmt = ZonedDateTime.now(ZoneId.of("Asia/Istanbul"))
            .withZoneSameInstant(gmt);
    System.out.println("Time in GMT: " + zdtGmt);
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
            .withLocale(Locale.forLanguageTag("tr"));
    System.out.println("Time in GMT: " + zdtGmt.format(formatter));

刚才的Output:

 Time in GMT: 2020-05-16T09:34:05.253696Z[Etc/GMT] Time in GMT: 16 Mayıs 2020 Cumartesi 09:34:05 Greenwich Ortalama Saati

你进一步写道:

稍后我将为每个用户分配他们喜欢的语言环境并返回他们的语言环境......

Locale在这里不相关。 区域设置和时区是正交概念。 例如,来自土耳其的访问上海的人可能想要使用土耳其语言环境和上海时区。 没有办法从语言环境中推断出时区(至少没有合理的方式)。 您可能需要考虑为每个用户分配一个首选时区。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM