我有两个时间戳1498329000000
和1485282600000
Europe/Brussels
-
其中第一个存在于夏令时,第二个存在于非夏令时
如何从UTC
获得正或负(差)的偏移量?即 1 小时或 2 小时,基于DST
。
使用java.time
-API 非常简单:
public static ZoneOffset getZoneOffset(long epochMillis, String zoneName) {
Instant instant = Instant.ofEpochMilli(epochMillis);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(zoneName));
return zonedDateTime.getOffset();
}
public static void main(String[] args) {
System.out.println(getZoneOffset(1498329000000l, "Europe/Brussels")); // +02:00
System.out.println(getZoneOffset(1485282600000l, "Europe/Brussels")); // +01:00
}
另请查看类ZoneRules
,其中具有处理时区和夏令时 (DST) 的有用方法:
boolean isDaylightSavings(Instant instant)
检查指定的时刻是否为夏令时。
这将检查指定时刻的标准偏移和实际偏移是否相同。如果不是,则假定夏令时正在运行。
此默认实现比较实际偏移量和标准偏移量。
参数:
instant
- 查找偏移量的时刻,不是空,但如果规则对所有时刻都有单个偏移量,则可以忽略空返回:
标准偏移量,不为空Duration getDaylightSavings(Instant instant)
获取此区域中指定时刻使用的夏令时量。
这提供了对有关夏令时量如何随时间变化的历史信息的访问。这是标准偏移量和实际偏移量之间的差值。通常,冬季的量为零,夏季为一小时。时区是基于秒的,因此持续时间的纳秒部分将为零。
此默认实现根据实际偏移量和标准偏移量计算持续时间。
参数:
instant
- 查找夏令时的时刻,不是空,但如果规则对所有时刻只有一个偏移量,则可以忽略空返回:
标准偏移量与实际偏移量之差,不为空ZoneOffsetTransition nextTransition(Instant instant)
获取指定时刻之后的下一个转换。
这将返回指定时刻之后下一个转换的详细信息。例如,如果 instant 表示应用"夏季"夏令时的点,则该方法将返回到下一个"冬季"时间的转换。
参数:
instant
- 在之后获得下一个转换的时刻,不是 null,但如果规则对所有时刻都有单个偏移量,则可以忽略 null返回:
指定时刻之后的下一个转换,如果这是在最后一个转换之后,则为 null
要获取您可以使用的ZoneRules
:
ZoneRules rules = ZoneId.of("Europe/Brussels").getRules();
您可以使用以下代码片段获取特定时间戳的布鲁塞尔时区中与 UTC 的时区偏移量(以秒为单位):
ZoneId zone = ZoneId.of("Europe/Brussels");
Instant instant = Instant.ofEpochMilli(timestamp);
OffsetDateTime dateTime = OffsetDateTime.ofInstant(instant, zone);
int offsetInSeconds = dateTime.get(ChronoField.OFFSET_SECONDS);
如果你想在几个小时内得到它,你需要做更多的工作,有些国家的时区偏移量不是整小时。
public static void main(String[] args) {
System.out.println(utcOffsetInHoursInBrussels(1498329000000L));
System.out.println(utcOffsetInHoursInBrussels(1485282600000L));
}
public static int utcOffsetInHoursInBrussels(long timestamp) {
ZoneId zone = ZoneId.of("Europe/Brussels");
Instant instant = Instant.ofEpochMilli(timestamp);
OffsetDateTime dateTime = OffsetDateTime.ofInstant(instant, zone);
int offsetInSeconds = dateTime.get(ChronoField.OFFSET_SECONDS);
if (offsetInSeconds % 3600 == 0) {
return offsetInSeconds / 3600;
} else {
throw new IllegalArgumentException("Offset is not a whole hour");
}
}
输出:
2
1
您不一定需要像其他答案那样经历ZonedDateTime
或OffsetDateTime
。
ZoneOffset offset = ZoneId.of("Europe/Brussels")
.getRules()
.getOffset(Instant.ofEpochMilli(1_498_329_000_000L));
你喜欢哪个可能是一个品味问题。
Oles 答案是最好的,因为查询给定时刻的时区偏移量的简单问题根本不需要使用像ZonedDateTime
这样的复杂类型。
Java-8或更高版本(另见Oles回答):
ZoneRules rules = ZoneId.of("Europe/Brussels").getRules();
ZoneOffset offsetDST =
rules.getOffset(Instant.ofEpochMilli(1498329000000L));
System.out.println(offsetDST); // +02:00
ZoneOffset offsetSTD =
rules.getOffset(Instant.ofEpochMilli(1485282600000L));
System.out.println(offsetSTD); // +01:00
旧API(令人惊讶的是,即使是最简单的方法):
TimeZone tz = TimeZone.getTimeZone("Europe/Brussels");
System.out.println(tz.getOffset(1498329000000L)); // 7200000 ms
System.out.println(tz.getOffset(1485282600000L)); // 3600000 ms