通过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 比如: * <pre> * 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 *</pre> * @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()。只到毫秒。