V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
alfredcai
V2EX  ›  Java

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

  •  
  •   alfredcai · 2020-03-04 20:09:36 +08:00 · 2901 次点击
    这是一个创建于 1717 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近解析别人的 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 吗?

    8 条回复    2020-03-05 20:26:03 +08:00
    chendy
        1
    chendy  
       2020-03-04 20:19:21 +08:00
    1000 毫秒 = 1 秒,所以并不存在 6 位的毫秒
    SImpleDateFormat 的 S 是毫秒,所以会多(为啥不报错呢…
    DateTimeFormatter 的 S 是 fraction-of-second,S 越多精度越高,最多 9 个 S 显示到纳秒
    also24
        2
    also24  
       2020-03-04 20:28:17 +08:00
    题外话:Z 不是 0 时区么?怎么转出来 CST 时间还是一样的?
    dallaslu
        3
    dallaslu  
       2020-03-04 21:39:10 +08:00
    就是微秒嘛,普通的只到毫秒
    alfredcai
        4
    alfredcai  
    OP
       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
        5
    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
        6
    alfredcai  
    OP
       2020-03-04 22:31:09 +08:00
    @also24 还好上来发帖,帮忙指出错误。感谢感谢。所以之前自己写的都是错的。pattern 应该是"yyyy-MM-dd'T'HH:mm:ss.SSSX"。LocalDateTime 换成 ZoneDateTime
    chendy
        7
    chendy  
       2020-03-04 22:48:50 +08:00
    @alfredcai 是的,Date 里面只有一个 long 表示毫秒,并不能支持更高的精度了,java8 的时间 api 才开始支持
    br00k
        8
    br00k  
       2020-03-05 20:26:03 +08:00 via iPhone
    Instant.parse("2020-02-25T03:13:28.620818Z")
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2739 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 10:01 · PVG 18:01 · LAX 02:01 · JFK 05:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.