哪个更快:DateTime.TryParse或Regex

vd2z7a6w  于 2023-05-30  发布在  其他
关注(0)|答案(6)|浏览(111)

在.NET中,确定提供的字符串是否是日期,哪一个更快:使用DateTime将其转换为日期,还是使用正则表达式检查字符串作为日期的有效性?
我只需要确保提供的值是一个日期,之后我不会对它做任何事情。
谢谢。

qnakjoqk

qnakjoqk1#

我的第一个问题是哪一个更有表现力?还是哪个最有可读性?在这种情况下,性能的提高可能是微不足道的,我会投票给最容易维护/阅读的代码。

编辑

找到一个体面的,类似的职位。值得一读
Regex vs Tryparse what is the best in performance

oxf4rvwz

oxf4rvwz2#

一个好的正则表达式应该快得多,并且可能消耗更少的瞬时内存。
但硬币的另一面是:
您非常依赖于一种时间格式,这意味着国际化将是痛苦的,并且您的用户需要接受教育,以正确的格式输入日期。
此外,您将丢失一些日期验证,例如,如何在非闰年中清除2月29日?4月31日

h7appiyu

h7appiyu3#

最好的办法是为这两个代码都写一点测试代码,然后运行一个循环来执行一百万次。在不知道输入的情况下,很难回答这个问题(尽管我猜TryParse会更快)。
也就是说,今天的处理器上的时差可能无关紧要。

czq61nw1

czq61nw14#

更新:当run in a fiddle TryParse是一个 * 很多 * 快。
我对10000个项目进行了初步测试。看起来Regexp的速度至少是DateTime.Parse的两倍。使用下面的代码自己看看:

  1. private string[] arrDates = new string[10000];
  2. protected void Page_Load(object sender, EventArgs e)
  3. {
  4. initialise();
  5. RunRegexDemo();
  6. RunDateTimeParseDemo();
  7. }
  8. private void initialise()
  9. {
  10. Random ryear, rmonth, rdate;
  11. ryear = new Random();
  12. rmonth = new Random();
  13. rdate = new Random();
  14. int y, m, d;
  15. DateTime dt;
  16. for (int i = 0; i < arrDates.Length; i++)
  17. {
  18. y = 0;
  19. m = 0;
  20. d = 0;
  21. while (y < 1850)
  22. {
  23. y = ryear.Next(2050);
  24. }
  25. while (m < 1 || m > 12)
  26. {
  27. m = rmonth.Next(12);
  28. }
  29. while (d < 1 || d > 28)
  30. {
  31. d = rdate.Next(28);
  32. }
  33. dt = new DateTime(y, m, d);
  34. arrDates[i] = dt.ToString("yyyy-MM-dd");
  35. //lbl1.Text += "<br />" + arrDates[i];
  36. }
  37. }
  38. private void RunRegexDemo()
  39. {
  40. System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
  41. lbl1.Text+= "<h4>Starting Regex demo</h4>";
  42. string f;
  43. st.Start();
  44. foreach(string x in arrDates){
  45. f= "<br/>" + x + " is a valid date? = " + System.Text.RegularExpressions.Regex.IsMatch(x, @"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$");
  46. }
  47. st.Stop();
  48. lbl1.Text+= "<p>Ended RegEx demo. Elapsed time: " + st.ElapsedMilliseconds;
  49. }
  50. protected void RunDateTimeParseDemo(){
  51. System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
  52. lbl1.Text += "<h4>Starting DateTime.Parse demo</h4>";
  53. st.Start();
  54. DateTime dt;
  55. string f;
  56. foreach (string x in arrDates)
  57. {
  58. f = "<br/>" + x + " is a valid date? = " + DateTime.TryParse(x, out dt);
  59. }
  60. st.Stop();
  61. lbl1.Text += "<p>Ended TryParse demo. Elapsed time: " + st.ElapsedMilliseconds;
  62. }
展开查看全部
jyztefdp

jyztefdp5#

在这种情况下,Regex似乎更快,因为Regex只会查找模式,而DateTime parse需要找到模式并从该模式中获取值以创建DateTime对象

scyqe7ek

scyqe7ek6#

添加基准测试,比较以ISO 8601格式解析日期/时间的不同方法:

  • 使用自定义格式解析精确
  • ParseExact使用标准格式
  • 带有日期/时间创建的预编译正则表达式
  • 预编译的正则表达式只验证输入字符串的格式

底线是:

  • Regex在不创建日期/时间的情况下检查格式要快得多,并且不分配
  • 正则表达式解析和构建日期/时间的速度更慢,分配的数据也更多(并且需要更多的代码……)
  • 标准格式似乎分配较少
  1. // * Summary *
  2. BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19044.2965/21H2/November2021Update)
  3. 12th Gen Intel Core i9-12900H, 1 CPU, 20 logical and 14 physical cores
  4. .NET SDK=7.0.302
  5. [Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
  6. .NET 7.0 : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
  7. Job=.NET 7.0 Runtime=.NET 7.0

| 方法|循环|平均值|错误|标准差|比率|比率SD| Gen0|已分配|
| - -----|- -----|- -----|- -----|- -----|- -----|- -----|- -----|- -----|
| ParseExactCustomFormat|十个|277.65纳秒|3.148纳秒|2.791纳秒|一点|零点|0.0114| B|
| 解析精确标准格式|十个|254.07纳秒|0.490 ns| 0.435 ns|零点九二|零点零一|零点零零五|B|
| Regex|十个|423.21纳秒|4.026纳秒|3.766纳秒|一点五二|零点零二|0.0858|小行星1080 B|
| RegexIsMatch|十个|62.19纳秒|0.322纳秒|0.302纳秒|零点二二|零点|- ----|- ----|
| | | | | | | | | |
| ParseExactCustomFormat|一百|255.08纳秒|1.176纳秒|1.042纳秒|一点|零点|0.0114| B|
| 解析精确标准格式|一百|255.18纳秒|1.358纳秒|1.271纳秒|一点|零点零一|零点零零五|B|
| Regex|一百|427.15纳秒|8.149纳秒|7.224纳秒|一点六七|零点零三|0.0858|小行星1080 B|
| RegexIsMatch|一百|88.23纳秒|1.920 ns| 5.508纳秒|零点三二|零点零五|- ----|- ----|
| | | | | | | | | |
| ParseExactCustomFormat|一千|255.65纳秒|1.409纳秒|1.249纳秒|一点|零点|0.0114| B|
| 解析精确标准格式|一千|255.34纳秒|0.689纳秒|0.611 ns|一点|零点|零点零零五|B|
| Regex|一千|437.88纳秒|4.192纳秒|3.273纳秒|一点七一|零点零二|0.0858|小行星1080 B|
| RegexIsMatch|一千|62.69纳秒|0.744纳秒|0.696纳秒|零点二五|零点|- ----|- ----|

  1. /// <summary>
  2. /// Compares different methods of parsing a date/time in the ISO 8601 format.
  3. /// </summary>
  4. [SimpleJob(RuntimeMoniker.Net70)]
  5. [MemoryDiagnoser]
  6. public partial class DateTimeParseExactVsRegex
  7. {
  8. [Params(10, 100, 1_000)]
  9. public int Loops { get; set; }
  10. /// <summary>
  11. /// Parses the input string by using <see cref="DateTime.ParseExact"/>
  12. /// with a custom format.
  13. /// </summary>
  14. [Benchmark(Baseline = true)]
  15. public void ParseExactCustomFormat()
  16. {
  17. DateTime.ParseExact(_serializedDateTime, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK",
  18. CultureInfo.InvariantCulture,
  19. DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
  20. }
  21. private const string _serializedDateTime = "2002-08-11T10:11:12.0000000Z";
  22. /// <summary>
  23. /// Parses the input string by using <see cref="DateTime.ParseExact"/>
  24. /// with a standard format.
  25. /// </summary>
  26. [Benchmark]
  27. public void ParseExactStandardFormat()
  28. {
  29. DateTime.ParseExact(_serializedDateTime, "O",
  30. CultureInfo.InvariantCulture,
  31. DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
  32. }
  33. /// <summary>
  34. /// Parses the input string by using a <see cref="Regex"/>.
  35. /// </summary>
  36. [Benchmark]
  37. public void Regex()
  38. {
  39. Match match = GetRegex().Match(_serializedDateTime);
  40. if (!match.Success)
  41. {
  42. throw new NotImplementedException();
  43. }
  44. int GetInt(string groupName)
  45. {
  46. ReadOnlySpan<char> yearAsString = match.Groups[groupName].ValueSpan;
  47. return int.Parse(yearAsString);
  48. }
  49. int year = GetInt("year"), month = GetInt("month"), day = GetInt("day");
  50. int hour = GetInt("hour"), minute = GetInt("minute"), second = GetInt("second");
  51. int subSecond = GetInt("subsecond");
  52. DateTime _ = new DateTime(year, month, day, hour, minute, second).AddTicks(subSecond);
  53. }
  54. [GeneratedRegex(@"^(?<year>\d{4})\-(?<month>\d{2})\-(?<day>\d{2})T(?<hour>\d{2})\:(?<minute>\d{2})\:(?<second>\d{2})\.(?<subsecond>\d{7})Z$")]
  55. private static partial System.Text.RegularExpressions.Regex GetRegex();
  56. /// <summary>
  57. /// Detects whether the input string matches the date/time format by using a <see cref="Regex"/>.
  58. /// </summary>
  59. [Benchmark]
  60. public void RegexIsMatch() => GetRegex().IsMatch(_serializedDateTime);
  61. }
展开查看全部

相关问题