2017-06-13 31 views
2

This question談論驗證表示日期的字符串,並在其中提到,避免對常規流邏輯使用異常是很好的做法。 TryParse()對此非常好。但TryParse()接受一個字符串,在我的情況下,我已經把年份和月份看作整數。我想驗證月/日/年組合。例如2月30日。C# - 無例外驗證基於int的DateTime?

只要在新的DateTime(int,int,int)中放一個try/catch就很容易,但是我想知道是否有辦法在不依賴於異常的情況下做到這一點。

我也覺得這些int整合到一個字符串中,然後使用TryParse()。

+1

僅供參考 - 「解析」總是涉及字符串。 –

回答

3

下面將通過DateTime支持的範圍內檢查有效年/月/日的組合,使用proleptic陽曆:

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

沒錯,但我覺得愚蠢的將字符串轉換爲字符串,然後要求DateTime將它們轉換爲整數。 –

+0

這種方法對文化很敏感。你可能連接2017年1月7日,考慮1月7日,但它可能會被解析爲7月1日。 –

+1

@orionelenzil:對你有好處!這完全是正確的本能:) –

0

據我所知,有沒有簡單的方法來檢查DateTimeint的有效性除了串接int s轉換格式正確的string提前。

爲了避免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 dateTime; 
if (DateTimeUtilities.TryParse(2017, 2, 30, out dateTime)) 
{ 
    // success 
} 
else 
{ 
    // fail, dateTime = DateTime.MinValue 
} 

待您的應用程序,例如需求(感謝@Matt Johnson),我還會考慮DateTime.TryParseExact

+0

即使您將字符串構建爲「年/月/日」,這種方法仍然對文化敏感。目前的文化可能不會使用公曆。例如,'ar-SA'默認使用'UmAlQuraCalendar'。 –

+0

正確,我看到OP實例化一個'new DateTime(int,int,int)',所以我認爲這個解決方案對於他的需求來說足夠好。在我發佈了一個答案之後,我想到了文化,這就是爲什麼我在最近的編輯中包含了(儘管沒有太多細節)「TryParseExact」註釋的原因。 –

+0

對不起,我將參數名稱從示例中刪除。 [唯一的簽名DateTime匹配(int,int,int)是(int year,int month,int date)](https://msdn.microsoft.com/en-us/library/system.datetime.datetime( v = vs.110)的.aspx)。 –

-1

這樣看。你寫任何代碼:

  • 則要檢查範圍爲每月1-12
  • 將不得不每月檢查日的範圍,這意味着你必須硬編碼的數組
  • 則要佔閏年,這可能是一個痛苦的後方

而不是做所有這些,並重新發明輪子,並可能出錯 - 爲什麼不保持簡單,只是包裝DateTime構造函數在try-catch中並保持移動?讓雷德蒙德的書呆子們爲了這個共同的任務而努力工作。最好的解決方案就是任何跟隨你的開發人員都能快速理解和依賴。

我敢打賭,在引擎蓋下,TryParse和DateTime構造函數使用完全相同的驗證器,只是後者拋出異常而前者不是。爲此,TryParse與所有額外的字符串操作有關。

+1

'DateTime.DaysInMonth'執行您描述的後兩項。 (實際上,它也是第一次,但如果超出範圍則會拋出異常) –

+0

@MattJohnson因此,我們仍在處理可能的異常,除非有更多的代碼來阻止它* le嘆息* –

+0

沒錯。沒有'DateTime.IsValid(year,month,day,...)'靜態函數開箱即用。人們必須執行它,類似於我在答案中的表現。 –