【问题标题】:How to validate if a path (string) contains a date in a variable time format in C# .NET?如何验证路径(字符串)是否包含 C# .NET 中可变时间格式的日期?
【发布时间】:2011-07-26 12:46:30
【问题描述】:

问题陈述:

  • 有一个路径包含特定格式的日期,这是一个配置参数。说,“yyyy_MMM_d”,
  • 我需要检测路径是否包含这样的日期:
    • 如果有,请将其更改为新日期。
    • 如果没有,则将新日期附加到路径中
  • 路径中的现有日期可以是任何日期,并不总是昨天或明天。

尝试的解决方案:

  • 通过正则表达式(在示例中为\d{4}_[a-zA-Z]{3}_\d{1,2})检测类似于日期的部分,然后使用TryParseExact() 对其进行验证
    • 这适用于常量格式,但我需要为正则表达式编译器编写格式以支持参数更改。这真的不值得努力。

那么,还有其他解决方案吗?我认为,如果没有比我拥有的更好的方法,我可能会要求在日期格式参数旁边添加一个正则表达式参数:-)

【问题讨论】:

    标签: .net string date


    【解决方案1】:

    在斜线分隔符处拆分字符串。在 while 循环中,检查它是否是有效的日期时间字符串。如果没有,请转到下一个部分。如果你通过每一件,你没有日期,所以追加一个。

    请注意,我不是 .net 开发人员,因此,这可能是一件可怕而令人讨厌的事情,永远不会出现......

    【讨论】:

    • 好主意。我很惭愧自己没有想到它:)
    • 呃!无意冒犯。处理异常的成本很高,不应将其用作以这种方式解析数据的“大锤”方法。
    • 谢谢,在我开始编写 python 代码之前,我从未真正见过它。
    • 异常不一定很昂贵,实际上在 .NET 中它们非常便宜。无论如何,我不会抛出异常,而是使用 TryParseExact()。我羞于考虑的绝妙想法是分割路径分隔符。
    • DateTime.TryParseExact(问题中已经提到)可以防止在使用这种方法时抛出异常。
    【解决方案2】:

    为什么不在配置中存储 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;
            }
        }
    }
    

    【讨论】:

    • 如果可能的话,我宁愿让应用程序自行解决,而不是添加额外的配置参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多