簡體   English   中英

為什么 SimpleDateFormat("MM/dd/yyyy") 將日期解析為 10/20/20128?

[英]Why SimpleDateFormat("MM/dd/yyyy") parses date to 10/20/20128?

我有這個代碼:

  DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
  dateFormat.setLenient(false);
  Date date = dateFormat.parse("10/20/20128");

我希望 dateFormat.parse 調用拋出 ParseException,因為我提供的年份是 5 個字符,而不是我定義的格式中的 4 個字符。 但出於某種原因,即使將 lenient 設置為 false,此調用也會返回 10/20/20128 的 Date 對象。

這是為什么? 這對我來說沒有多大意義。 是否有其他設置使其更加嚴格?

20128是一個有效的年份,Java希望世界能夠存活這么長時間。

如果模式字母的數量大於2,則無論數字位數如何,都按字面解釋年份。

參考。

如果您想驗證日期是否有限,您可以定義一個並檢查 -

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date maxDate = sdf.parse("01/01/2099");  // This is the limit

if(someDate.after(maxDate)){            
    System.out.println("Invalid date");            
}

請參閱javadoc

年份:如果格式化程序的日歷是公歷,則應用以下規則。

  • 對於格式化,如果模式字母的數量為2,則年份被截斷為2位數; 否則它被解釋為一個數字。
  • 對於解析,如果模式字母的數量大於2, 無論數字位數如何,都按字面解釋年份 所以使用“MM / dd / yyyy”模式,“01/11/12”解析到公元12年1月11日
  • 對於使用縮寫年份模式(“y”或“yy”)進行解析,SimpleDateFormat必須解釋相對於某個世紀的縮寫年份。 它通過將日期調整為創建SimpleDateFormat實例之前的80年和20年之后來實現此目的。 例如,使用“MM / dd / yy”模式和SimpleDateFormat
    在1997年1月1日創建的實例,字符串“01/11/12”將是
    解釋為2012年1月11日,而字符串“05/04/64”將是
    解釋為1964年5月4日。在解析期間,只包含字符串
    正好由Character.isDigit(char)定義的兩位數字將被解析為默認世紀。 任何其他數字字符串,例如a
    一個數字字符串,三個或更多個數字字符串,或者不是所有數字的兩位數字符串(例如,“ - 1”)按字面解釋。
    所以使用相同的模式解析“01/02/3”或“01/02/003”
    1月2日,3日。 同樣,“01/02 / -3”被解析為公元前1月2日。
  • 否則,將應用日歷系統特定表單。 對於格式化和解析,如果模式字母的數量是4或
    更多,使用日歷特定的長形式。 否則,一個日歷
    使用特定的簡短或縮寫形式。

因此,它將讀取最后一個/作為年份之后的所有字符。

請參閱java.text.SimpleDateFormat API,模式字母y :對於解析,如果模式字母的數量大於2,則無論數字位數如何,都將按字面解釋年份。

在java中使用SimpleDateFormat,您可以實現許多人類可讀的格式。 請考慮以下代碼段:

        Date curDate = new Date();

        SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");

        String DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("dd MMMM yyyy zzzz", Locale.ENGLISH);
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

查看各種格式生成的各種輸出:

2014年5月11日

11-5-2014 11:11:51

2014年5月11日東歐夏令時

太陽,2014年5月11日23:11:51 EEST

隨意修改格式字符串,您可能會得到所需的結果。

時間

我始終建議您使用 java.time,現代 Java 日期和時間 API,進行日期工作。 此外,碰巧 java.time 會給你你要求的異常。

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/uuuu")
            .withResolverStyle(ResolverStyle.LENIENT);
    LocalDate date = LocalDate.parse("10/20/20128", dateFormatter);

結果:

線程“main”中的異常 java.time.format.DateTimeParseException:無法在索引 6 處解析文本“10/20/20128”

提到的索引 6是字符串中 5 位數年份的位置。

也就是說,其他人建議的范圍檢查仍然是一個好主意。 使用 java.time 這很容易。 比如說我們不想接受任何未來的日期:

    LocalDate date = LocalDate.parse("10/20/8012", dateFormatter);
    if (date.isAfter(LocalDate.now(ZoneId.systemDefault()))) {
        System.err.println("Date must not be in the future, was " + date);
    }

日期不能在未來,是 8012-10-20

教程鏈接: Trail:Date Time(Java™ 教程)解釋了如何使用 java.time。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM