SimpleDateFormat 解析时间和日期错误的分钟和秒

问题描述 投票:0回答:3

任何人都可以向我解释一下这段代码有什么问题吗:

System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'").parse("2015-04-22T19:54:11.827Z"));

System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'").parse("2015-04-22T19:54:11.0Z"));

输出是:

Wed Apr 22 20:07:47 GMT+02:00 2015
Wed Apr 22 19:54:00 GMT+02:00 2015

输入时间中有毫秒时请注意分钟的差异。

java android date
3个回答
9
投票

对于

SimpleDateFormat
,毫秒格式值包含大写
S
字符,而不是小写
s
秒字符。

分钟中的第二个数字 55

S 毫秒数 978

它将

827
解释为秒,并将这些秒(847 秒是 13 分 47 秒)添加到您的值中。

使用

SSS
表示毫秒。

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

顺便说一句,如果是相同的,则无需多次重新创建

SimpleDateFormat
。 您可以创建一次,将其保存到变量中,然后多次调用
parse
,对于您想要解析的每个日期/时间字符串调用一次。


1
投票

使用大写 SSS 而不是 sss,因为 s 在 SimpleDateFormat 中被解释为秒。因此,将您的代码更改为

System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse("2015-04-22T19:54:11.827Z"));

System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse("2015-04-22T19:54:11.0Z"));

这将为您完成这项工作。为了优化你的代码,请使用这个

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
System.out.println(sdf.parse("2015-04-22T19:54:11.827Z"));

System.out.println(sdf.parse("2015-04-22T19:54:11.0Z"));

无需一次又一次创建对象。只需创建一次并使用它来解析。


0
投票

不幸的是接受的答案中使用的模式不正确。切勿在日期时间解析/格式化模式中指定

'Z'
,因为
'Z'
是字符文字,而
Z
是指定时区偏移量的模式字符。要解析表示时区偏移的字符串,您必须使用
X
(或
XX
XXX
,具体取决于要求)。

SimpleDateFormat
容易出错

2014 年 3 月,Java 8 引入了现代的

java.time
日期时间 API,取代了容易出错的旧版
java.util
日期时间 API
。任何新代码都应使用
java.time
API。如果您将
.sss
java.time.format.DateTimeFormatter
一起使用,它将抛出以下异常,提示您查看问题。

java.lang.IllegalArgumentException: Too many pattern letters: s

但是

SimpleDateFormat
默默地解析了你的字符串,给你意想不到的结果。

使用现代日期时间 API 的解决方案

由于您的日期时间字符串采用

Instant#parse
使用的默认格式,因此您可以直接将其解析为
Instant

演示:

import java.time.Instant;
    
public class Main {
    public static void main(String[] args) {
        Instant instant1 = Instant.parse("2015-04-22T19:54:11.827Z");
        Instant instant2 = Instant.parse("2015-04-22T19:54:11.0Z");
        System.out.println(instant1);
        System.out.println(instant2);
    }
}

输出:

2015-04-22T19:54:11.827Z
2015-04-22T19:54:11Z

在线演示

您可以从

java.time
派生其他
Instant
类,例如

Instant instant = Instant.now();

// ZoneId.systemDefault() returns the ZoneId set to the JVM executing the code
// Replace it with the applicable ZoneId e.g. ZoneId.of("America/New_York")
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());

OffsetDateTime odt = zdt.toOffsetDateTime();
LocalDateTime ldt = zdt.toLocalDateTime();

注意: 无论出于何种原因,如果您需要

java.util.Date
对象的
Instant
实例,您可以按如下方式操作:

java.util.Date date = Date.from(instant);

Trail:日期时间了解有关现代日期时间 API 的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.