我正在处理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格式。但是,您的输入在小时和分钟之间的偏移量中缺少冒号。虽然标准允许,但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 的所有时区的列表。
正确的时区名称具有continent/region
的格式,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。切勿使用 3-4 个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
我们使用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
末尾的Z
是Zulu
的缩写,表示 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.Date
、Calendar
和SimpleDateFormat
。
Joda-Time项目现在处于维护模式,建议迁移到 java.time 类。
要了解更多信息,请参阅Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。
您可以直接与数据库交换java.time对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要java.sql.*
类。
从哪里获得java.time类?
Java SE- 8、Java 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的试验场。你可以在这里找到一些有用的类,如Interval
、YearWeek
、YearQuarter
等。
您可以将日期转换为日历。Calendar.getTimeZone() 将返回与日历匹配的时区。然后TimeZone.getAvailableIDs()会给你可用的ID。