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 | 對於時間格式要求最寬鬆,只要是數字就能解析,並且會自動轉換爲有效日期,可是轉換後的日期與以前相差較大,慎用!!! |