>我需要以 [+/-]hh:mm 格式保存手机的时区
我正在使用时区类来处理这个问题,但我能得到的唯一格式如下:
PST -05:00
GMT +02:00
我宁愿不对结果进行子串串,是否有任何键或选项标志可以设置为仅获取该时区的值而不是该时区的名称(GMT/CET/PST...(?
我需要以 [+/-]hh:mm 格式保存手机的时区
不,你没有。偏移量本身是不够的,您需要存储整个时区名称/ID。例如,我住在奥斯陆,我的当前偏移量是 +02:00,但在冬季(由于 dst(,它是 +01:00。标准时间和夏令时之间的确切切换取决于您不想探索的因素。
因此,而不是存储+ 02:00
(或者应该+ 01:00
?我将"Europe/Oslo"
存储在数据库中。现在,我可以使用以下命令恢复完整配置:
TimeZone tz = TimeZone.getTimeZone("Europe/Oslo")
想知道我今天的时区偏移量是多少吗?
tz.getOffset(new Date().getTime()) / 1000 / 60 //yields +120 minutes
然而,在 12 月也是如此:
Calendar christmas = new GregorianCalendar(2012, DECEMBER, 25);
tz.getOffset(christmas.getTimeInMillis()) / 1000 / 60 //yields +60 minutes
足以说:存储时区名称或id,每次要显示日期时,请检查当前偏移量(今天(是多少,而不是存储固定值。可以使用TimeZone.getAvailableIDs()
枚举所有支持的时区 ID。
遇到过类似的情况,我必须调用第三方网络服务并以 +/-hh:mm 格式传入 Android 设备的当前时区偏移量。 这是我的解决方案:
public static String getCurrentTimezoneOffset() {
TimeZone tz = TimeZone.getDefault();
Calendar cal = GregorianCalendar.getInstance(tz);
int offsetInMillis = tz.getOffset(cal.getTimeInMillis());
String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));
offset = (offsetInMillis >= 0 ? "+" : "-") + offset;
return offset;
}
现在使用 Java 8,您可以使用:
Integer offset = ZonedDateTime.now().getOffset().getTotalSeconds();
以获取与 UTC 的当前系统时间偏移量。然后,您可以将其转换为所需的任何格式。发现它对我的情况有用。
示例:https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html
在 Java 8 中,您可以使用以下代码实现此目的。
-
获取区域偏移量
TimeZone tz = TimeZone.getDefault(); String offsetId = tz.toZoneId().getRules().getStandardOffset(Instant.now()).getId();
offsetId
将是类似+01:00
.请注意
ZoneRules::getStandardOffset
在应用夏令时之前为您提供区域 ID 的偏移量,因为区域 ID 的偏移量可能随时间而变化,如 Javadoc 所述。获取此区域中指定时刻的标准偏移量。这提供了对有关标准偏移如何随时间变化的历史信息的访问。标准偏移量是应用任何夏令时之前的偏移量。这通常是冬季适用的偏移量。
-
使用 DST 获取电流偏移
返回TimeZone.getDefault().toZoneId().getRules().getOffset(Instant.now()).getId()
的标识符将返回此区域的实际偏移量。
获取在这些规则中指定时刻适用的偏移量。从瞬间到偏移量的映射很简单,每个时刻只有一个有效的偏移量。此方法返回该偏移量。
函数ZoneRules::getStandardOffset
/ZoneRules::getOffset
的工作方式,即它们需要一个Instant
作为参数,是因为需要特定的时间点来计算该区域的偏移量。因为此区域的规则可能会随时间而更改。
例如,一个区域可能已经更改了其时区,例如 2011 年的萨摩亚。或者改变夏令时政策的国家,比如韩国或日本过去所做的,也许是未来的欧洲国家。
这就是为什么@Tomasz Nurkiewicz的答案建议不要直接以带符号的小时格式存储偏移量,而是让代码在每次需要时计算偏移量。
其他接口
ZoneId.systemDefault().getRules().getStandardOffset(Instant.now())
ZoneId.systemDefault().getRules().getOffset(Instant.now())
// ZonedDateTime don't expose the standard offset (i.e without DST)
ZonedDateTime.now().getOffset()
引用
- 时区
- 数据库中维护的时区规则(几乎每个软件系统都使用(。它也被称为奥尔森数据库。
- W3 使用时区
ZoneId here = ZoneId.of("Europe/Kiev");
ZonedDateTime hereAndNow = Instant.now().atZone(here);
String.format("%tz", hereAndNow);
将为您提供标准化的字符串表示形式,例如"+0300">
java.time
: 现代日期时间 API
您可以使用 ZonedDateTime#getOffset
获取时区的偏移量。
请注意,观察 DST 的时区的偏移量会随着 DST 的变化而变化。对于其他地方(例如印度(,它保持固定。因此,建议提及显示时区偏移量的时刻。时刻被提及为 Instant.now()
,它表示 UTC 中的日期时间(由 Z
表示,代表祖鲁语并指定 +00:00
小时的时区偏移量(。
显示按ZoneId.getAvailableZoneIds()
返回的所有时区的偏移量:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// Test
Instant instant = Instant.now();
System.out.println("Timezone offset at " + instant);
System.out.println("==============================================");
ZoneId.getAvailableZoneIds()
.stream()
.sorted()
.forEach(strZoneId -> System.out.printf("%-35s: %-6s%n",
strZoneId, getTzOffsetString(ZoneId.of(strZoneId), instant)));
}
static String getTzOffsetString(ZoneId zoneId, Instant instant) {
return ZonedDateTime.ofInstant(instant, zoneId).getOffset().toString();
}
}
输出:
Timezone offset at 2021-05-05T21:45:34.150901Z
==============================================
Africa/Abidjan : Z
Africa/Accra : Z
Africa/Addis_Ababa : +03:00
...
...
...
W-SU : +03:00
WET : +01:00
Zulu : Z
要了解有关现代日期时间 API* 的更多信息,请参阅跟踪:日期时间。
<小时 />出于任何原因,如果你必须坚持使用Java 6或Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到Java 6和7。如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请查看通过脱糖提供的 Java 8+ API 和如何在 Android Project 中使用 ThreeTenABP。
我们可以很容易地获得只有TimeZone
实例和System.currentTimeMillis()
的TimeZone
的毫秒偏移量。然后,我们可以使用 TimeUnit
类从毫秒转换为任何选择的时间单位。
这样:
public static int getOffsetHours(TimeZone timeZone) {
return (int) TimeUnit.MILLISECONDS.toHours(timeZone.getOffset(System.currentTimeMillis()));
}
或者,如果您更喜欢新的Java 8时间API
public static ZoneOffset getOffset(TimeZone timeZone) { //for using ZoneOffsett class
ZoneId zi = timeZone.toZoneId();
ZoneRules zr = zi.getRules();
return zr.getOffset(LocalDateTime.now());
}
public static int getOffsetHours(TimeZone timeZone) { //just hour offset
ZoneOffset zo = getOffset(timeZone);
TimeUnit.SECONDS.toHours(zo.getTotalSeconds());
}
我知道这很旧,但我想我会给出我的意见。我必须为工作中的一个项目这样做,这是我的解决方案。
我有一个使用时区类包含时区的 Building 对象,并希望在新类中创建 zoneId 和偏移量字段。
所以我所做的是创建:
private String timeZoneId;
private String timeZoneOffset;
然后在构造函数中,我传入了 Building 对象并设置了这些字段,如下所示:
this.timeZoneId = building.getTimeZone().getID();
this.timeZoneOffset = building.getTimeZone().toZoneId().getId();
所以timeZoneId可能等于"EST"之类的东西时区偏移量可能等于"-05:00">
我不想你可能不会