获取时区的时区 ID



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

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

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

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

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没有时区。它只有一个与 UTC 的偏移量。

偏移量只是在 UTC 之前或之后的位移小时、分钟和秒数。您的显示偏移量比 UTC 晚 5 小时。相反,时区是某个地区人们使用的偏移量的过去、现在和未来变化的历史。

OffsetDateTime

java.time中,我们将一个带有偏移量的时刻表示为OffsetDateTime类。

您的输入字符串采用标准 ISO 8601 格式。因此,我们应该能够在不指定格式化模式的情况下直接解析,因为java.time类在解析/生成字符串时默认使用ISO 8601格式。但是,您的输入在小时和分钟之间的偏移量中缺少冒号。虽然标准允许,但OffsetDateTimeJava 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 的所有时区的列表。

正确的时区名称具有continent/region的格式,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

我们使用ZoneId表示时区。TimeZone阶级现在是遗产,应该避免。

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

ZoneOffset offset = odt.getOffset() ;

offset.toString(): -05:00

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

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

即时字符串(): 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集合转储到控制台。

[美洲/巴拿马, 美洲/芝加哥, 美洲/

艾鲁内佩, 等等/格林威治标准时间+5, 太平洋/复活节, 墨西哥/一般, 美洲/Porto_Acre, 美洲/瓜亚基尔, 美洲/Rankin_Inlet, 美国/中部, 美洲/Rainy_River, 美洲/印第安纳州/诺克斯, 美洲/North_Dakota/比尤拉, 美洲/蒙特雷, 美洲/牙买加, 美洲/阿提科坎, 美洲/Coral_Harbour, 美洲/North_Dakota/中心, 美洲/开曼, 美洲/印第安纳州/Tell_City, 智利/复活节岛, 美洲/Mexico_City, 美洲/马塔莫罗斯

, CST6CDT, 美洲/Knox_IN, 美洲/波哥大, 美洲/梅诺米尼, 美洲/坚决, SystemV/EST5, 加拿大/中部, 巴西/英亩, 美洲/坎昆, 美洲/利马, 美洲/Bahia_Banderas, 美国/印第安纳-斯塔克, 美洲/Rio_Branco, SystemV/CST6CDT, 牙买加, 美洲/梅里达, 美洲/North_Dakota/New_Salem, 美洲/温尼伯]

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


关于java.time

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

Joda-Time项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。

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

从哪里获得java.time类?

Java SE
  • 8Java SE 9及更高版本
    • 内置。
    • 具有捆绑实现的标准 Java API 的一部分。
    • Java 9添加了一些小功能和修复。
  • Java SE 6 和 Java SE 7 大部分
    • java.time 功能在ThreeTen-Backport中向后移植到 Java 6 和 7。
  • Android
    • 更高版本的 java.time 类的 Android 捆绑实现。
    • 对于早期的Android,ThreeTenABP项目适应了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP...

ThreeTen-Extra项目通过额外的类扩展了java.time。这个项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等。

您可以将日期转换为日历。Calendar.getTimeZone() 将返回与日历匹配的时区。然后TimeZone.getAvailableIDs()会给你可用的ID。

相关内容

  • 没有找到相关文章

最新更新