通缉:DateTime.TryNew(年,月,日)或DateTime.IsValidDate(年,月,日)
标题基本上都说明了一切。 我从遗留数据库(我无法更改)获得三个用户提供的整数( year
, month
, day
) 1 。 目前,我使用以下代码将这些整数解析为DateTime
结构:
try { return new DateTime(year, month, day); } catch (ArgumentException ex) { return DateTime.MinValue; }
有时,这些值不代表有效日期(是的,用户输入类似1999-06-31的内容,不,遗留应用程序没有validation这一点)。 由于在数据validation失败时抛出exception被认为是不好的做法 ,我宁愿用无exception代码替换它。 但是,我能找到的唯一解决方案是将整数转换为一个字符串和TryParseExact
这个字符串,这对我来说似乎更加丑陋。 我错过了一些明显更好的解决方案吗
1实际上,它是YYYYMMDD格式的一个整数,但将其转换为年,月和日是微不足道的……
没有静态函数IsValidDate()
所以你必须自己编写它,首先天真的实现可能是:
public static bool IsValidDate(int year, int month, int day) { if (year < DateTime.MinValue.Year || year > DateTime.MaxValue.Year) return false; if (month < 1 || month > 12) return false; return day > 0 && day <= DateTime.DaysInMonth(year, month); }
我说这是一个天真的实现,因为(除了参数范围)唯一的检查是否存在日期是闰年。 在实践中,如果您正在处理非公历日历(以及在格里高利历中用于与Julian日历对齐日期的日历中缺少日期),则可能因日历问题而失败。
使用日历
非Gregorian日历可能会破坏这些假设:
- 1月1日是最小的有效日期。 这不是真的。 不同的日历具有不同的最小日期。 此限制只是
DateTime
技术限制,但可能有一个日历(或日历中的Era)具有不同的最小(和最大)日期。 - 一年中的月数小于或等于12.这不是真的,在某些日历中,上限为13,并且每年的情况并不总是相同。
- 如果日期有效(根据所有其他规则),则它是有效日期。 事实并非如此,日历可能有多个时代而且并非所有日期都有效(甚至可能在时代日期范围内)。
管理这个的规则非常复杂,很容易忘记一些事情,所以在这种情况下,捕获exception可能不是一个坏主意。 以前validation函数的更好版本可能只提供基本validation并依赖DateTime
来检查其他规则:
public static DateTime? TryNew(int year, int month, int day, Calendar calendar) { if (calendar == null) calendar = new GregorianCalendar(); if (year < calendar.MinSupportedDateTime.Year) return null; if (year > calendar.MaxSupportedDateTime.Year) return null; // Note that even with this check we can't assert this is a valid // month because one year may be "shared" for two eras moreover here // we're assuming current era. if (month < 1 || month > calendar.GetMonthsInYear(year)) return null; if (day <= 0 || day > DateTime.DaysInMonth(year, month)) return null; // Now, probably, date is valid but there may still be issues // about era and missing days because of calendar changes. // For all this checks we rely on DateTime implementation. try { return new DateTime(year, month, day, calendar); } catch (ArgumentOutOfRangeException) { return null; } }
然后,给定这个新函数,您的原始代码应该是:
return TryNew(year, month, day) ?? DateTime.MinValue;
您可以使用DateTime.DaysInMonth
来检查日期是否有效。 显然月份必须在范围内(1; 12)