使用 TimeZone.getDefault(),您的设备 return 是什么?

Using TimeZone.getDefault(), what does your device return?

getDisplayName(false, TimeZone.SHORT) 的值是多少?

我估计值是 GMToffset,例如在新加坡它将是 GMT+08:00

但是,在一台设备 (Google Pixel 2 XL) 上,我得到 SGT

为什么不同?是 Android Oreo 还是提供网络提供时区的 SIM 卡?我还认为这样的缩写或 3/4 字母 ID 已经被弃用了。

"三个字母的时区 ID 为了兼容JDK1.1.x,一些其他的三字母时区ID(如"PST"、"CTT"、"AST")也被支持。但是,它们的使用已被弃用,因为相同的缩写经常用于多个时区(例如,"CST" 可能是 U.S、"Central Standard Time" 和 "China Standard Time"),并且 Java 平台只能识别其中之一。"

https://developer.android.com/reference/java/util/TimeZone.html

过时的 TimeZone.getDefault() 及其现代等效项 ZoneId.systemDefault() 都是 return JVM 的时区设置。除非做了一些特殊的事情来获得其他东西,否则这将与启动 JVM 时设备的时区设置相同。它稍后可能会被您的程序或同一 JVM 中的其他程序 运行 更改。另一方面,如果您更改设备设置,这不会影响 JVM(直到启动新的 JVM)。

很可能您的设备具有不同的时区设置。我会认为设置 Asia/Singapore 更正确,即使对于实际的日常用途 UTC+08:00 是等效的。后者不是真正的时区,当涉及到历史日期时,它并不总是与新加坡时间一致。 Asia/Singapore 时间也称为新加坡时间、SGT、新加坡标准时间或 SST。最后一个缩写也与萨摩亚标准时间共享,这是一个完全不同的时区(因此请避免使用那些三个和四个字母的缩写)。

时区,如Asia/Singapore,是共享同一时间的区域(区域),如新加坡共和国,不仅包含当前与 UTC 的偏移量,还包含历史和已知的未来变化偏移量。另一方面,与 UTC 或 GMT 的偏移量(例如 +08:00)没有任何固有的有效时间。它在特定时间在特定区域的有效性仅来自时区。因此,使用偏移量作为设备的时区设置充其量是有问题的。旧的 class TimeZone 可用于表示时区或偏移量,这可能会模糊区分。在 java.time 中,区分了 ZoneId(带有名称的时区,通常并建议采用 region/city 格式)和ZoneOffset。由于 pragmatic/practical 原因,在需要 ZoneId 的地方也可以使用 ZoneOffset(通过继承实现)。

java.time

顺便说一句,考虑扔掉长期过时的 TimeZone 和朋友,改用 java.time、现代的 Java 日期和时间 API。与它一起工作要好得多。您需要的现代 class 是 ZoneId。它也有一个很好的 getDisplayName 方法。

  • 在 Java 8 及更高版本和较新的 Android 设备上 java.time 是内置的。
  • 在 Java 6 和 7 中获取 ThreeTen Backport,新 classes 的 backport(ThreeTen 用于 JSR 310;请参阅底部的链接)。
  • 在较旧的 Android 上使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 classes。

链接

终于,花了一些时间,但我弄清楚了为什么返回的时区格式不同。这是我的发现:

当语言与设备上的时区匹配时(例如英语(马来西亚)并且时区设置为吉隆坡 +08:00),则时区将以 3/4 字母 ID(例如 MYT)返回。我不知道为什么会这样,但不知何故我偶然发现了这一点。

另外,以偏移量格式不断获取时区的方法是使用此方法:

DateFormat date = new SimpleDateFormat("XXX", Locale.getDefault());
offset = date.format(new Date());