【问题标题】:Correct ZoneId for eastern time (ET): either "US/Eastern" or "America/New_York"?东部时间 (ET) 的正确 ZoneId:“US/Eastern”还是“America/New_York”?
【发布时间】:2019-06-25 16:51:54
【问题描述】:

我必须使用时区“ET”(东部时间)。在 Java 中,没有 ZoneId.of("ET")。

我应该使用哪一个来正确表示“ET”:

ZoneId TIMEZONE_ET = ZoneId.of("US/Eastern");

ZoneId TIMEZONE_ET = ZoneId.of("America/New_York");

【问题讨论】:

  • 您是否阅读了 ZoneId 的 javadoc?它解释了这些名称的来源及其优先级。
  • @JClassic 不是一个好主意..如果我使用它,我必须每年更改 1 次..
  • @YCF_L - 不,我很确定US/Eastern 是东部地区,这是一年中的东部时间和东部时间的一部分。 ZoneId.of("US/Eastern").getRules().isDaylightSavings(Instant.parse("2019-07-01T00:00:00Z")) 返回true,它不会在东部标准时间。
  • 除非纽约更改其时区,使其不再位于东部时区,否则我看不出这有什么关系。但是考虑到 “我必须使用时区“ET”(东部时间)......” 那么......这就是我会做的。
  • @nimo23 - 自从你接受它以来,我已经在很大程度上改变了我的答案。我想我应该提请您注意US/Eastern 已经过时并且可能已被弃用的事实。查看我的编辑和问题的其他答案。

标签: java timezone


【解决方案1】:

鉴于您的要求是使用“东部区域”,我会使用US/Eastern,但请注意:

  • 这只是指向America/New_York 的链接。
  • This file 在 Paul Eggert 的 tz repo 中说这些链接是将“旧”名称(例如美国/东部)链接到当前名称。在这种情况下,“旧”可能意味着“已弃用”。 Paul Eggert 是 IANA 时区列表的 TZ 协调员,因此这是一个明显的规范来源。

鉴于此,您可能最好使用 America/New_York,但鉴于该更改被列为 1993 年以来的更改,显然旧名称不会很快消失。

要么包含夏令时规则等。例如在我的系统上:

var zoneRules = ZoneId.of("US/Eastern").getRules();
System.out.println(zoneRules.isDaylightSavings(Instant.parse("2019-07-01T12:00:00Z"))); // true
System.out.println(zoneRules.isDaylightSavings(Instant.parse("2019-01-01T12:00:00Z"))); // false

请注意,7 月 1 日中午是 DST,而 1 月 1 日中午不是。

更多:

IANA Time Zone Database files,我发现:

to2050.tzs:

链接美国/纽约美国/东部

...这表明两者是别名(尽管ZoneId#equals 不会为它们返回true)。此外,在northamerica 他们有:

#美国东部时间,以纽约为代表

附有引用相关法律的注释。

所以我现在很清楚,它们是同义词。很明显US/Eastern 是“旧名称”。当然,理论上,纽约可以在某个时候决定不再成为东部时区的一部分(也许在时间上更接近英国和欧洲),但这似乎 真的不太可能……

【讨论】:

  • 很好的答案。最后一点非常重要。如果纽约移动到其他时区(例如大西洋时间),则必须更新来自US/Eastern 的链接以指向其他地方(可能是新时区)。另外值得指出的是,印第安纳州和肯塔基州的一些城市当前在东部时间过去几年已经偏离中部时间,并且它们有自己的 TZDB 标识符。还要考虑到夏令时在其中一些地区有所不同(例如,1970 年代的底特律),而加拿大东部时间最好由 America/Toronto 代表。
【解决方案2】:

美国/纽约

答案在List of tz database time zones:US/Eastern 已弃用,只是指向 America/New_York 的链接。因此,为了确保未来的兼容性,您应该使用 America/New_York。

关于时区名称的维基百科

The Wikipedia article tz database 说(摘录):

时区具有“区域/位置”形式的唯一名称,例如 “美国/纽约”。 …

Area 是大陆、海洋或“等”的名称。目前使用的大陆和海洋是非洲、美洲、南极洲、北极、 亚洲、大西洋、澳大利亚、欧洲、印度和太平洋。

位置是该区域内特定位置的名称——通常是城市或小岛。

此方案中未使用国家/地区名称,主要是因为它们 由于频繁的政治和边界变化,不会很强大。 大城市的名称往往更永久。 …

因此,US/Eastern 这个名称来自于按照其他规则创建名称的时间。

关于缩写,ET

由于我在几个 cmets 中感觉到了疑问:北美东部时间可能是并且通常缩写为 ET。看到这一点的一种方法是在Time Zone Abbreviations – Worldwide List。您还可以看到,ET 可能要么包含 EST(东部标准时间)和 EDT(东部夏令时间)用作 EST 的同义词,也称为 Tiempo del Este 西班牙语。当你研究这个列表时,你也会发现很多缩写都是模棱两可的。

或者在 Java 中(使用 REPL):

jshell> ZoneId.of("America/New_York").getDisplayName(TextStyle.SHORT, Locale.US) 
$3 ==> "ET"

只是出于好奇而不推荐,因为存在歧义的风险:您也可以另辟蹊径,从缩写中获取ZoneId

jshell> var dtf = DateTimeFormatter.ofPattern("z", Locale.US);
dtf ==> ZoneText(SHORT)

jshell> ZoneId.from(dtf.parse("ET"))
$7 ==> America/New_York

我再说一遍:不要在家里尝试这最后一招。

【讨论】:

  • 源文件中没有出现“已弃用”一词。如果您想要美国整个东部时区的时区规则,那么US/Eastern 最有意义。在国家层面定义的任何时区也是如此。那些US/* 的名字不会消失,特别是如果纽约、芝加哥、丹佛、洛杉矶或任何其他城市决定使用自己的不同于国家规则的规则。
  • @lilole 我相信你在射击信使?我引用和链接到的维基百科文章的作者并不是他/她自己编造的。尽管在源文件中没有明确说明,但 IANA 时区数据库背后的人员确实区分了已弃用和未弃用的时区 ID。所有规范的都是 region/city 格式。我理解您的反对意见,但我无权重新评估(?)美国/东部或任何其他已弃用的时区。更多链接:Deprecated time zones.
  • 感谢您的链接@Ole。它把我带到了data.iana.org/time-zones/theory.html#naming,这解释了为什么他们喜欢带有城市的 AREA/LOCATION 格式——本质上,国家名称的变化比城市名称更频繁,他们想要反映区域的“主要”时钟在哪里。这在世界上的小国是有道理的。但是“弃用”仍然是错误的词。如果你想坚持下去,那么你必须通过你的链接来生活:这些名称仅供“专家”阅读,而不是供最终用户看到。
  • 感谢@lilole,感谢您的cmets。我可以快乐地生活。我想要的只是正确而忠实地引用我的消息来源。我很想知道如果你发布一个问题,你对这个问题的回答会是什么样子。在小国家,是的,偶尔在大国家,比如(现在是前)苏联。
  • 干杯@Ole。你的cmets让我更努力地思考。对于这个特定的问题,在US/EasternAmerica/New_York 之间,两者都不正确。在代码中,我总是投票给最接近原始含义的内容。有时不同意维基百科真的没关系! ?
【解决方案3】:

如果你这样做:

System.out.println(TimeZone.getTimeZone(("US/Eastern")));
System.out.println(TimeZone.getTimeZone(("America/New_York")));

输出是:

sun.util.calendar.ZoneInfo[id="US/Eastern",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=US/Eastern,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]


sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]

这表明设置的每个值完全相同相同。两者没有区别。

但是,感谢 Andreas 的评论,最好使用 America/New_York 而不是 US/Eastern,因为它已被弃用,显示为 here 和官方列表 here

根据数据库作者在github上的官方列表,US/Eastern的存在只是为了向后兼容。

【讨论】:

  • ...目前... ;-)
  • 我认为建议纽约可能会在它甚至不在时区边缘border 时更改其时区是非常荒谬的。无论哪种方式,它们当前都是链接的,所以如果确实发生了,数据库无论如何都需要更改。
  • 数据库,是的;代码,不,前提是 OP 使用正确的时区标识符来满足他们真正想要的内容。 (正如我在其他地方所说:纽约似乎真的不太可能改变时区。)
  • 根据WikipediaUS/Eastern 被列为 DeprecatedAmerica/New_York 被列为 Canonical.
  • "这表明设置的每个值都完全相同。"当然,更简单的方法是使用TimeZone.hasSameRules
猜你喜欢
  • 2015-01-26
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
  • 2019-07-21
  • 2016-09-05
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多