这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
❤️作者简介:Java领域优质创作者🏆,CSDN博客专家认证🏆,华为云享专家认证🏆
❤️技术活,该赏
❤️点赞 👍 收藏 ⭐再看,养成习惯
大家好,我是小虚竹。之前有粉丝私聊我,问能不能把JAVA8 新的日期时间API(JSR-310)知识点梳理出来。答案是肯定的,谁让我宠粉呢。由于内容偏多,会拆成多篇来写。
闲话就聊到这,请看下面的正文。
DateTimeFormatter
DateTimeFormatter类说明
DateTimeFormatter的作用是进行格式化日期时间显示,且DateTimeFormatter是不可变类且是线程安全的。
1 | java复制代码public final class DateTimeFormatter { |
说到时间的格式化显示,就要说老朋友SimpleDateFormat了,之前格式化Date就要用上。但是我们知道SimpleDateFormat是线程不安全的,还不清楚的,请看这篇文章java的SimpleDateFormat线程不安全出问题了,虚竹教你多种解决方案
DateTimeFormatter常用的用法
格式化
1 | java复制代码 ZonedDateTime zonedDateTime = ZonedDateTime.now(); |
解析
1 | java复制代码 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒"); |
大家有没有注意到,parse方法 是放在LocalDateTime类中 的,而不是DateTimeFormatter类中 。这样的设计符合正常的思路想法,想解析出LocalDateTime 的日期时间,那就用LocalDateTime 。想解析其他的JSR-310的日期时间对象,那就用对应的日期时间对象去解析。
博主把常用的日期时间API都看了,这些里面除了Clock (时钟不需要解析的),其他都有实现parse方法 。
DateTimeFormatter的坑
1、在正常配置按照标准格式的字符串日期,是能够正常转换的。如果月,日,时,分,秒在不足两位的情况需要补0,否则的话会转换失败,抛出异常。
1 | java复制代码 DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); |
会报错:
1 | java复制代码java.time.format.DateTimeParseException: Text '2021-7-20 23:46:43.946' could not be parsed at index 5 |
分析原因:是格式字符串与实际的时间不匹配
“yyyy-MM-dd HH:mm:ss.SSS”
“2021-7-20 23:46:43.946”
中间的月份格式是MM,实际时间是7
解决方案:保持格式字符串与实际的时间匹配
1 | java复制代码 DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); |
2、YYYY和DD谨慎使用
1 | java复制代码 LocalDate date = LocalDate.of(2020,12,31); |
1 | java复制代码Java’s DateTimeFormatter pattern “YYYY” gives you the week-based-year, (by default, ISO-8601 standard) the year of the Thursday of that week. |
YYYY是取的当前周所在的年份,week-based year 是 ISO 8601 规定的。2020年12月31号,周算年份,就是2021年
1 | java复制代码 private static void tryit(int Y, int M, int D, String pat) { |
1 | ini复制代码Y=2020 M=01 D=20 formatted with "MM/DD/YYYY" -> 01/20/2020 |
最后三个日期是有问题的,因为大写的DD代表的是处于这一年中那一天,不是处于这个月的那一天,但是dd就没有问题。
例子参考于:www.cnblogs.com/tonyY/p/121…
所以建议使用yyyy和dd。
3、DateTimeFormatter.format(Instant)会报错
报错信息:
1 | java复制代码java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra |
分析原因:
代码**DateTimeFormatter.format(Instant)**是怎么处理的呢?
1 | java复制代码 public String format(TemporalAccessor temporal) { |
首先new了个StringBuilder对象,用来拼接字符串;
然后调用**formatTo(temporal, buf)**方法
1 | java复制代码public void formatTo(TemporalAccessor temporal, Appendable appendable) { |
**formatTo(temporal, buf)**方法也是先判断两个入参空处理。
然后,Instant对象被封装在一个新new的DateTimePrintContext对象
运行demo有问题,进行排查
1 | java复制代码 //根据特定格式格式化日期 |
到这里已经是jdk的源码了DateTimeFormatter.format
从上面可知,会调用 NumberPrinterParser.format() NumberPrinterParser是在DateTimeFormatterBuilder类中的。
到这一步会报错
为什么会报错呢,我们来看下context.getValue(field)发生了什么:
从上面代码可行,temporal实际上是Instant对象,Instant.getLong只支持四种字段类型。。
1 | 复制代码NANO_OF_SECOND |
如果不是上面这几种字段类型,则抛出异常
DateUtil.format当遇到DateTimeFormatter会将Date对象首先转换为Instant,因为缺少时区,导致报错。
解决方案:
1 | java复制代码/** |
先把date类型转化为LocalDateTime类型,然后再进行DateTimeFormatter.format(LocalDateTime)的格式化
测试demo
1 | java复制代码//根据特定格式格式化日期 |
DateTimeFormatterBuilder
DateTimeFormatterBuilder类说明
DateTimeFormatter 的所有格式化器都是用DateTimeFormatterBuilder 建造器类创建的。
看下面两个ofPattern 源码:
1 | java复制代码//DateTimeFormatter |
解析风格配置
官方提供了四种解析风格的配置,如下枚举 SettingsParser :
1 | java复制代码 static enum SettingsParser implements DateTimePrinterParser { |
对应DateTimeFormatterBuilder 类中的方法:
1 | java复制代码// 大小写敏感 |
这四个方法对应的源码如下:
1 | java复制代码// 大小写敏感 |
可以看出,都是调用appendInternal 方法。
接着往下看 appendInternal 源码:
1 | java复制代码 private int appendInternal(DateTimePrinterParser pp) { |
其中active 是一个DateTimeFormatterBuilder 实例,且这个DateTimeFormatterBuilder 实例内部有一个列表 List< DateTimePrinterParser > ,看了源码可知,真正做解析工作的是DateTimePrinterParser 对应的实例来做的。
DateTimePrinterParser 的源码:
1 | java复制代码 interface DateTimePrinterParser { |
源码有一共有16个DateTimePrinterParser 的实例。
1 | java复制代码//1.Composite printer and parser. |
推荐相关文章
hutool日期时间系列文章
2DateUtil(时间工具类)-常用的时间类型Date,DateTime,Calendar和TemporalAccessor(LocalDateTime)转换
9LocalDateTimeUtil(JDK8+中的{@link LocalDateTime} 工具类封装)
10TemporalAccessorUtil{@link TemporalAccessor} 工具类封装
其他
java的SimpleDateFormat线程不安全出问题了,虚竹教你多种解决方案
本文转载自: 掘金