ZonedDateTime 的 GMT 和 UTC 是否相同?
Is GMT and UTC same for ZonedDateTime?
我已经实现了一个 API 供国际使用,我正在尝试 return ISO 8601 格式的格林威治标准时间对象日期。现在我通过
ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)
但我知道 UTC 和 GMT 不是一回事。
稍后我将为每个用户分配他们的首选 Locale 并 return 分配给他们的 Locale ,但现在我想在 GMT 时执行此操作,但我不知道如何以正确的方式进行
TL;DR
ZonedDateTime
UTC 和 GMT 的名称不同,但时区规则相同,因此 UTC 和 GMT 的时间始终相同。
理论
最初 GMT 和 UTC 的定义不同。 UTC 时间和 GMT 时间之间的时间从来不会超过一秒。由于 UTC 已成为无处不在的时间锚点,因此 GMT 有时被宽松地用来表示 UTC,因此区分更加模糊。
练习:ZonedDateTme
A 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);
输出为:
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
if 时间zone 使用常量偏移量。在这两种情况下,我们得到的偏移量都为零。所以这里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));
刚才的输出:
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
您还写道:
Later I will be assigning every user with their preferred Locale and
return with their Locale …
Locale
与此处无关。语言环境和时区是正交的概念。例如,访问上海的土耳其人可能想要使用土耳其语言环境和上海时区。无法从语言环境推断出时区(至少没有可靠的方法)。您可能需要考虑为每个用户分配一个首选时区。
我已经实现了一个 API 供国际使用,我正在尝试 return ISO 8601 格式的格林威治标准时间对象日期。现在我通过
ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)
但我知道 UTC 和 GMT 不是一回事。
稍后我将为每个用户分配他们的首选 Locale 并 return 分配给他们的 Locale ,但现在我想在 GMT 时执行此操作,但我不知道如何以正确的方式进行
TL;DR
ZonedDateTime
UTC 和 GMT 的名称不同,但时区规则相同,因此 UTC 和 GMT 的时间始终相同。
理论
最初 GMT 和 UTC 的定义不同。 UTC 时间和 GMT 时间之间的时间从来不会超过一秒。由于 UTC 已成为无处不在的时间锚点,因此 GMT 有时被宽松地用来表示 UTC,因此区分更加模糊。
练习:ZonedDateTme
A 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);
输出为:
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
if 时间zone 使用常量偏移量。在这两种情况下,我们得到的偏移量都为零。所以这里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));
刚才的输出:
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
您还写道:
Later I will be assigning every user with their preferred Locale and return with their Locale …
Locale
与此处无关。语言环境和时区是正交的概念。例如,访问上海的土耳其人可能想要使用土耳其语言环境和上海时区。无法从语言环境推断出时区(至少没有可靠的方法)。您可能需要考虑为每个用户分配一个首选时区。