为什么不在配置文件中存储DateTime.ParseExact的正则表达式和相应的格式字符串呢?
当然,你需要花费一些精力来确定正确的值,但之后只需更新配置文件就可以了。
无论如何,除非您告诉它格式或它恰好符合标准格式,否则您仍将面临解析日期时间的问题。
编辑:希望您不介意我有点篡改问题,但我对Regex vs. TryParseExact vs.异常处理的讨论很感兴趣,所以我做了一个小测试。下面的代码将相同的文件名解析100,000次,以识别并转换嵌入的日期。
我确保在发布模式下运行代码,并且没有附加调试器;在使用Visual Studio进行调试时,异常处理会使程序变慢。
我发现Regex vs. TryParseExact方法非常接近。毫不奇怪,随着路径级数的增加,Regex方法变得更加高效,但仍然没有太大差别。如果路径根本不包含日期,则平衡略微向Regex方法倾斜,但不足以产生显着差异。
然而,使用依赖异常处理的“错误”方式却大不相同!
下面是我展示的代码的时间:
Using Regex:
Duration: 543.0543
Using TryParse:
Duration: 429.0429
Using Exceptions:
Duration: 11930.4865
这些时间是以毫秒为单位的。我最初运行了100万次迭代,但在执行异常运行时感到无聊。
实验表明,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;
}
}
}