joda时区ID是否与java时区ID相同?

Roe*_*oel 0 java datetime android jodatime

我在Android上使用ACTION_TIMEZONE_CHANGED意图过滤器来响应时区更改.

我注意到Jodas当前时区目前没有更新使用: DateTimeZone.getDefault()

当我使用Java的默认值时TimeZone.getDefault(),时区是正确的.

注意:当我再次更改它时:Joda具有我之前更改过的值.所以它落后了(当Android激发广播意图时尚未更新).

所以我只能将Java时区用于当前时区.但我的域对象使用Joda DateTimeZone.现在我想将当前时区与我的域对象中的时区进行比较.保存这样做:

TimeZone currenTimeZone = TimeZone.getDefault();
if(action.getLocation().getDateTimeZone().getID().equals(currenTimeZone.getID()))) {
 [...]
}
Run Code Online (Sandbox Code Playgroud)

?或者两个库之间的时区ID可以不同吗?

Bas*_*que 5

TL;博士

不,假设时区不安全:

  • 存在.
  • 有一个特定的标识符定义.
  • 具有相同的定义/规则.

的tzdata

大多数操作系统和软件库依靠IANA维护的tz数据库来提供当前和过去的时区信息.也称为或.以前称为Olson数据库.tzdataTZDB

经常变化

在世界各地,政治家们喜欢经常改变,重新定义,重新安排,重命名,以及以其他方式搞乱时区定义和规则.他们经常在没有预警的情况下这样做,例如在土耳其(2016年秋季)不到两个月.

有时会定义新的时区.因此,在这方面,要具体回答您的问题:是的,tzdata的某些副本可能具有旧版本中不存在的较新时区定义,因此时区标识符可能不同.

此外,有时会为现有时区指定新名称.例如,印度最近恢复了他们的城市名称,Asia/Calcutta现在也被标记为Asia/Kolkota.同样,旧的tzdata副本不会知道这个新名称.

指定适当的时区名称,格式continent/region,如America/Montreal,Africa/CasablancaPacific/Auckland.切勿使用3-4字母缩写,例如ESTIST因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!).

某些软件会扩展tzdata以尝试识别这些伪时区.不是个好主意.但是,同样,这意味着使用这些非标准时区标识符可能在一个地方工作,但不能在另一个地方工作.坚持使用官方时区名称.

某些区域具有显示名称,例如British Time.但是你永远不应该使用它作为标识符.

更新

系统管理员必须努力在可能使用的所有不同位置更新tzdata:

  • 操作系统
  • Java虚拟机
  • 软件库(例如Joda-Time,可能还有ThreeTen-Backport).

JVM的提供者通常在JVM的更新中包含最新版本的tzdata.但政客们比Java更新更频繁地使用时区.因此,您可能需要手动更新JVM.Oracle 为Oracle和OpenJDK JVM 提供了时区更新工具.

Joda-Time包含自己的tzdata副本.因此,您需要更新Joda-Time库或手动更换tzdata.请注意,Joda-Time项目现在处于维护模式,并建议转移到Java 8及更高版本捆绑的java.time类.

列出已知标识符

java.time类可以显示已知区域标识符的列表.

Set<String> zoneIds = ZoneId.getAvailableZoneIds() ;
Run Code Online (Sandbox Code Playgroud)

其他库和操作系统也许能够做到这一点.

避免遗留日期时间类

与最早版本的Java捆绑在一起的麻烦的旧日期时间类现在已经遗留下来,取而代之的是java.time类.

所以你的使用TimeZone.getDefault()现在已经过时了ZoneId.systemDefault:

ZoneId z = ZoneId.systemDefault() ;
String zoneIdentifier = z.toString() ;
Run Code Online (Sandbox Code Playgroud)

使用它来获取特定区域中的当前时刻.

ZonedDateTime zdt = ZonedDateTime.now( z );
Run Code Online (Sandbox Code Playgroud)