SimpleDateFormat 将字符串解析为错误的时间

SimpleDateFormat parses a string to wrong time

我运行下面的代码:

SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");

    try{
        Date date = sdf.parse("03-28-2003 01:00:00");
        System.out.print(date.toString());
    }
    catch(Exception e){
        //do something
    }

解析的结果是这个日期:2003-03-28T02:00:00.000+0300

增加一小时。

当我将 year/day/hour 更改为任何其他有效数字时,我得到了正确的时间,没有增加额外的小时。如果我只更改分钟或秒数,我仍然会得到增加的小时数。

谁能告诉我为什么会这样?

编辑:

这与我的程序 运行s on- UTC+02:00 时区应用夏令时有关。 在这个时区,时钟在 2003 年 3 月 28 日更改。这就是添加一个小时的原因,正如下面的评论和答案所建议的那样。

我使用了答案中建议的代码来解析我的日期并且解析成功了!日期被正确解析,没有添加额外的时间。

准确地找出你的代码做什么是复杂的,因为不仅 SimpleDateFormat.parse() 可能取决于计算机的默认时区(并且在这种情况下模式不包括时区) , 也 Date.toString() 取决于默认时区。但是,我知道您想用 UTC 解释日期字符串,所以我会集中精力进行正确的解析,而不用太担心打印的内容。

Feek 的评论是正确的,将 SimpleDateFormat 的时区设置为 UTC 将得到你想要的,例如:

    sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));

try 之前添加了这一行,我在我的计算机上得到了这个输出:

Fri Mar 28 02:00:00 CET 2003

凌晨 2 点。 CET 与 1 UTC 一致,所以现在解析正确。

补充一下,如果可以使用Java8日期和时间类,我觉得对应的代码更清晰一些:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss");
    LocalDateTime dateTime = LocalDateTime.parse("03-28-2003 01:00:00", formatter);
    OffsetDateTime utcDateTime = dateTime.atOffset(ZoneOffset.UTC);
    System.out.println(utcDateTime);

重点不是它更短,而是你不会轻易怀疑它的作用,也不会轻易遇到时区或 DST 问题。一个额外的好处是输出也符合预期:

2003-03-28T01:00Z

现在很明显时间是正确的(Z表示Z或Zulu或UTC时区,它有多个名称)。

如果出于某种原因您绝对需要一个老式的 java.util.Date 对象,那并不困难:

    Date date = Date.from(utcDateTime.toInstant());

这与我们从 sdf.parse() 获得的日期相同,采用 UTC 时区。