2017-06-13 10 views
2

This questionは、日付を表す文字列の検証について話しています。その中には、通常のフローロジックの例外を使用しないことをお勧めします。 TryParse()はそれに最適です。しかし、TryParse()は文字列を受け取り、私の場合はすでに年月日を整数として取得しています。私は月/日/年の組み合わせを検証したいと思います。たとえば2月30日です。例外のないintベースのDateTimeを検証しますか?

新しいDateTime(int、int、int)の周りにtry/catchを置くのはかなり簡単ですが、例外に頼ることなくそれを行う方法があるのだろうかと思います。

私はまた、これらのintを文字列に構成してから、TryParse()を使用することを愚かに感じます。

+1

FYI - 「解析」には常に文字列が含まれます。 –

答えて

3

以下は先発グレゴリオ暦を使用して、DateTimeによってサポートされている範囲内で有効な年/月/日の組み合わせをチェックします:

public bool IsValidDate(int year, int month, int day) 
{ 
    return year >= 1 && year <= 9999 
      && month >= 1 && month <= 12 
      && day >= 1 && day <= DateTime.DaysInMonth(year, month); 
} 

あなたが他のカレンダーシステムで動作する必要がある場合は、としてそれを拡大します次のようになります。

public bool IsValidDate(int year, int month, int day, Calendar cal) 
{ 
    return year >= cal.GetYear(cal.MinSupportedDateTime) 
      && year <= cal.GetYear(cal.MaxSupportedDateTime) 
      && month >= 1 && month <= cal.GetMonthsInYear(year) 
      && day >= 1 && day <= cal.GetDaysInMonth(year, month); 
} 
+1

これは素晴らしいことです。私は新しい言葉を学びました! –

0

使用文字列補間

int year = 2017; 
int month = 2; 
int day = 28; 
DateTime dt; 
DateTime.TryParse($"{month}/{day}/{year}", out dt); 
+1

右ですが、intを文字列に変換してから、DateTimeにintに変換するように頼んでいます。 –

+0

このアプローチは培養に敏感です。 1月7日を考えて、2011年1月7日を連結するかもしれませんが、7月1日に解析される可能性があります。 –

+1

@orionelenzil:あなたのために良い!それはまさに正しい本能です:) –

0

は、私の知る限りでは、正しく事前string書式設定にint Sを連結する以外にDateTimeさんintの妥当性をチェックするための簡単な方法はありません。アプリケーションのニーズ保留

DateTime dateTime; 
if (DateTimeUtilities.TryParse(2017, 2, 30, out dateTime)) 
{ 
    // success 
} 
else 
{ 
    // fail, dateTime = DateTime.MinValue 
} 

、例えば:

try/catch -ingを回避するために、私はDateTime.TryParseを利用して、静的なユーティリティクラスを記述します。

using System; 

public static class DateTimeUtilities 
{ 
    public static bool TryParse(int year, int month, int day, out DateTime result) 
    { 
     return DateTime.TryParse(
      string.Format("{0}/{1}/{2}", year, month, day), out result); 
    } 
} 

使い方文化(感謝@マットジョンソン)、私はまたDateTime.TryParseExactを見てみましょう。

+0

あなたの文字列を '年/月/日'として構築しても、このアプローチはまだ文化に敏感です。現在の文化はグレゴリオ暦を使用していない可能性があります。例えば、 'ar-SA'はデフォルトで' UmAlQuraCalendar'を使います。 –

+0

正しいですが、私はOPが 'new DateTime(int、int、int)'をインスタンス化するのを見たので、このソリューションは彼のニーズに十分に適していると思いました。私が答えを投稿した後、私は文化について考えました。そのため、最新の編集にTryParseExactというメモを(あまり詳しくは書いていませんが)含めました。 –

+0

申し訳ありませんが、私は例の引数名を残しました。 [(int、int、int)と一致する唯一のシグネチャDateTimeは(int year、int month、int date)]です(https://msdn.microsoft.com/en-us/library/system.datetime.datetime() v = .110).aspx)。 –

-1

このように見てください。あなたが書いどれコード:

  • が月をチェックする必要がありますが、1〜12
  • あなたはハードコードに
  • をする必要があります配列を持っているだろうことを意味する、月によって日範囲をチェックする必要があります範囲後ろの痛みの原因になる可能性があります。

ホイールを再製作して間違っている可能性があります。なぜなら、それを単純なままにして、ちょうどDateTime try-catchでコンストラクタを作成し、それを移動し続けますか?レドモンドのオタクたちがこの共通の仕事のために一生懸命働くようにしましょう。最善の解決策は、あなたの次の開発者がすぐに理解して頼ることができるソリューションです。

TryParseとDateTimeコンストラクタは完全に同じバリデータを使用していますが、後者は例外をスローしますが、前者は例外ではありません。 TryParseは、余分な文字列の操作が必要なため、余計です。

+1

'DateTime.DaysInMonth'は、あなたが記述する2番目の2つの項目を行います。 (実際にはそれも最初ですが、範囲外であれば例外がスローされます) –

+0

@MattJohnsonそれで、それを防ぐためのコードがない限り、可能性のある例外を処理しています* –

+0

右。 'DateTime.IsValid(年、月、日、...)'静的関数はそのままではありません。私は答えを示したのと同様に、それを実装する必要があります。 –

関連する問題