簡體   English   中英

為什么SimpleDateFormat.parse不會在這里拋出異常?

[英]Why does SimpleDateFormat.parse not throw an exception here?

首先請注意我在這里遇到了java6。

我試圖從字符串中獲取可能有不同格式的日期。 出於某種原因,我沒有得到ParseException,我期待一個......

    import java.text.SimpleDateFormat;
    import java.util.Date;

    public class test1{

      public static void main(String argc[]){
          System.out.println(parseAllDateFormats(argc[0]));
    }

      private static final String[] dateFormats = "yyyyMMdd,yyyy/MM/dd,yyyy-MM-dd,dd/MM/yyyy,dd-MM-yyyy,dd-MMM-yyyy,yyyy MM dd".split(",");
      public static Date parseAllDateFormats(String date) {
          if (date == null)
              return null;
          for (int f = 0; f < dateFormats.length; f++) {
              String format = dateFormats[f];
              try {
                  SimpleDateFormat dateFormat = new SimpleDateFormat(format);
    System.out.println("trying " + format);                
                  return dateFormat.parse(date);
              }
              catch (Exception e) {}
          }
          return null;
      }

    }

run:java test1 1980-04-25

我希望得到:

 trying yyyyMMdd trying yyyy/MM/dd trying yyyy-MM-dd Fri Apr 25 00:00:00 EST 1980 

但我只得到:

 trying yyyyMMdd Tue Dec 04 00:00:00 EST 1979 

知道什么是錯的嗎?

SimpleDateFormat默認是寬松的,即使給定日期的格式可能與其配置解析的格式不匹配,也不會拋出異常。 您可以將其設置為不那么寬松,如下所示:

SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setLenient(false);

這樣它將檢查字符實際上是否對該日期有效。

知道什么是錯的嗎?

這是SimpleDateFormat真正麻煩的地方之一。 當試圖使用模式yyyyMMdd解析1980-04-25 ,它按照預期解析1980年,然后-0作為月份,因為它應該是兩個字符,然后4作為月份的日期,即使它應該是兩個字符太。 它忽略了-25因為它已經完成了解析。

具有標准設置的SimpleDateFormat也忽略了沒有月份-0的事實。 它取為0,所以在1980年1月之前的那個月,這就是為什么你得到1979年12月。

SimpleDateFormat非常麻煩,而且Date的設計也很差。 兩者都很久了。 我建議你不要使用SimpleDateFormat 永遠。

java.time

private static final String[] dateFormats
        = "yyyyMMdd,yyyy/MM/dd,yyyy-MM-dd,dd/MM/yyyy,dd-MM-yyyy,dd-MMM-yyyy,yyyy MM dd"
                .split(",");

public static LocalDate parseAllDateFormats(String date) {
    if (date == null) {
        return null;
    }
    for (String format : dateFormats) {
        try {
            System.out.println("trying " + format);                
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(format, Locale.ENGLISH);
            return LocalDate.parse(date, dateFormatter);
        }
        catch (DateTimeParseException e) {
            // Ignore, try next format
        }
    }
    return null;
}

讓我們用你的示例字符串嘗試:

    System.out.println(parseAllDateFormats("1980-04-25"));

輸出是預期的:

 trying yyyyMMdd trying yyyy/MM/dd trying yyyy-MM-dd 1980-04-25 

我正在使用java.time,現代Java日期和時間API。 與舊的日期時間類相比,使用起來更好。 現代DateTimeFormatter可以將解析后的值解析為三種樣式的日期:strict,smart和lenient。 Smart是默認設置,它只接受1到12之間的月號。此外, LocalDate.parse將堅持解析整個字符串,否則將引發異常。

與您的代碼相比,我也進行了一些小修改。 在大多數情況下,我創建一個DateTimeFormatter數組(不是String ),但它不允許我打印trying yyyyMMdd ,所以在這里我沒有。 我把花括號放在第一個if語句中。 我在格式化程序上指定了語言環境,因為月份縮寫在語言之間有所不同,我想控制使用哪種語言。 我捕獲了特定的DateTimeParseException並添加了注釋,為什么我忽略它,因為否則忽略異常是一件壞事,壞事。 在方法的底部,如果沒有格式工作而不是返回null ,您還應該考慮拋出異常。

Java 6

請注意我在這里遇到了java6。

鏈接

暫無
暫無

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

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