获取时区

时间:2018-02-27 00:28:15

标签: java date datetime timezone timezone-offset

我正在处理Java中的时间和日期。

我的约会时间为:2018-08-22T22:00:00-0500 我的时区偏移是-0500 如何获取可用的时区ID列表?

我的主要目标是为特定时区设置日期。但是我不知道这个日期格式中嵌入的时区。

更新 我的问题与Java TimeZone offset不同 根据对该问题的接受答案,我需要有时区信息:"欧洲/奥斯陆" 。但是我只有偏移。请参阅下面接受的答案,它解决了我的问题。

1 个答案:

答案 0 :(得分:4)

TL;博士

eachZoneId.getRules().getOffset(
    OffsetDateTime.parse( 
        "2018-08-22T22:00:00-0500" , 
        DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" ) 
    ).toInstant()
).equals( myTargetZoneOffset )

偏移与区域

  

我不知道这个日期格式中嵌入的时区。

不,您的2018-08-22T22:00:00-0500输入字符串没有时区。它只有offset-from-UTC

偏移量只是UTC之前或之后的位移小时数,分钟数和秒数。你的显示距离UTC五小时的偏移量。相比之下,time zone是某个地区人民使用的偏移的过去,现在和将来变化的历史。

OffsetDateTime

java.time 中,我们将偏移量表示为OffsetDateTime类。

您的输入字符串采用标准ISO 8601格式。所以我们应该能够直接解析而不指定格式化模式,因为 java.time 类在解析/生成字符串时默认使用ISO 8601格式。但是,您的输入在小时和分钟之间的偏移中缺少冒号。虽然标准允许,OffsetDateTime类是Java 8和Java中的一个小错误。 9默认情况下无法解析此类值。要解决此问题,请指定DateTimeFormatter

String input = "2018-08-22T22:00:00-0000";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" );  // Specify formatting pattern to match input string.
OffsetDateTime odt = OffsetDateTime.parse( input , f );  // Parse from dumb string to smart `OffsetDateTime` object.
  

odt.toString():2018-08-22T22:00-05:00

时区名称

  

如何获取可用时区ID列表?

不确定“时区ID”的含义。我猜你要求在特定时刻使用特定的UTC偏移量来列出所有时区的列表。

proper time zone name的格式为continent/region,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

我们使用ZoneId表示时区。 TimeZone类现在是遗留的,应该避免使用。

要获取我们在该日期使用该偏移的ZoneId个对象列表,我们需要先从ZoneOffset中提取偏移量(OffsetDateTime)。

ZoneOffset offset = odt.getOffset() ;
  

offset.toString(): - 05:00

下一阶段是询问所有已知时区,询问每个时区在OffsetDateTime时刻的有效偏移量。该时刻的参数必须是UTC,一个Instant对象。因此,我们必须从Instant中提取OffsetDateTime。仍然是同一时刻,时间轴上的相同点,但通过不同的挂钟时间镜头看到。

Instant instant = odt.toInstant() ;  // Extract a UTC value (`Instant`) from our `OffsetDateTime` object.
  

instant.toString():2018-08-23T03:00:00Z

最后ZZulu的缩写,表示UTC。

制作一个空列表以收集所需的区域。

List< ZoneId > hits = new ArrayList<>() ;  // Make an empty list of `ZoneId` objects found to have our desired offset-from-UTC.

现在获取所有已知区域。存在一种方法,给出一组所有区域名称,但不包括区域对象。因此,对于每次迭代,我们必须实例化ZoneId。然后我们询问区域的规则,即该区域随时间变化的变化列表。根据规则,我们通过了我们的时刻(Instant),然后返回当时生效的ZoneOffset。如果此偏移量与我们的目标偏移量匹配,我们将该区域添加到列表中。

请注意,许多区域可能基本上是重复的或已弃用。区域列表的历史已经破裂,有许多变化,有些仅仅是别人的别名。

    Set < String > names = ZoneId.getAvailableZoneIds();  // Get a collection of all known time zones’ names.
    for ( String name : names )                           // Loop each name.
    {
        ZoneId z = ZoneId.of( name );                     // Instantiate a `ZoneId` for that zone name.
        ZoneRules rules = z.getRules();                   // Get the history of past, present, and future changes in offset used by the people of this particular region (time zone).
        ZoneOffset o = rules.getOffset( instant );        // Get the offset-from-UTC in effect at this moment for the people of this region.
        if( o.equals( offset )) {                         // Compare this particular offset to see if it is the same number of hours, minutes, and seconds as our target offset.
            hits.add( z );                                // If we have a hit, add to our collection of `ZoneId` objects.
        }
    }

将我们的hits集合转储到控制台。

  

[America / Panama,America / Chicago,America / Eirunepe,Etc / GMT + 5,Pacific / Easter,Mexico / General,America / Porto_Acre,America / Guayaquil,America / Rankin_Inlet,US / Central,America / Rainy_River, America / Indiana / Knox,America / North_Dakota / Beulah,America / Monterrey,America / Jamaica,America / Atikokan,America / Coral_Harbour,America / North_Dakota / Center,America / Cayman,America / Indiana / Tell_City,Chile / EasterIsland,America / Mexico_City,America / Matamoros,CST6CDT,America / Knox_IN,America / Bogota,America / Menominee,America / Resolute,SystemV / EST5,Canada / Central,Brazil / Acre,America / Cancun,America / Lima,America / Bahia_Banderas,US / Indiana-Starke,America / Rio_Branco,SystemV / CST6CDT,Jamaica,America / Merida,America / North_Dakota / New_Salem,America / Winnipeg]

请注意,此区域列表仅对我们选择的特定时刻有效。在较早时间或更晚时间,这些区域中的一些可能正在使用来自UTC的一些其他偏移。相反,在其他时刻,不在此列表中的某些区域可能正在使用我们所需的偏移量。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore