在.NET中,要确定提供的字符串是否为日期,哪个更快:使用DateTime将其强制转换为日期,还是使用正则表达式检查字符串作为日期的有效性?
我只需要确保提供的价值是一个日期,之后我不会做任何事情。
谢谢。
我的第一个问题是哪一个更具表现力?或者哪一个最可读?在这种性能提升可能微不足道的情况下,我会投票给最容易维护/读取的代码。
编辑
找到了一个不错的、类似的帖子。值得一读
Regex vs Tryprse什么是性能最好的
一个好的正则表达式应该更快,并且可能消耗更少的瞬态内存。
但硬币的另一面是:
你几乎只能使用一种时间格式,这意味着国际化将是痛苦的,你的用户需要接受教育,以正确的格式输入日期。
此外,你会失去一些日期验证,比如说,你如何在非闰年剔除2月29日?4月31日?
最好的做法是为两者编写一点测试代码,然后运行一个循环进行一百万次测试。在不知道输入的情况下,很难回答这个问题(尽管我猜测TryParse会更快)。
也就是说,今天处理器上的时差可能无关紧要。
UPDATE:当在小提琴中运行时,TryParse会更快。
我用10000个项目进行了初步测试。看起来Regexp的速度至少是DateTime.Parse的两倍。请参阅下面的代码:
private string[] arrDates = new string[10000];
protected void Page_Load(object sender, EventArgs e)
{
initialise();
RunRegexDemo();
RunDateTimeParseDemo();
}
private void initialise()
{
Random ryear, rmonth, rdate;
ryear = new Random();
rmonth = new Random();
rdate = new Random();
int y, m, d;
DateTime dt;
for (int i = 0; i < arrDates.Length; i++)
{
y = 0;
m = 0;
d = 0;
while (y < 1850)
{
y = ryear.Next(2050);
}
while (m < 1 || m > 12)
{
m = rmonth.Next(12);
}
while (d < 1 || d > 28)
{
d = rdate.Next(28);
}
dt = new DateTime(y, m, d);
arrDates[i] = dt.ToString("yyyy-MM-dd");
//lbl1.Text += "<br />" + arrDates[i];
}
}
private void RunRegexDemo()
{
System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
lbl1.Text+= "<h4>Starting Regex demo</h4>";
string f;
st.Start();
foreach(string x in arrDates){
f= "<br/>" + x + " is a valid date? = " + System.Text.RegularExpressions.Regex.IsMatch(x, @"^(19|20)dd[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$");
}
st.Stop();
lbl1.Text+= "<p>Ended RegEx demo. Elapsed time: " + st.ElapsedMilliseconds;
}
protected void RunDateTimeParseDemo(){
System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
lbl1.Text += "<h4>Starting DateTime.Parse demo</h4>";
st.Start();
DateTime dt;
string f;
foreach (string x in arrDates)
{
f = "<br/>" + x + " is a valid date? = " + DateTime.TryParse(x, out dt);
}
st.Stop();
lbl1.Text += "<p>Ended TryParse demo. Elapsed time: " + st.ElapsedMilliseconds;
}
Regex在这种情况下似乎更快,因为Regex只会查找DateTime解析需要找到模式并从该模式中获取值以创建DateTime对象的模式
添加基准,比较ISO 8601格式中解析日期/时间的不同方法:
- 使用自定义格式的ParseExact
- 使用标准格式的ParseExact
- 带有日期/时间创建的预编译正则表达式
- 预编译的regex只是验证输入字符串的格式
底线:
- Regex在不创建日期/时间的情况下检查格式的速度要快得多,并且不分配
- Regex解析和构建日期/时间的速度较慢,分配的数量明显更多(并且需要更多的代码…)
- 标准格式似乎分配较少
// * Summary *
BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19044.2965/21H2/November2021Update)
12th Gen Intel Core i9-12900H, 1 CPU, 20 logical and 14 physical cores
.NET SDK=7.0.302
[Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
Job=.NET 7.0 Runtime=.NET 7.0
方法 | 平均值 | 已分配 | |||||
---|---|---|---|---|---|---|---|
ParseExactCustomFormat:right;">144 B | |||||||
ParseExactStandardFormat | 10 | 254.07 ns | |||||
10 | 423.21 ns | ||||||
RegexIsMatch | 10 | 62.19 ns | >td style="text align:right;/tr>|||||
ParseExactCustomFormat | 100 | 255.08 ns | |||||
ParseExactStandardFormat | 100 | 255.18 ns | |||||
Regex | 100 | 427.15 ns | |||||
RegexIsMatch | 100 | 88.23 ns | >td style="text-align:right;/tr>|||||
ParseExactCustomFormat | 1000 | 255.65 ns | |||||
ParseExactStandardFormat | 1000 | 255.34 ns | |||||
Regex | 1000 | 437.88 ns | |||||
RegexIsMatch | 1000 | 62.69 ns | >td style="text-align:right;tr>