亚利桑那州时区夏令时

4

我想获取特定时区的当前时间。我尝试了以下代码:

Calendar j = new GregorianCalendar(TimeZone.getTimeZone("US/Mountain"));
j.setTimeInMillis(Calendar.getInstance().getTimeInMillis());
System.out.println(j.get(Calendar.HOUR_OF_DAY)+":"+j.get(Calendar.MINUTE));
TimeZone tz = TimeZone.getTimeZone("US/Mountain");
System.out.println("tz.getRawOffset()"+tz.getRawOffset()/3600);
System.out.println(tz.getDSTSavings());
System.out.println

(tz.inDaylightTime(new Date()));

我得到的答案令人惊讶 - 16:57 - 错了1小时 tz.getRawOffset()-7000 3600000 true - 为什么亚利桑那州也使用夏令时? 如何获取准确的凤凰城或美国其他城市的挂钟时间?
5个回答

10

亚利桑那州位于山区时区,但不遵循夏令时规定。如果你指定了时区为"US/Mountain",计算机将应用大多数山区时区州遵循的规则,包括遵循夏令时。若想获取亚利桑那州的规则(不包括夏令时),你需要使用时区为"US/Arizona"(或"America/Phoenix")。在纳瓦霍族国内,你需要使用名为"Navajo"的时区。

为了减少麻烦,始终尝试使用"America/*"中的名称,在这里你可以选择与你感兴趣的地方具有相同时区规则的城市名称。

要获得世界上任何一个城市的正确时间和正确时区,你只需熟悉Olson时区数据库中的名称及其含义。虽然通常认为“时区”一词指的是冬季中午(当所有人都遵守标准时间)的时间,但在Olson数据库中,时区名称代表特定地区整个夏令时规则和时区规则的历史。

例如,即使印第安纳州现在遵循东部时区并遵循夏令时(除芝加哥附近的一些县属于中央时区,如芝加哥),但在2006年之前他们不遵循夏令时。为此,创建了一个名为"US/Indiana"(或"America/Indianapolis")的时区来覆盖这个地区,即使今天,谈论印第安纳州时,你仍需要使用"America/Indianapolis"时区,以便正确回答关于2006年之前的日期和时间的查询。


印第安纳州的情况比上面概述的更加复杂。一些县使用东部时间和夏令时;一些使用中部时间和夏令时;大多数使用东部时间,但不遵守夏令时。Olson数据库中印第安纳州的时区名称列表包括以下所有内容:America/Fort_Wayne、America/Indiana/Indianapolis、America/Indiana/Knox、America/Indiana/Marengo、America/Indiana/Petersburg、America/Indiana/Tell_City、America/Indiana/Vevay、America/Indiana/Vincennes、America/Indiana/Winamac、America/Indianapolis、America/Knox_IN、US/East-Indiana、US/Indiana-Starke。 - Jonathan Leffler
@Jonathan:你说得对。在东部时区一直遵守夏令时的县市是存在的。然后,当印第安纳州决定全面采用夏令时时,许多位于两个时区边界上的不同县市在不同时间之间来回切换,因此实际上有更多的印第安纳州时区。但就理解奥尔森如何设计他的数据库而言,我对印第安纳州的简化解释已经足够了。 - Ken Bloom

3

亚利桑那州大部分地区不遵守夏令时,但亚利桑那州内的纳瓦霍族却遵守夏令时。


2
我会提供现代的答案。不要使用类CalendarGregorianCalendarTimeZoneDate。它们都设计得很糟糕,而且幸运的是,它们都已经过时了。

java.time

当你知道如何做时,它就很简单:
    ZonedDateTime arizonaExceptNavajo = ZonedDateTime.now(ZoneId.of("America/Phoenix"));
    System.out.println(arizonaExceptNavajo);

当我刚才运行这段代码时,输出结果是:

2019-10-23T04:07:23.034-07:00[美国/凤凰城]

美国/山区时区ID已被弃用。它是指向美国/丹佛的链接,而美国/丹佛使用夏令时(夏季节约时间,DST)。现代时区ID的格式为地区/城市,其中地区可以是像美洲大陆这样的大陆或像太平洋这样的海洋。
正如其他人所说,亚利桑那州只有一个地方使用夏令时,那就是纳瓦霍族。提到的Navajo时区ID也已被弃用。请使用美国/丹佛:
    ZonedDateTime navajoNation = ZonedDateTime.now(ZoneId.of("America/Denver"));
    System.out.println(navajoNation);

2019-10-23T05:07:23.037-06:00[美国/丹佛]

由于夏令时仍在生效,所以与上面的凤凰城相比,现在的时间要快一个小时。

链接


1

许多世界主要城市的区域信息可以直接获取。其中包括凤凰城,其区域标识符为“America/Phoenix”。

您可以使用方法TimeZone.getAvailableIDs()查找可用区域标识符列表,或手动检查JRE lib/zi目录的内容。

正如其他帖子所指出的那样,“US/Arizona”区域信息与“US/Mountain”不同。


0
    Date timeTest = Calendar.getInstance().getTime();
     
    SimpleDateFormat localFormater = new SimpleDateFormat("hh:mm aaa");
    String localTime = localFormater.format(timeTest);
    System.out.println("Local time :  " + localTime);
     
    SimpleDateFormat arFormatter = new SimpleDateFormat("hh:mm aaa");
    arFormatter.setTimeZone(TimeZone.getTimeZone("US/Arizona"));
    System.out.println("Arizona equivalent time :  " + arFormatter.format(timeTest));
     
    SimpleDateFormat mstFormmater = new SimpleDateFormat("hh:mm aaa");
    mstFormmater.setTimeZone(TimeZone.getTimeZone("US/Mountain"));
    System.out.println("MST equivalent time   :  " +  mstFormmater.format(timeTest));

输出:

本地时间:08:43 AM
亚利桑那州等效时间:01:43 AM
MST等效时间:02:43 AM

但是,如果我们更改日历而不更改日期格式,则时区格式(MST、US/Arizona、US/Mountain)的输出将相同。

    Calendar userCalendar1 = new GregorianCalendar(TimeZone.getTimeZone("MST"));<br>
    Calendar userCalendar2 = new GregorianCalendar(TimeZone.getTimeZone("US/Arizona"));<br>
    Calendar userCalendar3 = new GregorianCalendar(TimeZone.getTimeZone("US/Mountain"));
     
    Date timeTest1 = Calendar.getInstance().getTime();
    Date timeTest2 = userCalendar1.getTime();
    Date timeTest3 = userCalendar2.getTime();
    Date timeTest4 = userCalendar3.getTime();

    SimpleDateFormat localFormater = new SimpleDateFormat("hh:mm aaa");
    String   localTime = localFormater.format(timeTest1);
    System.out.println(" Local   time 1:  " + localTime);
 
    localFormater = new SimpleDateFormat("hh:mm aaa");
    localTime = localFormater.format(timeTest2);
 
    System.out.println("Local   time  2:  " + localTime);
 
    localFormater = new SimpleDateFormat("hh:mm aaa");
    localTime = localFormater.format(timeTest3);

    System.out.println("Local   time 3:  " + localTime);

    localFormater = new SimpleDateFormat("hh:mm aaa");
    localTime = localFormater.format(timeTest4);
 
    System.out.println("Local   time 4:  " + localTime);

输出:
本地时间1:08:56 AM
本地时间2:08:56 AM
本地时间3:08:56 AM
本地时间4:08:56 AM


首先,CalendarTimeZoneDate这些类的设计很糟糕,而SimpleDateFormat是一个臭名昭著的麻烦制造者。因此,它们在十年前就被现代Java日期和时间API——java.time所取代。不要使用那些旧类。其次,时区ID US/Arizona和US/Mountain已经被弃用,分别被America/Phoenix和America/Denver所替代。第三,你有没有提供其他答案中没有的贡献? - Ole V.V.
挑剔一点,我认为你输出的第一行中的9:52不是东部标准时间(EST),而是东部夏令时(EDT)。同样,最后一行是山区夏令时(MDT),而不是山区标准时间(MST)。更糟糕的是,将你的“Date”变量命名为“estTime”是误导性的,因为“Date”没有任何时区。 - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接