问题描述
编辑:因为我有很多关于以单一格式而不是数组使用 TryParseExact 的评论:
- 我必须测试数组中的所有格式 - 输入可能是这些格式,而我对这些其他格式的单元测试实际上有效。我必须全部使用它们。
- 我知道 DateTime.TryParse 将匹配第一个并且不会进一步迭代。因此我使用的是 TryParseExact as Microsoft shows。它应该完全匹配。但它在这种情况下不起作用。
TLDR:给定格式为 "dd/MM/yyyy"
且值为 "29/11/2019"
DateTime.TryParseExact 的字符串,返回格式为 "dd/MM/yyyy hh:mm tt"
且值为 {{1} 的匹配项}.为什么?
问题:在使用 TryParseExact 时,如何确保格式为 29/11/2019 12:00 AM
的字符串返回为与格式 "dd/MM/yyyy"
而不是 "dd/MM/yyyy"
的匹配项?
Context的长解释;
我有以下问题。我需要将多种日期格式从字符串解析为日期时间值。它们(输入字符串)可以以下列格式出现:
"dd/MM/yyyy hh:mm tt"
为了解决这个问题,我编写了一个字符串扩展来解析给定的输入字符串并返回一个 bool 成功和一个潜在的匹配格式。
{ "dd/MM/yyyy hh:mm tt","dd/M/yyyy hh:mm tt","dd/MM/yyyy H:mm","dd/MM/yyyy H:m","dd/MM/yyyy","dd-MM-yyyy","d-M-yyyy","dddd,d MMMM yyyy"};
这将返回字符串输入 private static readonly string[] _DateFormats = new string[] { "dd/MM/yyyy hh:mm tt",d MMMM yyyy"};
public static bool StringToDateTime(this string dateTimeString,out DateTime dateTimeValue,out string matchingFormat)
{
matchingFormat = ""; // defaults
dateTimeValue = new DateTime();
if (string.IsNullOrEmpty(dateTimeString)) return false;
foreach (string format in DateFormats)
{
matchingFormat = format;
if (DateTime.TryParseExact(dateTimeString,DateFormats,AUSCulture,DateTimeStyle,out dateTimeValue)) return true;
}
return false;
}
作为 DateTime "29/11/2019 successfully"
,匹配格式为 29/11/2019 12:00 AM
,而不是匹配原始输入 "dd/MM/yyyy hh:mm tt"
的格式。
鉴于这个问题,我能想到的唯一(管道胶带)解决方案是:
29/11/2019
哪个有效,但显然,这还有其他问题(产生输入格式等)。所以我宁愿不使用它。
解决方法
System.DateTime 不能在没有时间组件的情况下存在,因此不可能将日期解析为 DateTime 而不是时间组件。它将默认为一天的开始,例如12:00 AM,这与调用 dateTime.Date()
的结果相同。这将允许您在不考虑时间的情况下比较两个日期。
如果拥有或存储时间元素确实让您感到困扰,那么您可以创建自己的 struct
来存储日期,或者考虑使用诸如 NodaTime 之类的提供仅日期结构的东西。
此外,Dotnet 6 将引入 DateOnly 和 TimeOnly 结构来做到这一点。您可以在 MS devblogs 上阅读更多相关信息。
,您正在传递整个格式数组,因此它将匹配任何格式。
由于您在 foreach
之上的 DateFormats
,因此您只需匹配当前值。
所以替换这一行
if (DateTime.TryParseExact(dateTimeString,DateFormats,AUSCulture,DateTimeStyle,out dateTimeValue))
return true;
有了这个
if (DateTime.TryParseExact(dateTimeString,format,out dateTimeValue))
return true;