Java日期时间API系列35—–Jdk8中java.time包中的新的日期时间API类应用,微秒和纳秒等更精确的时间格式化和解析。

  通过Java日期时间API系列1—–Jdk7及以前的日期时间类中得知,Java8以前除了java.sql.Timestamp扩充纳秒,其他类最大只精确到毫秒;Java8 time包所有相关类都支持纳秒。下面是示意图:

 

 

图中的nano 是 一秒钟包含的纳秒值,0到999999999。毫秒,微秒和纳秒都是通过这个值计算得到的。

 

1.Timestamp格式化中的纳秒。

java.sql.Timestamp.toString()方法中的格式为:

格式化模板是:yyyy-mm-dd hh:mm:ss.fffffffff,这里的 fffffffff 指的是纳秒,但会将最后的0省略掉。比如:

2020-05-23 17:06:30.0
2020-05-23 17:06:30.272
2020-05-23 17:06:30.27215
2020-05-23 17:06:30.27215062

 

2.Timestamp格式解析

.

/**
     * 解析Timestamp格式字符串为LocalDateTime  默认格式 yyyy-mm-dd hh:mm:ss.fffffffff 其中 fffffffff 纳秒,省略后面的0 比如:
     * 
     * 2020-05-23 17:06:30.0
     * 2020-05-23 17:06:30.272
     * 2020-05-23 17:06:30.27215
     * 2020-05-23 17:06:30.27215062
     *

* @param text
*
@return LocalDateTime
*/
public static LocalDateTime parseTimestampStyleToLocalDateTime(String text){
//预处理
Objects.requireNonNull(text, "text");
text
=text.trim();
if(!text.contains(".")){
throw new DateTimeException("text is not supported! " + text);
}

//.分割成2部分,分别分析
String[] textArr = text.split("\\.");
String main
= textArr[0];
String nanoOfSecond
= textArr[1];
int mainLen = main.length();
int len = nanoOfSecond.length();
if(mainLen != DateFormatPattern.YYYY_MM_DD_HH_MM_SS.length()){
throw new DateTimeException("text is not supported! " + text);
}
if(len>9){
throw new DateTimeException("text is not supported! " + text);
}

//纳秒部分补0
StringBuilder sb = new StringBuilder();
for(int i=0;i<9-len;i++){
sb.append(
"0");
}
nanoOfSecond
= nanoOfSecond+sb.toString();
text
= main+"."+nanoOfSecond;

//使用yyyy-MM-dd HH:mm:ss.SSSSSSSSS 标准格式解析
return parseToLocalDateTime(text, DateTimeFormatterUtil.YYYY_MM_DD_HH_MM_SS_SSSSSSSSS_FMT);
}

 

测试:

  /**
     * 含纳秒Timestamp时间格式解析
     */
    @Test
    public void parseTimestampStyleTest(){
        
        Date date = DateTimeFormatterUtil.smartParseToDate("2020-05-23 17:06:30");
        
        Date date2 = DateTimeFormatterUtil.parseTimestampStyleToDate("2020-05-23 17:06:30.0");
        
        Date date3 = DateTimeFormatterUtil.parseTimestampStyleToDate("2020-05-23 17:06:30.0");
        
        Assert.assertEquals(date, date2);
        Assert.assertEquals(date2, date3);
        
        LocalDateTime localDateTime1 = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23 17:06:30.272150");
        
        LocalDateTime localDateTime2 = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23 17:06:30.27215");
        Assert.assertEquals(localDateTime1, localDateTime2);
    }

 

 

 

3.微秒和纳秒的格式化和解析

 // ==================================yyyy-MM-dd HH:mm:ss.SSSSSS 相关Pattern==================================    
    
    /**
     * yyyy-MM-dd HH:mm:ss.SSSSSS 比如:2020-05-23 17:06:30.272150
     */
    public static final String YYYY_MM_DD_HH_MM_SS_SSSSSS = "yyyy-MM-dd HH:mm:ss.SSSSSS";
    
    
    
    // ==================================yyyy-MM-dd HH:mm:ss.SSSSSSSSS 相关Pattern==================================    
    
    /**
     * yyyy-MM-dd HH:mm:ss.SSSSSSSSS 比如:2020-05-23 17:06:30.272150620
     */
    public static final String YYYY_MM_DD_HH_MM_SS_SSSSSSSSS = "yyyy-MM-dd HH:mm:ss.SSSSSSSSS";    

 

 

(1)格式化

  /**
     * 含纳秒时间格式化
     */
    @Test
    public void formatTimeWithNanoTest(){
        LocalDateTime localDateTime = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23T17:06:30.272150620+08:00");
        //时间格式化
        Assert.assertEquals("17:06:30.272", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.HH_MM_SS_SSS_FMT));
        Assert.assertEquals("17:06:30.272150", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.HH_MM_SS_SSSSSS_FMT));
        Assert.assertEquals("17:06:30.272150620", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.HH_MM_SS_SSSSSSSSS_FMT));
        
        //日期时间格式化
        Assert.assertEquals("2020-05-23 17:06:30.272150", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.YYYY_MM_DD_HH_MM_SS_SSSSSS_FMT));
        Assert.assertEquals("2020-05-23 17:06:30.272150620", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.YYYY_MM_DD_HH_MM_SS_SSSSSSSSS_FMT));

        //ISO日期时间格式化
        Assert.assertEquals("2020-05-23T17:06:30.272150620+0800", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.YYYY_MM_DD_T_HH_MM_SS_SSSSSSSSS_Z_FMT));
        Assert.assertEquals("2020-05-23T17:06:30.272150620+08:00", DateTimeFormatterUtil.format(localDateTime, DateTimeFormatterUtil.YYYY_MM_DD_T_HH_MM_SS_SSSSSSSSS_XXX_Z_FMT));
    }

 

 

 

(2)解析

 /**
     * 含纳秒时间格式解析
     */
    @Test
    public void parseTimeWithNanoTest(){
        LocalDateTime localDateTime1 = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23T17:06:30.272150620+08:00");
        
        LocalDateTime localDateTime2 = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23T17:06:30.272150+08:00");
        
        LocalDateTime localDateTime3 = DateTimeFormatterUtil.smartParseToLocalDateTime("2020-05-23T17:06:30.272+08:00");
        
        Assert.assertTrue(localDateTime3.isBefore(localDateTime2));
        
        Assert.assertTrue(localDateTime2.isBefore(localDateTime1));
    }

 

4.LocalDateTime转Date会精度丢失,丢失毫秒以后部分。

因为Date只精确到毫秒,下面是转换方法:DateTimeConverterUtil类中

    /**
     * LocalDateTime转Date
     * @param localDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime localDateTime) {
        Objects.requireNonNull(localDateTime, "localDateTime");
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
Date from(Instant instant)方法:
    public static Date from(Instant instant) {
        try {
            return new Date(instant.toEpochMilli());
        } catch (ArithmeticException ex) {
            throw new IllegalArgumentException(ex);
        }
    }

 

 核心部分:new Date(instant.toEpochMilli()); 创建Date只使用了Instant的时间戳部分 instant.toEpochMilli()。只到毫秒。

 

源代码地址:https://github.com/xkzhangsan/xk-time