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 时区。
我运行下面的代码:
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 时区。