这些 3 字母缩写的问题在于它们是 ambiguous and not standard。
所以,MST 是一个时区名称,可以应用于许多不同的地区,它们可能有不同的 DST 规则(有些可能有 DST,有些可能没有,更不用说历史信息了 - 有些可能 过去有 DST,现在没有了,或者相反)。
旧 API (java.util.TimeZone) 处理这些歧义,假设这些歧义 3 字母名称的默认值,所以 MST 被映射到 America/Denver 并且这被保存在 joda-time - IMO - for 兼容性 原因(您可以在源代码中看到 - 我使用的是 jodatime 2.7)。至少这是我从评论中可以理解的:
map.put("MST", "America/Denver"); // JDK 1.1 compatible
而且这个映射只用在DateTimeZone.forTimeZone(TimeZone)中,这是一种将旧的TimeZone类转换为jodatime的DateTimeZone的方法(对我来说,这证实了兼容性的原因)。
如果您想确保您的代码使用正确的时区,您可以按照@Ole V.V.'s comment 中的说明进行操作,并使用America/Phoenix 而不是MST。这将消除歧义,并使您的代码更清楚地了解它使用的时区。
这些时区名称 (Continent/City) 来自 IANA database,这是 Java 的 API 和 Joda time 使用的名称。
示例代码:
// create a date/time in UTC
DateTime utc = new DateTime("2017-03-26T10:00:00Z", DateTimeZone.UTC);
System.out.println(utc); // 2017-03-26T10:00:00.000Z
// convert to Arizona timezone
DateTimeZone arizona = DateTimeZone.forID("America/Phoenix");
DateTime arizonaDate = utc.withZone(arizona);
System.out.println(arizonaDate); // 2017-03-26T03:00:00.000-07:00
新的 Java 时间 API
如果可能,我建议您使用新的日期/时间 API(如果无法从 Joda-time 迁移到此新 API,请忽略此答案的其余部分;但如果您想迁移它,请继续)。
joda 的问题是因为在joda's website 中它说:请注意,Joda-Time 被认为是一个基本上“完成”的项目。没有计划进行重大改进。如果使用 Java SE 8,请迁移到 java.time (JSR-310)。
如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs。
如果您使用的是 Java ,则可以使用 ThreeTen Backport,这是 Java 8 新日期/时间类的一个很好的向后移植。对于Android,还有ThreeTenABP(更多关于如何使用它here)。
下面的代码适用于两者。
唯一的区别是包名(在 Java 8 中是 java.time,而在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。
在新 API 中,可以使用自定义 Map 将 MST 映射到您想要的时区:
// custom map with timezone names
Map<String, String> map = new HashMap<>();
// map "MST" to Arizona's timezone
map.put("MST", "America/Phoenix");
// create timezone
ZoneId arizona = ZoneId.of("MST", map);
// datetime in UTC
ZonedDateTime utc = ZonedDateTime.parse("2017-03-26T10:00:00Z");
System.out.println(utc); // 2017-03-26T10:00Z
// convert to Arizona timezone
ZonedDateTime arizonaDate = utc.withZoneSameInstant(arizona);
System.out.println(arizonaDate); // 2017-03-26T03:00-07:00[America/Phoenix]
当然,理想的选择是使用ZoneId.of("America/Phoenix"),但如果不可行,您必须使用MST,自定义地图是一个不错的选择。
另请注意,新 API 会打印 [] 之间的时区名称。如果要更改它,可以使用DateTimeFormatter 类。您可以使用内置格式化程序(查看javadoc 了解更多信息),或者自己制作:
// use built-in formatter
DateTimeFormatter fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println(fmt.format(arizonaDate)); // 2017-03-26T03:00:00-07:00
// use custom format
fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println(fmt.format(arizonaDate)); // 2017-03-26T03:00:00.000-07:00