Java MST被映射到乔达的丹佛时区,目前为MDT。这是joda DateTimeZone的一个bug吗?

Java MST被映射到乔达的丹佛时区,目前为MDT。这是joda DateTimeZone的一个bug吗?,java,jodatime,timezone-offset,Java,Jodatime,Timezone Offset,我需要将GMT转换为亚利桑那时间。亚利桑那州目前有MST(夏令时关闭) 但是,在Joda TimeDateTimeZonecode中,MST已映射到America/Denver: map.put("MST", "America/Denver"); 可以看出,目前丹佛已启用夏令时,因此有了MDT。 那么为什么要在DateTimeZonecode中进行这样的映射呢 从GMT转换到亚利桑那州的本地时区时,我得到的偏移量为GMT-6,这是错误的,应该是GMT-7,因为MST没有夏令时 这是虫子吗? 如

我需要将
GMT
转换为亚利桑那时间。亚利桑那州目前有
MST
(夏令时关闭)

但是,在Joda Time
DateTimeZone
code中,
MST
已映射到
America/Denver

map.put("MST", "America/Denver");
可以看出,目前丹佛已启用夏令时,因此有了
MDT
。 那么为什么要在
DateTimeZone
code中进行这样的映射呢

GMT
转换到亚利桑那州的本地时区时,我得到的偏移量为
GMT-6
,这是错误的,应该是
GMT-7
,因为
MST
没有夏令时

这是虫子吗?
如何解决这个问题?

起初,我认为Joda time将使用与基本Java时区相同的时区ID。我对代码进行了调试,发现代码有点复杂。虽然可能有一个与Joda并行的程序,它使用与基本Java相同的ID,但实际上是从Joda jar中的文件加载时区信息。本例使用所有Joda类完成。 dt在亚利桑那州凤凰城的时间播出

public static void main(String[] args)
{
  //List all time zones
  Set<String> timezones = DateTimeZone.getAvailableIDs();
  for(String tz : timezones)
  {
    System.out.println(tz);
  }

  DateTimeZone arizona = DateTimeZone.forID("US/Arizona");
  DateTimeZone.setDefault(arizona);
  DateTime dt = new DateTime();
  System.out.println(dt);

}
publicstaticvoidmain(字符串[]args)
{
//列出所有时区
设置时区=DateTimeZone.getAvailableIDs();
用于(字符串tz:时区)
{
系统输出打印LN(tz);
}
DateTimeZone arizona=DateTimeZone.forID(“美国/亚利桑那州”);
DateTimeZone.setDefault(亚利桑那州);
DateTime dt=新的DateTime();
系统输出打印ln(dt);
}

这些三个字母缩写的问题在于它们是

因此,
MST
是一个时区名称,可以应用于许多不同的地区,它们可能有不同的DST规则(有些可能有DST,有些可能没有,更不用说历史信息了-有些可能过去有过DST,现在没有了,或者相反)

旧的API(
java.util.TimeZone
)处理这些模糊性,假设这些模糊的三个字母的名称具有默认值,因此
MST
被映射到
America/Denver
,并保存在joda time-IMO中,这是因为兼容性原因(您可以在源代码中看到,我使用的是jodatime 2.7)。至少我可以从评论中理解:

map.put("MST", "America/Denver");  // JDK 1.1 compatible
此映射仅用于
DateTimeZone.forTimeZone(TimeZone)
,这是一种将旧的
TimeZone
类转换为jodatime的
DateTimeZone
的方法(对我来说,这确认了兼容性原因)


如果您想确保您的代码使用正确的时区,您可以按照中的说明,使用
America/Phoenix
而不是
MST
。这将消除歧义,并使您的代码更清楚地了解它使用的时区

这些时区名称(
大陆/城市
)来自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 Time被认为是一个基本上“已完成”的项目。没有计划进行重大改进。如果使用JavaSE8,请迁移到Java.time(JSR-310)

如果使用<强> java 8 < />,请考虑使用这更容易


如果您使用的是Java,您能否明确指定
America/Phoenix
?(我不知道JodaTime,但我猜它应该能够理解。)如果其他的都失败了,你可以考虑转换到java 8代码> java。时间< /C>日期和时间类或者它们的java 6和7的后端,ThreeTen Backport。如果您已经有一个使用JodaTime的大型代码库,那么这当然不是您想要的。
// 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]
// 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