模拟SQL Server CAST/CONVERT的行为,在C#中将字符串解析为DateTime



我正在使用一个数据库,该数据库包含以各种不同格式存储为字符串的日期-时间值。这些值是从不同的外部来源获得的,它们的格式超出了我的控制范围。可以枚举当前存储在数据库中的所有格式,但一些尚未发现的格式可能会在未来某个时候出现。

过去,这些值通过SQL Server的CONVERT函数解析为SQL DATETIME,然后返回到.NET应用程序。现在应用程序正在接收字符串,并且必须在那里进行解析。

我最初使用DateTime.Parse((,但失败了,因为它无法处理SQL Server默认处理的某些格式(如"yyyyMMdd"(。下一种方法是使用DateTime.TryParseExact重载,该重载接受各种格式的字符串数组。类似于:

var dateTimeString = "20210101";
var dateTimeFormatInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
var expectedDateTimeFormats = dateTimeFormatInfo.GetAllDateTimePatterns().ToList();
expectedDateTimeFormats.Add("yyyyMMdd");
DateTime.TryParseExact(dateTimeString, expectedDateTimeFormats.ToArray(), CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var myDateTime);

这是有效的,除了它也不处理某些格式,比如";yyyy-mm-dd hh:mi:ss.mmm";,SQL Server默认处理的。具有讽刺意味的是,DateTime.Parse((.也能很好地处理这个特定的例子

有没有一种好的方法可以模仿C#中SQL Server的CONVERT(DATETIME,val(的行为,尝试并成功解析至少与在数据库中进行转换的原始解决方案中处理的格式一样多的格式?

我认为一个包含这里列出的所有格式的ParseExact解决方案可能会奏效,但我想知道是否有更好的方法。或者也许是一个更好的方法。

更新:@jeroen mostert关于使用SqlDateTime.Parse的评论可能比我们最终的结果更好。

原始答案:

如果它在未来对任何人都有帮助,那么最终的答案是使用DateTime.TryParse((,如果失败,则使用TryParse((不支持的特殊格式调用DateTime.TyParseExact((。

从源代码来看,Parse/TryParse似乎对分隔符之类的东西更宽容,因此它甚至可以使用枚举dateTimeFormatInfo.GetAllDateTimePatterns((时未显示的类似格式,即使TryParseExact使用DateTimeFormatInfo对象提供的所有DateTime模式。

我还针对微软文档中列出的日期和时间样式验证了格式支持。不过,此解决方案并不支持100%的功能。这是经过设计的,因为有些组合可能是不确定的,谢天谢地,我们被限制在特定的文化中。

正如评论中所指出的,这不是一个完美的解决方案,但它在这里起到了作用。

如果您可以控制数据库的架构,您可以使用FORMAT()函数在表上创建一个View或Computed Column,以C#的DateTime可以轻松处理的标准化和单一一致的格式格式化日期。

请注意,在某些情况下,与其他本机SQL Server函数相比,FORMAT()函数可能性能较差。

最新更新