簡體   English   中英

Lenient SimpleDateFormat表現得很奇怪

[英]Lenient SimpleDateFormat acting strange

我理解,為了正確驗證日期字符串,必須使DateFormat實例非寬松,以便從格式錯誤的日期獲取所有ParseExceptions。 但考慮一下

String  dubiousDate = "2014-04-01";
DateFormat  sdf = new SimpleDateFormat( "yyyyMMdd");
Date d;
try {
    d = sdf.parse( dubiousDate);
    System.out.println( dubiousDate + " -> " + d);
} catch ( ParseException e) {
    e.printStackTrace();
    System.err.println( dubiousDate + " failed");
}

這會給

2014-04-01 - > Wed Dec 04 00:00:00 CET 2013

現在我可以理解寬松的日歷試圖很好並接受有趣的負數,但這種解釋看起來像-01被認為是月份,即使它出現在最后,日期也是如此。 -04個月變為04天,減去忽略。

在所有寬大處理中,為什么這對任何人都有意義?

我看到另一種可能的解釋:

在模式yyyyMMdd中,月份部分限於精確的兩個字符,因為不同的數字字段之間沒有分隔符。 因此,“-0”將被視為月份,僅為零,比1月份的一個月產生去年12月。

在“解析”假月之后,日期部分在第二個減去字符之前停止“4”。 結果是12月4日。

最后,剩下的字符“-01”被忽略了。 這是SimpleDateFormat類關於如何處理非數字尾隨字符的典型情況,例如,請參閱以下代碼:

String dubiousDate = "2014-04-01xyz";
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d;
try {
    d = sdf.parse(dubiousDate);
    System.out.println(dubiousDate + " -> " + d);
    // output: Tue Apr 01 00:00:00 CEST 2014
} catch (ParseException e) {
    e.printStackTrace();
    System.err.println(dubiousDate + " failed");
}

作為拇指規則,只有兩個相等的符號字符MM或dd,解析器最多只消耗兩個字符(如果找到數字)。

關於Java 8的一些研究:

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseLenient();
builder.append(DateTimeFormatter.ofPattern("yyyyMMdd"));
DateTimeFormatter dtf = builder.toFormatter();
String dubiousDate = "2014-04-01";
LocalDate date = LocalDate.parse(dubiousDate, dtf);
System.out.println(date);

根據JDK-8文檔,以這種方式構造的格式化程序應該表現得很寬松,但不幸的是仍然會拋出異常:

“線程中的異常”主“java.time.format.DateTimeParseException:無法在索引3處解析文本'2014-04-01'”

最好的選擇是在寬松的情況下 - 理論上 - 如果解析器只是忽略減去字符。 但顯然這對JSR-310來說是不可能的(仍然太嚴格)。 嗯, SimpleDateFormat很寬松,但方式錯誤。

這沒有意義。 這對我來說聽起來像個錯誤。

我認為正確的答案是等待最終完成日期的Java 8。 例如,您的代碼現在可以更改為類似下面的內容。 並且,Java會拋出異常,就像它應該的那樣。

import java.util.*;
import java.lang.*;
import java.io.*;

import java.text.DateFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Main {
  public static void main(String[] args) {
    String dubiousDate = "2014-04-01";
    LocalDate d;
    try {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        d = LocalDate.parse(dubiousDate, formatter);
        System.out.println(dubiousDate + " -> " + d);
      }
      catch (Exception e) {
        e.printStackTrace();
        System.err.println(dubiousDate + " failed");
      }
    }
  }
}

暫無
暫無

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

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