java - 获取时区的TimeZoneID

标签 java date datetime timezone timezone-offset

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

我的约会日期是:2018-08-22T22:00:00-0500
我的时区偏移量是-0500
如何获得可用时区ID的列表?

我的主要目的是将日期设置为特定的时区。但是我不知道时区,因为它以这种日期格式嵌入。

更新:
我的问题与Java TimeZone offset不同
根据对该问题的公认答案,我需要时区信息:“ Europe / Oslo”。但是我只有抵消。请参阅下面可接受的答案,它可以解决我的问题。

最佳答案

tl; dr

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和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。切勿使用3-4个字母的缩写,例如ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

我们使用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集合转储到控制台。


  [美国/巴拿马,美国/芝加哥,美国/埃鲁尼佩,Etc / GMT + 5,太平洋/复活节,墨西哥/一般,美国/ Porto_Acre,美国/瓜亚基尔,美国/ Rankin_Inlet,美国/中部,美国/ Rainy_River,美国/印第安纳州/诺克斯,美国/北达科他州/比拉,美国/蒙特雷,美国/牙买加,美国/阿蒂坎坎,美国/科勒尔港,美国/北达科他州/中部,美国/开曼,美国/印第安纳州/泰勒城,智利/复活节岛,美国/墨西哥_城市,美国/ Matamoros,CST6CDT,美国/诺克斯_IN,美国/波哥大,美国/ Menominee,美国/ Resolute,SystemV / EST5,加拿大/中部,巴西/英亩,美国/坎昆,美国/利马,美国/巴伊亚州_班德拉斯,美国/印第安纳州·斯塔克,美国/里约布兰科,SystemV / CST6CDT,牙买加,美国/梅里达,美国/北达科他州/新萨兰姆,美国/温尼伯]


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



关于java.time

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

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?


Java SE 8Java SE 9和更高版本


内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


ThreeTen-Backport中的大部分java.time功能都已反向移植到Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于早期的Android,ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - 获取时区的TimeZoneID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48999280/

相关文章:

javascript - toLocaleString() 在不同浏览器中的不一致行为

java - drawLine() 方法不绘制任何东西

android - 是否可以在 android studio 项目中找出最后修改日期?

java - 在转换为 Java 对象之前检查 xsd datetime 是否有定义的时区

java - 尝试将字符串日期转换为日期

Java判断时间是否大于X分钟

javascript - 如何检查两个日期之间的天数是否是工作日?

java - 使用 JSON 模式和 ElasticSearch Java API 添加类型映射

java - Android - 空对象引用错误

java - 我是否需要在 Spring 事务中显式保存修改后的域对象?