使用TimeZone和SimpleDateFormat进行日期解析/格式化会在DST开关周围产生不同的结果 [英] Date parsing/formatting with TimeZone and SimpleDateFormat give different results around DST switch

查看:149
本文介绍了使用TimeZone和SimpleDateFormat进行日期解析/格式化会在DST开关周围产生不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在谷歌和Stack Overflow上发布了关于TimeZone和SimpleDateFormat的多篇帖子,但仍然没有得到我做错的事。
我正在处理一些遗留代码,并且有一个方法parseDate,它给出了错误的结果。



我附加了示例JUnit,我正在尝试使用do调查问题。



第一个方法(testParseStrangeDate_IBM_IBM)使用IBM的实现来格式化 parseDate 方法的输出。
第二种格式输出与Sun的实现。



使用Sun的SimpleDateFormat给我们的时间相差一小时(这可能与Day Light Savings有关)。将默认TimeZone设置为IBM的实现修复 parseDate 方法(只需在setupDefaultTZ方法中取消注释3行)。



我确定这不是错误,但是我做错了。

  @Test 
public void testParseStrangeDate_IBM_IBM(){
setupDefaultTZ();

日历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();

日历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 {
//不会造成任何差异:
// 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();
}
返回cal;
}

private void setupDefaultTZ(){
java.util.TimeZone timeZoneSun = java.util.TimeZone.getTimeZone(America / Chicago);
java.util.TimeZone.setDefault(timeZoneSun);

//解除这一个修复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 (比日期/日历/ SimpleDateFormat好得多的Java API) - 你应该考虑迁移到它,如果你可以)将在凌晨3:25给你,即过渡后25分钟。



当你想要想要时你会发生什么?由于DST过渡,给出了一个不可能的日期/时间组合?在这种情况下,很难确定错误结果的含义。我会说你的单元测试有点瑕疵 -

IBM时区工作是它可以使用旧时区数据,从美国改变其DST转换之前。尝试使用3月28日,也就是我认为 其他情况 - 你可能会发现测试以与IBM区域相同的方式失败,但不是与Sun的失败:)(As太阳区不会将其视为DST过渡。)


I went throe multiple posts about TimeZone and SimpleDateFormat on Google and Stack Overflow, but still do not get what I'm doing wrong. I'm working on some legacy code, and there is a method parseDate, which gives wrong results.

I attached sample JUnit which I'm trying to use do investigate issue.

First method (testParseStrangeDate_IBM_IBM) uses IBM's implementation to format output of parseDate method. Second formats output with Sun's implementation.

Using Sun's SimpleDateFormat gives us time different by an hour (which might be related to Day Light Savings). Setting default TimeZone to IBM's implementation fixes parseDate method (simply uncomment 3 lines in setupDefaultTZ method).

I am sure it's not a bug, but I am doing something wrong.

@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);
}

解决方案

The trouble is, you've specified a time which doesn't exist. The clocks go forward such that 2am becomes 3am - 2:25am never happens.

Now, there are various options for what could happen here. In Noda Time I believe we'd throw an exception (that's the plan anyway); I believe Joda Time (a far better Java API than Date/Calendar/SimpleDateFormat - you should consider migrating to it if you possibly can) will give you 3:25am, i.e. 25 minutes after the transition.

What would you want to happen when you're given a date/time combination which is impossible due to the DST transition? In this situation it's hard to know for sure what you mean by the "wrong" results. I would say your unit test is somewhat flawed - there is no possible time which should be formatted to that time.

My guess as to why the IBM time zone "works" is that it may use old time zone data, from before the US changed its DST transitions. Try using March 28th, which is when I think it would have been otherwise - you'll probably find the tests fail in the same way with the IBM zone, but not with the Sun one :) (As the Sun zone won't consider it a DST transition.)

这篇关于使用TimeZone和SimpleDateFormat进行日期解析/格式化会在DST开关周围产生不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆