我知道如何得到相反的结果。给定一个时区,我可以通过以下代码片段获得时区偏移:
TimeZone tz = TimeZone.getDefault();
System.out.println(tz.getOffset(System.currentTimeMillis()));
我想知道如何从时区偏移量中获取时区名称。
给定
timezone offset = 21600000
(以毫秒为单位;+6.00偏移量)
我想得到以下任何可能的时区名称的结果:
(GMT+6:00) Antarctica/Vostok
(GMT+6:00) Asia/Almaty
(GMT+6:00) Asia/Bishkek
(GMT+6:00) Asia/Dacca
(GMT+6:00) Asia/Dhaka
(GMT+6:00) Asia/Qyzylorda
(GMT+6:00) Asia/Thimbu
(GMT+6:00) Asia/Thimphu
(GMT+6:00) Asia/Yekaterinburg
(GMT+6:00) BST
(GMT+6:00) Etc/GMT-6
(GMT+6:00) Indian/Chagos
tl;dr
Instant instant = Instant.now();
List < String > names =
ZoneId
.getAvailableZoneIds()
.stream()
.filter(
( String name ) ->
ZoneId
.of( name )
.getRules()
.getOffset( instant )
.equals(
ZoneOffset.ofHours( 6 )
)
)
.collect( Collectors.toList() )
;
在Java 14.0.1:中
names=[Asia/Kashgar,Etc/GMT-6,Asia/阿拉木图,Asia/达卡,Asia/鄂木斯克,Asia/Dhaka,Indian/Chagos,Asia/Qostanay,Asia/Bishkek,Antarctic/Vostok,Asia/乌鲁木齐,Asia/Thimbu,Asia/廷布]
java.time
现代解决方案使用java.time类,这些类在几年前取代了糟糕的遗留日期-时间类。具体而言,TimeZone
被替换为:
ZoneId
ZoneOffset
ZoneRules
与UTC的偏移量仅为本初子午线之前或之后的小时-分-秒。时区远不止这些。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史。时区的名称采用Continent/Region
格式。请参阅分区列表。
获取JVM的当前时区。
ZoneId z = ZoneId.systemDefault() ;
获取当前定义的所有ZoneId
对象的列表。请注意,政客们经常更改时区。因此,这个列表及其包含的规则将发生变化。保持tzdata的最新状态。
Set< String > zones = ZoneId.getAvailableZoneIds() ;
你问:
我想知道如何从时区偏移量中获取时区名称。
许多时区在任何给定时刻都可能巧合地共享相同的偏移量。在下面的代码中,我们循环所有已知的时区,询问每个时区的偏移量。
由于时区规则会随着时间的推移而变化(由政治家决定),您必须提供一个时刻,以便每个区域使用偏移量。这里我们在运行时使用当前时刻。
// Convert your milliseconds to an offset-from-UTC.
int milliseconds = 21_600_000;
int seconds = Math.toIntExact( TimeUnit.MILLISECONDS.toSeconds( milliseconds ) );
ZoneOffset targetOffset = ZoneOffset.ofTotalSeconds( seconds );
// Capture the current moment as seen in UTC (an offset of zero hours-minutes-seconds).
Instant now = Instant.now();
// Loop through all know time zones, comparing each one’s zone to the target zone.
List < ZoneId > hits = new ArrayList <>();
Set < String > zoneNames = ZoneId.getAvailableZoneIds();
for ( String zoneName : zoneNames )
{
ZoneId zoneId = ZoneId.of( zoneName );
ZoneRules rules = zoneId.getRules();
// ZoneRules rules = zoneId.getRules() ;
ZoneOffset offset = rules.getOffset( now );
if ( offset.equals( targetOffset ) )
{
hits.add( zoneId );
}
}
转储到控制台。请在IdeOne.com上实时查看此代码。
// Report results.
System.out.println( "java.version " + System.getProperty("java.version") ) ;
System.out.println( "java.vendor " + System.getProperty("java.vendor") ) ;
System.out.println() ;
System.out.println( "targetOffset = " + targetOffset );
System.out.println( "hits: " + hits );
请在IdeOne.com上实时查看此代码。
java.version 12.0.1
java.vendor Oracle Corporation
targetOffset=+06:00
点击次数:[Asia/Kashgar,Etc/GMT-6,Asia/阿拉木图,Asia/达卡,Asia/鄂木斯克,Asia/Dhaka,Indian/Chagos,Asia/Qyzylorda,Asia/Bishkek,Antarctic/Vostok,Asia/乌鲁木齐,Asia/Thimbu,Asia/廷布]
关于java.time
java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.Date
、Calendar
和&CCD_ 10。
要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。
现在处于维护模式的JodaTime项目建议迁移到java.Time类。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*
类。休眠5&JPA 2.2支持java.time.
从哪里获得java.time类?
- Java SE 8、Java SE 9和Java SE 10,爪哇SE 11及更高版本-标准Java API的一部分,具有捆绑实现。
- Java 9添加了一些小功能和修复程序
- Java SE 6和Java SE 7
- java.time的大部分功能都是后移植到Java6&7英寸ThreeTen背包
- 安卓
- java.time类的Android捆绑包实现的后续版本
- 对于早期的Android(<26),ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…
使用TimeZone#getAvailableIDs(int)
import java.util.*;
class Hello
{
public static void main (String[] args) throws java.lang.Exception
{
TimeZone tz = TimeZone.getDefault();
int offset = 21600000;
String[] availableIDs = tz.getAvailableIDs(offset);
for(int i = 0; i < availableIDs.length; i++) {
System.out.println(availableIDs[i]);
}
}
}