Java日期格式问题

3
以下是我运行的一段代码。
@Test
public void testMyMehotd() {
    String expected = "2012-09-12T20:13:47.796327Z";
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
    //df.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date d = null;
    try {
        d = df.parse(expected);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return;
    }

    String actual = df.format(d);

    System.out.println(expected);
    System.out.println(actual);

}

但输出的结果与我的期望不同。

expected : 2012-09-12T20:13:47.796327Z
actual   : 2012-09-12T20:27:03.000327Z

有人可以告诉我这个问题的原因以及解决方法吗?

提前感谢。


4
看起来你正在打印日期,而不是字母"d"。 - gtgaxiola
定义日期格式中的 SSSSSS 是否意味着微秒? - Keen Sage
2个回答

5
每当你超过999毫秒,DateFormat都会尝试将剩余的毫秒数添加到你的日期中。考虑以下更简单的例子:
 String expected = "2012-09-12T20:13:47.1001Z";
 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSS'Z'");
 Date d = df.parse(expected);

生成的日期将是2012-09-12T20:13:48.0001。也就是说,由于你有1001毫秒,你会得到1额外时间(1000毫秒),以及1毫秒(1001%1000)。因此,与原始日期中的47秒不同,你得到了48秒。
这也会发生在尝试解析一个月份中无效的天数时。例如,如果您尝试在九月份添加一天并解析2012-09-31
String expected = "2012-09-31";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date d = df.parse(expected);
System.out.println(df.format(d));

你实际上会得到2012-10-01。这是因为DateFormat会检测到9月31日不是有效的日期,并尝试使用启发式方法来转换Date,从而添加一天,最终得到下个月的第一天。
有一个选项可以告诉解析器不要使用这些启发式方法,通过设置lenient模式为false
df.setLenient(false);

然而,使用此模式,上述两个示例都会抛出 ParseException

谢谢你的回答。SSSSSS的格式中是否表示微秒? - Keen Sage
@Sashwat:不,使用多少个“S”并不重要,一个就足以匹配毫秒。但在宽松模式下,“S”将匹配您拥有的所有毫秒,并尝试使用启发式方法对其进行处理(将时间添加到原始日期)。 - João Silva

2

S代表毫秒,你传递了796327毫秒。这个数字相当于13[min]:16[sec]:327[millis],因此额外的分钟和秒被添加到你的日期中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接