是否有一种优雅的方式允许 C# 中的日期输入以适应用户输入,例如“2009-09-31”(例如 9 月 31 日,它不存在并导致 DateTime.Parse 阻塞)?理想情况下,我想将其解析为 10 月 1 日(例如,最新的可能日期加上溢出)。
6 回答
我不相信这是直接为您处理的。您可以做的是自己将日期解析为三个单独的整数:
- 解析 2009,并构造 2009 年 1 月 1 日的 DateTime
- 解析 09 并减一,然后调用
dt = dt.AddMonths(8)
获取 9 月 1 日 - 解析 31 并减一,然后调用
dt.AddDays(30)
这将处理诸如 2009/13/01 之类的事情,表示 2010 年 1 月 1 日。不过,我怀疑它不会在 2 月 31 日做你想做的事情......
在用户输入中避免错误日期的一种方法是不要让它们在第一个实例中发生,即使用日期选择器控件。
怎么用 DateTime.TryParse
?
使用指定的特定于区域性的格式信息和格式样式将日期和时间的指定字符串表示形式转换为其等效的 DateTime,并返回一个指示转换是否成功的值。
此MSDN 页面显示了使用示例。
我认为该DateTime.DaysInMonth
方法可以提供很大帮助,经过TryParse
...您可以实现您正在谈论的逻辑
您(在道德上)不应该尝试处理这样的输入。是 1900 年 2 月 29 日被解释为 1900 年 3 月 1 日(因为 1900 年 2 月 29 日可以解释为 1900 年 2 月 28 日之后的第二天,但由于它不存在,因此将 1900 年 2 月 28 日之后的实际日期移动)或作为二月1900 年 2 月 28 日(因为 1900 年 2 月 29 日可以解释为 1900 年 2 月的最后一天)?另一种情况是,如果用户打算输入“2009-3-3”,但由于手指又快又粘,不小心输入了“2009-3-33”。然后,与其错误被捕获,自定义解析器会将其吞噬到 2009 年 4 月 2 日。由于这种情况,您应该只DateTime.TryParse
输入并在出现无效输入时通知用户。这就是你应该做的。
现在,如果您需要处理此类输入。我会使用以下内容:
static DateTime Parse(int year, int month, int day) {
DateTime date;
if (month < 1 || month > 12) {
int direction = month < 1 ? 1 : -1;
do {
month += direction * 12;
year -= direction;
} while (month < 1 || month > 12);
}
int daysInMonth = DateTime.DaysInMonth(year, month);
if (day < 1 || day > daysInMonth) {
date = new DateTime(year, month, daysInMonth);
int difference = day - daysInMonth;
date = date.AddDays(difference);
}
else {
date = new DateTime(year, month, day);
}
return date;
}
编译器只会抛出无法解析的异常,因此您必须为此类问题编写自己的解析器。
规则#1:尽可能合理,首先不要让用户输入无效数据。
如果您正在使用 Windows 窗体,请尽可能使用 DateTimePicker(尽管它在语言环境方面有其局限性);或者,如果您的应用程序在 ASP.NET 中,请使用日历或 AJAX 控件工具包控件之一(我现在忘记了确切的名称),但它会弹出一个带有日历的小窗口。
如果以后有可能需要本地化此应用程序,我强烈建议不要将日期组件分离到不同的字段中(或将它们解析)。