【问题标题】:Which is Quicker: DateTime.TryParse or Regex哪个更快:DateTime.TryParse 或 Regex
【发布时间】:2011-06-22 11:41:11
【问题描述】:

在 .NET 中,要确定提供的字符串是否为日期,哪个更快:使用 DateTime 将其转换为日期,还是使用正则表达式检查字符串作为日期的有效性?

我只需要确保提供的值是一个日期,之后我不会对它做任何事情。

谢谢。

【问题讨论】:

  • 你为什么不测试呢?如果您或多或少知道它们的频率,则获取一堆其中大约 % 无效的日期字符串,将它们扔给两种方法并选择最快的。
  • 编写一个基准测试(或多个测试)。说真的,这是唯一确定的方法
  • 哪个更快:编写一个 5 行基准,或者在 SO 上发布并等待其他人这样做。
  • 这是13.5K Rep的人提出的一个很奇怪的问题
  • 当您说您需要“确保提供的值是日期”时,您是指有效的日期还是格式化为日期的值?它必须是一个非常聪明和复杂的正则表达式,可以确定一个值是否实际上是一个有效的日期。

标签: c# .net regex datetime


【解决方案1】:

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

编辑

找到了一篇不错的类似帖子。值得一读

Regex vs Tryparse what is the best in performance

【讨论】:

    【解决方案2】:

    一个好的正则表达式应该更快,并且可能消耗更少的瞬态内存。

    但这是硬币的另一面:

    您几乎只使用一种时间格式,这意味着国际化会很痛苦,并且需要教育您的用户以正确的格式输入日期。

    此外,您将丢失一些日期验证,例如,您如何在非闰年剔除 2 月 29 日? 4 月 31 日?

    【讨论】:

      【解决方案3】:

      最好的办法是为两者编写一些测试代码,然后运行一个循环来执行一百万次。在不知道输入的情况下,很难回答这个问题(尽管我猜测 TryParse 会更快)。

      也就是说,当今处理器上的时差可能无关紧要。

      【讨论】:

        【解决方案4】:

        更新:当run in a fiddle 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)\d\d[- /.](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;
            }
        

        【讨论】:

        • 这个例子确实每次都重新创建一个新的正则表达式,这是非常不合适的。请检查固定的小提琴:dotnetfiddle.net/Apdhhe 缓存的正则表达式每次都获胜(jitted 和 unjitted)
        • 谢谢!我已修复的最终 string.format 参数列表中有一个错误。 dotnetfiddle.net/cHcOR8
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2011-07-19
          • 2010-11-10
          • 2012-10-03
          • 2011-02-15
          • 2012-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-05
          相关资源
          最近更新 更多