joda 时区 ID 是否与 java 时区 ID 相同?
Are joda timezone ids the same as java time zone ids?
我在 Android 上使用 ACTION_TIMEZONE_CHANGED 意图过滤器来响应时区更改。
我注意到此时 Jodas 当前时区未更新,使用:
DateTimeZone.getDefault()
当我使用 Java 的默认值 TimeZone.getDefault()
时,时区是正确的。
注意:当我再次更改它时:Joda 具有我之前更改的值。所以它落后了(当 Android 触发广播意图时尚未更新)。
所以我只能使用当前时区的 Java 时区。但是我的域对象使用 Joda DateTimeZone`s。现在我想将当前时区与我的域对象中的时区进行比较。这样做省钱吗:
TimeZone currenTimeZone = TimeZone.getDefault();
if(action.getLocation().getDateTimeZone().getID().equals(currenTimeZone.getID()))) {
[...]
}
?
或者两个库之间的时区 ID 可以不同吗?
tl;博士
不,假设时区不安全:
- 存在。
- 定义了一个特定的标识符。
- 具有相同的definition/rules。
tzdata
大多数操作系统和软件库都依赖 tz database maintained by IANA 来提供当前和过去的时区信息。也称为 tzdata
或 TZDB
。以前称为 Olson 数据库。
经常更改
在世界范围内,政治家喜欢经常改变、重新定义、重新安排时间、重新命名,以及以其他方式搞乱时区定义和规则。他们通常在没有预先警告的情况下这样做,例如 Turkey(2016 年秋季)现在不到两个月。
有时会定义新的时区。因此,在这方面,具体回答您的问题:是的,某些 tzdata 副本可能具有旧副本中不存在的较新时区定义,因此时区标识符可能有所不同。
此外,有时会为现有时区赋予新名称。例如,随着印度最近恢复其城市名称,Asia/Calcutta
现在也被标记为 Asia/Kolkota
。同样,旧的 tzdata 副本不会知道这个新名称。
指定 proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
或 Pacific/Auckland
。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们 不是 真正的时区,不是标准化的,甚至不是唯一的(!)。
某些软件会扩展 tzdata 以尝试识别这些伪时区。这不是个好主意。但是,这再次意味着使用这些非标准时区标识符可能在一个地方有效,但在另一个地方无效。坚持使用官方时区名称。
有些区域有 display name,例如 British Time
。但是你应该永远不要使用它作为标识符。
正在更新
系统管理员必须努力在所有可能使用它的地方更新 tzdata:
- 操作系统
- Java 虚拟机
- 软件库(例如 Joda-Time,可能 ThreeTen-Backport)。
JVM 的提供者通常在 JVM 的更新中包含最新版本的 tzdata。但是政客们更频繁地摆弄时区而不是 Java 更新。因此您可能需要手动更新 JVM。 Oracle 为 Oracle 和 OpenJDK JVM 提供 Timezone Update Tool。
Joda-Time 包含它自己的 tzdata 副本。因此,您需要更新 Joda-Time 库或手动替换 tzdata。请注意,Joda-Time 项目现在处于维护模式,并建议移动到与 Java 8 及更高版本捆绑在一起的 java.time 类。
列出已知标识符
java.time 类 可以显示他们的列表 known zone identifiers.
Set<String> zoneIds = ZoneId.getAvailableZoneIds() ;
其他图书馆和操作系统或许也能做到这一点。
避免遗留日期时间类
与 Java 的最早版本捆绑在一起的麻烦的旧日期时间 类 现在是遗留的,由 java.time 类.
取代
所以你使用 TimeZone.getDefault()
is now outmoded by ZoneId.systemDefault
:
ZoneId z = ZoneId.systemDefault() ;
String zoneIdentifier = z.toString() ;
使用它来获取特定区域的当前时刻。
ZonedDateTime zdt = ZonedDateTime.now( z );
我在 Android 上使用 ACTION_TIMEZONE_CHANGED 意图过滤器来响应时区更改。
我注意到此时 Jodas 当前时区未更新,使用:
DateTimeZone.getDefault()
当我使用 Java 的默认值 TimeZone.getDefault()
时,时区是正确的。
注意:当我再次更改它时:Joda 具有我之前更改的值。所以它落后了(当 Android 触发广播意图时尚未更新)。
所以我只能使用当前时区的 Java 时区。但是我的域对象使用 Joda DateTimeZone`s。现在我想将当前时区与我的域对象中的时区进行比较。这样做省钱吗:
TimeZone currenTimeZone = TimeZone.getDefault();
if(action.getLocation().getDateTimeZone().getID().equals(currenTimeZone.getID()))) {
[...]
}
? 或者两个库之间的时区 ID 可以不同吗?
tl;博士
不,假设时区不安全:
- 存在。
- 定义了一个特定的标识符。
- 具有相同的definition/rules。
tzdata
大多数操作系统和软件库都依赖 tz database maintained by IANA 来提供当前和过去的时区信息。也称为 tzdata
或 TZDB
。以前称为 Olson 数据库。
经常更改
在世界范围内,政治家喜欢经常改变、重新定义、重新安排时间、重新命名,以及以其他方式搞乱时区定义和规则。他们通常在没有预先警告的情况下这样做,例如 Turkey(2016 年秋季)现在不到两个月。
有时会定义新的时区。因此,在这方面,具体回答您的问题:是的,某些 tzdata 副本可能具有旧副本中不存在的较新时区定义,因此时区标识符可能有所不同。
此外,有时会为现有时区赋予新名称。例如,随着印度最近恢复其城市名称,Asia/Calcutta
现在也被标记为 Asia/Kolkota
。同样,旧的 tzdata 副本不会知道这个新名称。
指定 proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
或 Pacific/Auckland
。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们 不是 真正的时区,不是标准化的,甚至不是唯一的(!)。
某些软件会扩展 tzdata 以尝试识别这些伪时区。这不是个好主意。但是,这再次意味着使用这些非标准时区标识符可能在一个地方有效,但在另一个地方无效。坚持使用官方时区名称。
有些区域有 display name,例如 British Time
。但是你应该永远不要使用它作为标识符。
正在更新
系统管理员必须努力在所有可能使用它的地方更新 tzdata:
- 操作系统
- Java 虚拟机
- 软件库(例如 Joda-Time,可能 ThreeTen-Backport)。
JVM 的提供者通常在 JVM 的更新中包含最新版本的 tzdata。但是政客们更频繁地摆弄时区而不是 Java 更新。因此您可能需要手动更新 JVM。 Oracle 为 Oracle 和 OpenJDK JVM 提供 Timezone Update Tool。
Joda-Time 包含它自己的 tzdata 副本。因此,您需要更新 Joda-Time 库或手动替换 tzdata。请注意,Joda-Time 项目现在处于维护模式,并建议移动到与 Java 8 及更高版本捆绑在一起的 java.time 类。
列出已知标识符
java.time 类 可以显示他们的列表 known zone identifiers.
Set<String> zoneIds = ZoneId.getAvailableZoneIds() ;
其他图书馆和操作系统或许也能做到这一点。
避免遗留日期时间类
与 Java 的最早版本捆绑在一起的麻烦的旧日期时间 类 现在是遗留的,由 java.time 类.
取代所以你使用 TimeZone.getDefault()
is now outmoded by ZoneId.systemDefault
:
ZoneId z = ZoneId.systemDefault() ;
String zoneIdentifier = z.toString() ;
使用它来获取特定区域的当前时刻。
ZonedDateTime zdt = ZonedDateTime.now( z );