2012-02-17 6 views
2

以下の入力例がありますが、私は自分でフォーマットを調べてパターンを毎回変更したくありません。現在、DateTimeFormat.forPattern("dd.MM.yyyy");を使用していますが、これはa), c)またはd)が適用されるとすぐに失敗します。パターン自体を認識するスマート・デートAPIはありますか?

a) 1.1.12  => 01.01.0012 x 
b) 01.01.2012 => 01.01.2012 ✓ 
c) 01.01.12 => 01.01.0012 x 
d) 1.1.2012 => 01.00.2012 x 

私はフォーマットがD.M.Yであることを保証することができ、それが長いか短いか混ざっていない場合。 Jodaに "基本パターン"で与えられたパターンを選択するのに役立つ関数がすでにありますか?

ありがとうございました!

答えて

3

パターンの検索パスを使用します。一部の日付はあいまいなので、どのように扱うかを知る必要があります。 1.2.3 AD/1903/2003年2月3日の初め、3月1日、AD 3日、またはAD/1901/2001年2月3日の2日です。

(私はのSimpleDateFormatオブジェクトをキャッシュ除く;)私が使用して単純なパターン

public static Date parseDate(String dateStr) throws IllegalArgumentException { 
    // optionally change the separator 
    dateStr = dateStr.replaceAll("\\D+", "/"); 

    for (String fmt : "dd/MM/yy,yyyy/MM/dd,dd/MM/yyyy".split(",")) { 
     try { 
      SimpleDateFormat sdf = new SimpleDateFormat(fmt); 
      sdf.setLenient(false); 
      return sdf.parse(dateStr); 
     } catch (ParseException ignored) { 
     } 
    } 
    throw new IllegalArgumentException("Unable to parse date '" + dateStr + "'"); 
} 

public static void main(String... args) { 
    String dates = "1.2.12\n" + 
      "01.02.2012\n" + 
      "2012.02.01\n" + 
      "01-01-12\n" + 
      "1.1.2012"; 
    for (String dateStr : dates.split("\n")) { 
     Object result; 
     try { 
      result = parseDate(dateStr); 
     } catch (IllegalArgumentException e) { 
      result = e; 
     } 
     System.out.println(dateStr + " => " + result); 
    } 
} 

プリント

1.2.12 => Wed Feb 01 00:00:00 GMT 2012 
01.02.2012 => Wed Feb 01 00:00:00 GMT 2012 
2012.02.01 => Wed Feb 01 00:00:00 GMT 2012 
01-01-12 => Sun Jan 01 00:00:00 GMT 2012 
1.1.2012 => Sun Jan 01 00:00:00 GMT 2012 
+1

私はより良い方法についてはわかりませんが、プログラムフローの一部として例外に頼ることはベストプラクティスに反していると警告したいだけです。それはパフォーマンスに害を及ぼします。 – Vic

+0

ありがとう、 '#setLenient'はとても役に立ちます。それは分かりませんでした:)私はあなたにスタイルの質問をしてもらえますか? 'Arrays.asList(" dd/MM/yy "、" yyyy/MM/dd "、" dd/MM/yyyy ")'や 'new Object [] {..}'や、 '#split()'メソッドを使用していますか?それほど高価ではないですか? – codevour

+1

私はより簡潔なので分割が好きです。その高価ですが、定数を使用するのは簡単なので、起動時に一度しか実行されません。 SimpleDateFormatの作成は、これらを作成する方がはるかに高価であるため、より重要です。 –

1

あなたがjava.util.Dataへの参照を使用したくない場合は、あなたはこのようにそれを行う必要があるでしょう:

public DateTime getDateTime(String text) { 
    DateTimeFormatterBuilder fb = new DateTimeFormatterBuilder(); 
    fb.appendDayOfMonth(2); 
    fb.appendLiteral('.'); 
    fb.appendMonthOfYear(2); 
    fb.appendLiteral('.'); 
    fb.appendYear(2, 4); 
    DateTimeFormatter formatter = fb.toFormatter(); 

    DateTime dt = formatter.parseDateTime(text); 
    if (dt.getYear() < 2000) { 
     dt = dt.plusYear(2000); 
    } 
    return dt; 
} 

をしかし、私は、このソリューションをお勧めします:

public DateTime getDateTime(String text) { 
    SimpleDateFormat f = new SimpleDateFormat("dd.MM.yy"); 
    java.util.Date jud = f.parse(text); 
    if (jud != null) { 
     return new DateTime(jud); 
    } else { 
     return null; 
    } 
} 

両方とも、あなたの例のためのトリックと仕事をする必要があります。

注:Alberto氏によると、まず正規表現を使用して入力を検証する必要があります。なぜなら、SimpleDateFormatはこの使用法と非常によく一致していないため、入力を検証することが常に望ましいからです。

+0

これは非常にクールでシンプルなソリューションです。 – codevour

+0

私は車輪を2度発明することを始めてはならないと思う;)(それは英語の正しい諺です...) – AlexS

2

私はJoda-Timeを使用してより良い解決策を得たと思います。あなたは、日付を表す文字列のリストで構成された入力を持っている場合、間違った視点から問題にアプローチが、異なるにしている私見

DateTimeFormatter f = new DateTimeFormatterBuilder() 
      .appendDayOfMonth(1) 
      .appendLiteral('.') 
      .appendMonthOfYear(1) 
      .appendLiteral('.') 
      .appendTwoDigitYear(1970) // Notice this!! 
      .toFormatter(); 

    System.out.println(f.parseDateTime("01.1.12")); 
    System.out.println(f.parseDateTime("01.01.12")); 

    f = new DateTimeFormatterBuilder() 
      .appendDayOfMonth(1) 
      .appendLiteral('.') 
      .appendMonthOfYear(1) 
      .appendLiteral('.') 
      .appendYear(4,4) 
      .toFormatter(); 

    System.out.println(f.parseDateTime("01.01.2012")); 
    System.out.println(f.parseDateTime("1.1.2012")); 
    System.out.println(f.parseDateTime("01.1.2012")); 
+0

try-catch-blocksを使用すると思いますが、それはあまりにも高価だと思います。私の意見では例外的に例外的なものだけを使うべきです。 – AlexS

+0

それはあまりにも高価な場合は、簡単な解決策があります。最初に正規表現で構造体を検証し、適切な 'DateTimeFormatter'で構文解析します。また、私のソリューションは、標準のJDK「SimpleDateFormat」ではなく、要求されたJodatimeを使用して、受け入れられたソリューションと同じくらい高価です。 – Johannes

+0

真。あなたのソリューションを批判するのは私の意図ではありませんでした。私はこの質問を読んで他の人に注釈を付けるべきだと思った。私はこの問題に対する解決策が個人の好みに依存していると思います。私の意見では、あなたの答えは受け入れられたものよりも正確な質問によく合います... – AlexS

1

:私はあなたが試してみて2つのパーサにそれを降りて書式設定の問題ではなく、テキストの検証に問題があります。

また、これは私の意見ですが、必要なときにすべての入力のテキストを変更するテキストパーサを作成すると、日付パーサーにとってより適切なテキスト形式このように正規表現のようなより強力なユーティリティを使うことができます。

+0

+1の入力は常に良いアイデアですから! – AlexS

関連する問題