Java8引入了新的时间格式Api:LocalDateTime
、LocalDate
和LocalTime
,分别用于处理日期-时间、日期和时间。使用他们,我门能够很方便的把日期转成String
或者把String
解析成日期。下面咱们深刻探究一下对于String
转LocalDateTime
,java提供的三种模式。 如下以LocalDateTime
为例: 对于String
转日期,平时用的最多的就是LocalDateTime
的parse
方法。前端
public static LocalDateTime parse(CharSequence text) {
return parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
return formatter.parse(text, LocalDateTime::from);
}
复制代码
parse
方法提供两个重载方法,其实最后调用的都是parse(CharSequence text, DateTimeFormatter formatter)
,这里的关键就是DateTimeFormatter
,当咱们只传text的时候,默认的解析规则是:DateTimeFormatter.ISO_LOCAL_DATE_TIME
,他的格式以下所示:java
/** * The ISO date-time formatter that formats or parses a date-time without * an offset, such as '2011-12-03T10:15:30'. * The returned formatter has a chronology of ISO set to ensure dates in * other calendar systems are correctly converted. * It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style. */
public static final DateTimeFormatter ISO_LOCAL_DATE_TIME;
static {
ISO_LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}
复制代码
也就是yyyy-MM-ddTHH:mm:ss
(这里有个关键点就是方法最后有个参数ResolverStyle.STRICT
,这就是严格模式)。这种数据格式是ECMAScript基于ISO 8601扩展格式的简化,在国外比较常见。咱们平时使用最多的是yyyy-MM-dd HH:mm:ss
这个格式,比较方便前端展现。若是要转换成这种格式,那应该怎么办呢? 咱们能够自定义一个DateTimeFormatter
来完成。markdown
LocalDateTime parse = LocalDateTime.parse( "2021-02-23 08:02:02", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//输出结果
2021-02-23T08:02:02
LocalDateTime parse = LocalDateTime.parse( "2021-02-29 08:02:02", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//输出结果
2021-02-28T08:02:02
复制代码
细心的朋友可能已经发现了,我传的是02-29,为何结果是02-28呢,这里就牵扯本文所说的解析模式了。首先咱们看一下DateTimeFormatter.ofPattern
的源码:app
public static DateTimeFormatter ofPattern(String pattern) {
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
}
public DateTimeFormatter toFormatter() {
return toFormatter(Locale.getDefault(Locale.Category.FORMAT));
}
public DateTimeFormatter toFormatter(Locale locale) {
return toFormatter(locale, ResolverStyle.SMART, null);
}
复制代码
关键的地方就是 toFormatter
,依次进入方法能够看到最后传入了一个默认参数:ResolverStyle.SMART
,顾名思义,smart就是智能模式,ResolverStyle
提供:STRICT(严格),SMART(智能),LENIENT(宽松)三种模式对日期进行解析,下面咱们详细讨论下三种模式的不一样。ide
咱们首先定义一个严格的日期解析规则,而后用它解析日期。ui
/** * 自定义严格日期格式:yyyy-MM-dd HH:mm:ss **/
public static DateTimeFormatter STRICT_DATE_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral(" ")
.append(ISO_LOCAL_TIME)
.toFormatter(Locale.CHINESE)
.withResolverStyle(ResolverStyle.STRICT);
LocalDateTime normal = LocalDateTime.parse( "2021-04-30 08:02:02", STRICT_DATE_TIME);
// 输出结果
2021-04-30T08:02:02
LocalDateTime normal = LocalDateTime.parse( "2021-04-31 08:02:02", STRICT_DATE_TIME);
// 输出结果
Caused by: java.time.DateTimeException: Invalid date 'APRIL 31'
复制代码
由上面代码能够得知:对于不合法的日期,严格模式直接抛出异常。你们也能够改变一下其余字段,最后会发现,必须严格按照时间日期的取值,不然转换都会抛出异常。spa
/** * 自定义智能日期格式:yyyy-MM-dd HH:mm:ss **/
public static DateTimeFormatter SMART_DATE_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral(" ")
.append(ISO_LOCAL_TIME)
.toFormatter(Locale.CHINESE);//默认智能模式
LocalDateTime normal = LocalDateTime.parse( "2021-02-29 18:02:02", SMART_DATE_TIME);
//输出结果
2021-02-28T18:02:02
LocalDateTime unnormal = LocalDateTime.parse( "2021-04-31 08:02:02", SMART_DATE_TIME);
//输出结果
2021-04-30T08:02:02
复制代码
对于不合法的日期,智能模式会自动把数据转换成最近的有效日期,可是要注意不合法日期也是有规则的,超出个字段的取值范围也会有问题。你搞个"2021-02-32"这个格式仍是会抛出异常DateTimeException
。code
public static DateTimeFormatter LENIENT_DATE_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral(" ")
.append(ISO_LOCAL_TIME)
.toFormatter(Locale.CHINESE)
.withResolverStyle(ResolverStyle.LENIENT);
LocalDateTime normal = LocalDateTime.parse( "2021-02-32 18:02:02", LENIENT_DATE_TIME);
//输出结果
2021-03-04T18:02:02
LocalDateTime unnormal = LocalDateTime.parse( "2021-13-31 08:02:02", LENIENT_DATE_TIME);
//输出结果
2022-01-31T08:02:02
复制代码
宽松模式对数据的要求就比较宽松了,只要是数字通常都会解析成功,他会自动把不合法的日期转为有效日期,好比说,13就会转成12+1,这样2021年就变成了了2022年,天和时分秒同理。 orm
综上所述,咱们能够总结出:ip
解析模式 | 特色 |
---|---|
STRICT | 对于时间格式要求最严格,强制合法时间才能解析 |
SMART | 对于有效期内的日期字段,能够解析为最近的有效日期,经常使用与处理闰年2月份,和跨月时间格式问题 |
LENIENT | 对于时间格式要求最宽松,只要是数字就能解析,并且会自动转换为有效日期,可是转换后的日期与以前相差较大,慎用!!! |