Java 按时区偏移量获取时区
我需要一个时区,并且我有时区偏移。 例如,我有offset=Java 按时区偏移量获取时区,java,date,datetime,timezone,timezone-offset,Java,Date,Datetime,Timezone,Timezone Offset,我需要一个时区,并且我有时区偏移。 例如,我有offset=14400000。我想要一个时区(任何地方,任何城市)。我可以在SimpleDateFormat中使用此时区,因此它会打印此时区的正确时间 (我进行了一些重构): 我得到: sun.util.calendar.ZoneInfo[id="Asia/Baku",offset=14400000,dstSavings=0,useDaylight=false,transitions=68,lastRule=null] 我不喜欢这种方法,因为时区
14400000
。我想要一个时区(任何地方,任何城市)。我可以在SimpleDateFormat
中使用此时区,因此它会打印此时区的正确时间
(我进行了一些重构):
我得到:
sun.util.calendar.ZoneInfo[id="Asia/Baku",offset=14400000,dstSavings=0,useDaylight=false,transitions=68,lastRule=null]
我不喜欢这种方法,因为时区
将调用区域信息文件
getZoneIds(int var1)
,在这里。这是反编译代码
public static String[] getZoneIds(int var0) {
ArrayList var1 = new ArrayList();
String[] var2 = getZoneIds();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String var5 = var2[var4];
ZoneInfo var6 = getZoneInfo(var5);
if (var6.getRawOffset() == var0) {
var1.add(var5);
}
}
var2 = (String[])var1.toArray(new String[var1.size()]);
Arrays.sort(var2);
return var2;
}
publicstaticstring[]getZoneIds(int-var0){
ArrayList var1=新的ArrayList();
字符串[]var2=getZoneIds();
int var3=var2.length;
for(int var4=0;var4
您可以看到,它在现有对象上循环以构建区域ID数组,而我只需要一个
我的问题是,有没有更有效的方法?我只需要任何时区id或给定偏移量的单个时区。您可以使用以下命令为任何偏移量构造时区实例: 该类与您通常使用它的类一起早已过时<代码>日历,
格雷戈里安日历
,日期格式
和简化格式
我建议您开始使用java.time
,这是一种现代的java日期和时间API。和他一起工作总的来说要好得多。然后,您需要一个时区的ZoneId
对象。对于偏移量恒定的ZoneId
,我们创建ZoneOffset
的一个实例,它是ZoneId
的两个子类之一
int offsetMilliseconds = 14_400_000;
int offsetSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(offsetMilliseconds);
// to check that we haven’t lost any precision, convert back to milliseconds and compare
if (TimeUnit.SECONDS.toMillis(offsetSeconds) != offsetMilliseconds) {
throw new IllegalArgumentException("Millisecond precision not supported: " + offsetMilliseconds);
}
ZoneId tzid = ZoneOffset.ofTotalSeconds(offsetMilliseconds / 1000);
System.out.println(tzid);
// test the time zone we got
System.out.println(ZonedDateTime.now(tzid));
在我的电脑上,这是刚刚打印的:
+04:00
2018-01-16T19:44:22.863760+04:00
A的精度只有秒,而不是毫秒,这对于1440000毫秒的情况来说是很好的。如果您的毫秒数不等于整秒数,您可能希望舍入到整秒,而不是抛出异常,这是您的决定
只有当您需要将一个老式的时区
对象传递给一些您现在无法更改或不想更改的旧API时,才可以转换上面的时区ID
:
TimeZone oldfashionedTimeZone = TimeZone.getTimeZone(tzid);
这将为您提供一个显示名称为GMT+04:00的时区
,并且(当然)偏移4小时。但是,请注意,如果时区
无法识别您试图转换到的时区(如果偏移量为奇数秒,则很可能是这种情况),它会默认为GMT(这只是旧类的一个问题)。因此,您可能应该检查得到的时区
对象,例如:
if (oldfashionedTimeZone.getRawOffset() != offsetMilliseconds) {
throw new IllegalStateException("Conversion to legacy TimeZone object failed");
}
tl;博士
不要做你正在尝试的事情
没有意义,因为在某一时刻共享偏移的分区在过去或将来的其他时刻可能不会共享该偏移
分区是偏移的历史记录
答案是正确的。这里有更多的讨论
我需要一个时区,我有时区偏移
不太可能
时间只不过是在时间之前或之后的小时数、分钟数和秒数
时区更重要。分区是特定区域的人民使用的过去偏移量变化的历史。分区还具有针对该区域偏移的当前和未来更改的规则。因此,一个时区总是比一个简单的偏移更可取,但只有当确定知道时才是如此。在你的情况下,你不知道区域,不应该猜测;只要坚持使用偏移量
给定的偏移量不能将您引导到特定时区,而不会产生歧义和错误
- 模糊性,因为许多区域可能由于巧合而共享相同的偏移量。例如,
&Europe/Gibralter
&Europe/Oslo
今天都共享相同的偏移量,比UTC提前一小时。因此,如果UTC的偏移量仅为Africa/Lagos
,您如何知道哪个是合适的+01:00
- 错误,因为如果没有日期,您无法知道时区的偏移量。例如,上述三个区域在2017-2018年冬季共享相同的偏移量,但在夏季,直布罗陀和奥斯陆遵守夏令时(DST),这意味着它们将比UTC提前一小时,而拉各斯则比UTC提前一小时。从历史上看,由于世界各地的政治家都有重新定义区域的奇怪倾向,抵消可能会因为DST以外的其他原因而发生变化。例如,委内瑞拉在十年中两次将其补偿时间改为半小时。最近几年的另一个例子是,俄罗斯和土耳其一直在改变关于使用DST的想法,恢复到以前的静态偏移量,或者改变为永久保持在以前的静态偏移量之前李>
ZoneOffset offset = ZoneId.of( "Africa/Tunis" ) // Instantiate a `ZoneId`.
.getRules() // Obtain a `ZoneRules` object from that `ZoneId` object.
.getOffset( Instant.now() ) ; // Interrogate that `ZoneRules` for an offset-from-UTC in use at a specific moment in history.
我只需要任何时区id或给定偏移量的单个时区
这是不可取的。如上所述,在一个日期共享特定偏移的时区可能在另一个日期不共享该偏移。每个分区因其偏移量变化的历史而不同。因此,任意选择一个区域是不明智的
java.time
正如在另一个答案中所解释的那样,时区
和区域信息
类现在是遗留类。它们是被java.time类取代的麻烦的旧日期时间类的一部分
而是使用(与UTC的偏移量)和ZoneId
(时区)
以大陆/地区
的格式指定,例如,或太平洋/奥克兰
。永远不要使用3-4个字母的缩写
if (oldfashionedTimeZone.getRawOffset() != offsetMilliseconds) {
throw new IllegalStateException("Conversion to legacy TimeZone object failed");
}
ZoneOffset offset = ZoneId.of( "Africa/Tunis" ) // Instantiate a `ZoneId`.
.getRules() // Obtain a `ZoneRules` object from that `ZoneId` object.
.getOffset( Instant.now() ) ; // Interrogate that `ZoneRules` for an offset-from-UTC in use at a specific moment in history.
ZoneId z = ZoneId.of( "America/Montreal" );