Java 6 位毫秒格式刷解析错误求解

2020-03-04 20:09:36 +08:00
 alfredcai

最近解析别人的 API,分钟一直对不上,后来发现 Date 类解析有误,换成 LocalDataTime 就好了,网上资料很少,于是就来这里求解答了。具体代码如下。

public class DateFormat {
    public static void main(String[] args) throws ParseException {
        String strDate = "2020-02-25T03:13:28.620818Z";
        String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'";
        
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Date date = simpleDateFormat.parse(strDate);
        System.out.println(date);

        LocalDateTime localDateTime = LocalDateTime.parse(strDate, DateTimeFormatter.ofPattern(pattern));
        System.out.println(localDateTime);
    }
}
> Task :DateFormat.main()
Tue Feb 25 03:23:48 CST 2020
2020-02-25T03:13:28.620818

可以看到 SimpleDateFormat 解析出来的比正确值多了 10 分钟左右,我算了下差不多是 620818 毫秒=10.3469666 分钟,这算是 Java 老接口的 Bug 吗?

2902 次点击
所在节点    Java
8 条回复
chendy
2020-03-04 20:19:21 +08:00
1000 毫秒 = 1 秒,所以并不存在 6 位的毫秒
SImpleDateFormat 的 S 是毫秒,所以会多(为啥不报错呢…
DateTimeFormatter 的 S 是 fraction-of-second,S 越多精度越高,最多 9 个 S 显示到纳秒
also24
2020-03-04 20:28:17 +08:00
题外话:Z 不是 0 时区么?怎么转出来 CST 时间还是一样的?
dallaslu
2020-03-04 21:39:10 +08:00
就是微秒嘛,普通的只到毫秒
alfredcai
2020-03-04 22:18:58 +08:00
@chendy 我可能表达不清楚,我是想出 Date 解析小数点后 6 位出错。它把 .620818 当成 620818 毫秒了,算出来就多了十分钟。我现在觉得是 Date 的精度只支持到小数点后 3 位,也就是毫秒级别。从下面的代码里可以看出这点。

```java
Date d = new Date();
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(d));
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(d));
```
```
2020-03-04 22:14:06.518
2020-03-04 22:14:06.000518
```
第二个打印出来只是把 518 向后移了 3 位,但我希望是.518123 再多显示三位,也就是精确到微秒。
SoloCompany
2020-03-04 22:23:41 +08:00
老式 Date api 以及 SimpleDateFormat 只支持毫秒精度, 并且小数点后的数字作为整数而非小数解释, 所以如果要使用 SimpleDateFormat 的话, 只能手动把六位微秒进行截断 /补 0 凑够刚好三位才可以

或许也可以选择使用 java.sql.Timestamp
比如
java.sql.Timestamp.valueOf("2020-02-25T03:13:28.620818Z".replace("T", " ").replace("Z", ""))
可以解释小数点, 最高精度 9 位 (纳秒)
alfredcai
2020-03-04 22:31:09 +08:00
@also24 还好上来发帖,帮忙指出错误。感谢感谢。所以之前自己写的都是错的。pattern 应该是"yyyy-MM-dd'T'HH:mm:ss.SSSX"。LocalDateTime 换成 ZoneDateTime
chendy
2020-03-04 22:48:50 +08:00
@alfredcai 是的,Date 里面只有一个 long 表示毫秒,并不能支持更高的精度了,java8 的时间 api 才开始支持
br00k
2020-03-05 20:26:03 +08:00
Instant.parse("2020-02-25T03:13:28.620818Z")

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/649887

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX