为什么不在配置中存储 DateTime.ParseExact 的正则表达式和相应的格式字符串?
当然,您必须付出一些努力才能计算出正确的值,但只需更新配置即可。
除非你告诉它格式或者它恰好符合标准格式,否则你在解析日期时间时仍然会遇到问题。
编辑:我希望你不介意我劫持这个问题,但我对 Regex 与 TryParseExact 与异常处理的讨论感到好奇,所以我做了一个小测试。下面的代码解析相同的文件名 100,000 次以识别和转换嵌入的日期。
我确保在发布模式下运行代码并且没有附加调试器;使用 Visual Studio 进行调试时的异常处理是一个杀手锏。
我发现 Regex 与 TryParseExact 方法非常接近。不出所料,随着路径中级别数量的增加,Regex 方法变得更加高效,但仍然没有任何效果。如果路径根本不包含日期,则平衡会进一步向 Regex 方法移动,但不足以产生显着差异。
不过,使用依赖异常处理的“不正确”方式是完全不同的!
我对下面显示的代码的时间安排是:
Using Regex:
Duration: 543.0543
Using TryParse:
Duration: 429.0429
Using Exceptions:
Duration: 11930.4865
这些时间以毫秒为单位。我最初运行了 100 万次迭代,但是在运行 Exceptions 时我感到很无聊;-)
实验表明,Regex 和 TryParseExact 方法在性能方面相当可比,但 TryParseExact 方法的显着优势在于它不需要正则表达式定义或派生。毫无疑问,这是解决这个问题的好选择。
它还说明了处理异常的开销。这并不奇怪,真的,因为展开堆栈的过程可能是时间复杂且耗时的。应用程序花费了 95% 的时间来处理异常。它很好地说明了这个论点,您不应该依赖处理异常来解析日期 - 因此存在 TryParse... 方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
static Regex r = new Regex(@"\d{4}_[a-zA-Z]{3}_\d{1,2}");
static string dateFormat = "yyyy_MMM_d";
static CultureInfo provider = CultureInfo.InvariantCulture;
static void Main(string[] args)
{
string filepath = @"C:\TopDir\SubDir\2011_JUL_26\filename.ext";
DateTime startTime;
DateTime endTime;
TimeSpan duration;
bool success;
DateTime result;
System.Console.WriteLine("Using Regex:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingRegex(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
System.Console.WriteLine("Using TryParse:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingTryParse(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
System.Console.WriteLine("Using Exceptions:");
startTime = DateTime.Now;
for (int ix = 0; ix < 100000; ix++)
{
success = UsingExceptions(filepath, out result);
}
endTime = DateTime.Now;
duration = endTime - startTime;
System.Console.WriteLine("Duration: " + duration.TotalMilliseconds.ToString());
}
static bool UsingRegex(string filepath, out DateTime result)
{
var matches = r.Matches(filepath);
if (matches.Count > 0)
{
return DateTime.TryParseExact(matches[0].Value, dateFormat,
provider, DateTimeStyles.None, out result);
}
result = DateTime.MinValue;
return false;
}
static bool UsingTryParse(string filepath, out DateTime result)
{
var parts = filepath.Split('\\');
foreach (var part in parts)
{
if( DateTime.TryParseExact(part, dateFormat, provider,
DateTimeStyles.None, out result) )
{
return true;
}
}
result = DateTime.MinValue;
return false;
}
static bool UsingExceptions(string filepath, out DateTime result)
{
var parts = filepath.Split('\\');
foreach (var part in parts)
{
try
{
result = DateTime.ParseExact(part, dateFormat,
provider, DateTimeStyles.None);
return true;
}
catch(Exception ex)
{
}
}
result = DateTime.MinValue;
return false;
}
}
}