關於LocalDateTime解析的三種模式

Java8引入了新的時間格式Api:LocalDateTimeLocalDateLocalTime,分別用於處理日期-時間、日期和時間。使用他們,我門能夠很方便的把日期轉成String或者把String解析成日期。下面咱們深刻探究一下對於StringLocalDateTime,java提供的三種模式。 如下以LocalDateTime爲例: 對於String轉日期,平時用的最多的就是LocalDateTimeparse方法。前端

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"這個格式仍是會拋出異常DateTimeExceptioncode

寬鬆模式

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