我在 Google 和 Stack Overflow 上浏览了多篇关于 TimeZone 和 SimpleDateFormat 的帖子,但仍然不明白我做错了什么。 我正在处理一些遗留代码,并且有一个方法 parseDate,它给出了错误的结果。
我附上了示例 JUnit,我正在尝试使用它来调查问题。
第一种方法 (testParseStrangeDate_IBM_IBM) 使用 IBM 的实现来格式化 parseDate 方法的输出。 Sun 实现的第二种格式输出。
使用 Sun 的 SimpleDateFormat 使我们的时间相差一个小时(这可能与夏令时有关)。将默认时区设置为 IBM 的实现修复了 parseDate 方法(只需在 setupDefaultTZ 方法中取消注释 3 行)。
我确定这不是错误,但我做错了什么。
@Test
public void testParseStrangeDate_IBM_IBM() {
setupDefaultTZ();
Calendar date = parseDate("2010-03-14T02:25:00");
com.ibm.icu.text.SimpleDateFormat dateFormat = new com.ibm.icu.text.SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
// PASSES:
assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}
@Test
public void testParseStrangeDate_SUN_SUN() {
setupDefaultTZ();
Calendar date = parseDate("2010-03-14T02:25:00");
java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
// FAILS:
assertEquals("2010-03-14 02:25:00", dateFormat.format(date.getTime()));
}
public static Calendar parseDate(String varDate) {
Calendar cal = null;
try {
// DOES NOT MAKE ANY DIFFERENCE:
// com.ibm.icu.text.SimpleDateFormat simpleDateFormat = new
// com.ibm.icu.text.SimpleDateFormat(
// "yyyy-MM-dd'T'HH:mm:ss");
java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss", Locale.US);
Date date = simpleDateFormat.parse(varDate);
cal = GregorianCalendar.getInstance();
cal.setTimeInMillis(date.getTime());
System.out.println("CAL: [" + cal + "]");
} catch (ParseException pe) {
pe.printStackTrace();
}
return cal;
}
private void setupDefaultTZ() {
java.util.TimeZone timeZoneSun = java.util.TimeZone.getTimeZone("America/Chicago");
java.util.TimeZone.setDefault(timeZoneSun);
// UNCOMMENTING THIS ONE FIXES SUN PARSING ??
// com.ibm.icu.util.TimeZone timeZoneIbm = com.ibm.icu.util.TimeZone
// .getTimeZone("America/Chicago");
// com.ibm.icu.util.TimeZone.setDefault(timeZoneIbm);
Locale.setDefault(Locale.US);
}
最佳答案
问题是,您指定了一个不存在的时间。时钟向前走,凌晨 2 点变成凌晨 3 点 - 凌晨 2:25 永远不会发生。
现在,这里可能发生的事情有多种选择。在 Noda Time我相信我们会抛出一个异常(无论如何这就是计划);我相信Joda Time (比 Date/Calendar/SimpleDateFormat 好得多的 Java API - 如果可能的话,您应该考虑迁移到它)将为您提供凌晨 3:25,即转换后 25 分钟。
当您得到一个由于 DST 转换而无法实现的日期/时间组合时,您希望发生什么?在这种情况下,很难确定“错误”结果的含义。我会说您的单元测试有些缺陷 - 不可能应该格式化到那个时间。
我猜测 IBM 时区“有效”的原因是它可能使用美国更改其 DST 转换之前的旧时区数据。尝试使用 3 月 28 日,这是我认为它会否则的时间 - 您可能会发现测试以与 IBM 区域相同的方式失败,但与 Sun 区域不同:)(作为Sun 区域不会将其视为 DST 转换。)
关于java - 使用 TimeZone 和 SimpleDateFormat 进行日期解析/格式化会在 DST 开关周围产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2356672/