【问题标题】:Using Regex convert dd/mm/yy into dd/mm/yyyy使用正则表达式将 dd/mm/yy 转换为 dd/mm/yyyy
【发布时间】:2015-09-03 01:12:55
【问题描述】:

我正在使用正则表达式,我想将dd/mm/yy 转换为完整的dd/mm/yyyy

例如。用户输入他的出生日期:01/11/94
程序将年份94 转换为1994

现在如果用户输入出生日期:01/11/09
该程序将年份09 转换为01/11/2009,因为它不能是1909。除非你是吸血鬼。

现在如果用户输入出生日期:01/11/15
该程序让用户继续输入,因为它是当前年份。 2015。此处需要结合当前日期有效性检查功能。

我已经走了这么远,但我需要帮助才能使其完全正常运行。 如果您愿意提供帮助,我可以向您展示一些我创建的代码。

【问题讨论】:

  • 为什么不让他们输入出生日期为 dd/mm/yyyy?
  • 有什么理由要使用正则表达式而不是先解析然后格式化?
  • 您应该使用DateTime.TryParseDateTime.TryParseExact 而不是正则表达式。您可以使用 TwoDigitYearMax 属性管理 2 位日期
  • “因为不可能是 1909 年。除非你是吸血鬼。” => 我一直都知道吸血鬼do exist :-)
  • 您必须确定一个人的最大年龄可以编写这样的代码。您可以让 100 岁的人使用它,使“15”实际上是 1915 年,但您的代码会假设它是 2015 年。所以应该在假设或要求中的某处说明这一点。否则……使用代码来做这件事比使用正则表达式要容易得多。

标签: c# regex masking date


【解决方案1】:

可能是这样的:

string pattern = "\D\d{2}$"

shortYear.Replace(pattern, FullYear);

string FullYear(string value)
{
    string seperator = value.Substring(0,1);
    value = value.Substring(1,2);

    if(int32.Parse(value) < int32.Parse(DateTime.Now.Year.ToString().Substring(value.Length -2, 2))
        return seperator + DateTime.Now.Year.ToString().Substring(0, value.Length -2) + value;
    return seperator + (DateTime.Now.Year - 100).ToString().Substring(0, value.Length -2) + value;
}

【讨论】:

    【解决方案2】:

    有一些工具可以提供比正则表达式处理更多的价值。

    要使用的工具是DateTime 及其ParseExact,并带有适当的日期格式规范来进行转换。

    这里有四个例子,结果在评论中:

    DateTime.ParseExact("01/02/15", "MM/dd/yy", CultureInfo.InvariantCulture)
            .ToString("MM/dd/yyyy"); // 01/02/2015
    
    DateTime.ParseExact("01/02/93", "MM/dd/yy", CultureInfo.InvariantCulture)
            .ToString("MM/dd/yyyy"); // 01/02/1993
    
    DateTime.ParseExact("01/02/00", "MM/dd/yy", CultureInfo.InvariantCulture)
            .ToString("MM/dd/yyyy"); // 01/02/2000
    
     DateTime.ParseExact("01/02/09", "MM/dd/yy", CultureInfo.InvariantCulture)
             .ToString("MM/dd/yyyy") // 01/02/2009
    

    【讨论】:

    • 这比使用 RegEx 更容易理解,也更易于维护。 RegEx 有它的位置,但有些事情不应该被使用,比如解析 HTML。
    【解决方案3】:

    我真的很喜欢正则表达式并且几乎在任何地方都使用它们,但在这种情况下,我不推荐这种方式(除非你想出于学术目的这样做)。

    我会使用DateTime.TryParseDateTime.TryParseExact

    你可以写的第一件事是:

    Console.WriteLine("Enter the date:");
    string dateString = Console.ReadLine();
    DateTime date;
    
    if(!DateTime.TryParseExact(dateString, "dd/MM/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
    {
        throw new InvalidOperationException("Not a valid date");
    }
    Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
    // dateString = "17/04/88" => 17/04/1988
    // dateString = "17/04/1988" => "Not a valid date"
    

    .NET Fiddle


    很好,但请稍等,如果有人以dd/MM/yyyy 格式输入日期,则会失败。 TryParseExect 方法采用 string[] 重载,您可以在其中指定多种格式

    Console.WriteLine("Enter the date (you can write it in the dd/MM/yyyy format):");
    string dateString = Console.ReadLine();
    DateTime date;
    
    if (!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
    {
        throw new InvalidOperationException("Not a valid date");
    }
    Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
    // dateString = "17/04/1988" => "17/04/1988"
    // dateString = "17/04/29" => 17/04/2029
    // dateString = "17/04/30" => 17/04/1930
    

    .NET Fiddle


    很好,但是等等,如果有人出生在17/04/29,它会显示17/04/2029,那是未来! 如果有人在 2029 年以上阅读这篇文章,请注意它是在 2015 年写的。

    那是因为Calendar.TwoDigitYearMax Property

    此属性允许将 2 位数的年份正确转换为 4 位数年份。例如,如果此属性设置为 2029,则 100 年的范围是从 1930 年到 2029 年。因此,两位数的值 30 被解释为 1930,而 29 的两位数被解释为 2029.

    此时属性默认为2029,我不确定到了这个日期会做什么,可能是Year 2029 problem


    你可以再次改进它,但没有魔法,你必须做出选择,因为你已经知道,除非你做出假设,否则 2 位数的年份是不可能解决的。

    所以你需要回答以下问题:

    1) 我想解析的日期范围是多少 => 从 CurrentYear - 99CurrentYear

    如果是,我们可以这样写:

    // Execution date: 18/06/2015
    Console.WriteLine("Enter the date (if you want to enter a date from more than 99 years ago, you can enter the date in the dd/MM/yyyy format):");
    string dateString = Console.ReadLine();
    DateTime date;
    CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
    ci.Calendar.TwoDigitYearMax = DateTime.Now.Year;
    
    if(!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, ci, DateTimeStyles.None, out date))
    {
        throw new InvalidOperationException("Not a valid date");
    }
    Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
    // dateString = "17/04/15" => 17/04/2015
    // dateString = "17/04/16" => 17/04/1916
    

    .NET Fiddle


    2) 我们在谈论生日,对吧?
    我们真的需要管理不到一岁的人吗?

    或者,如果您的出生日期用于您可以说某人不可能小于 16 岁的系统,您可以更改此范围以处理从 CurrentYear - 99 - 16CurrentYear - 16 的日期。
    这样您就可以管理 16 到 115 岁的人。

    // Execution date: 18/06/2015
    Console.WriteLine("Enter your birth date (if you are less than 16 year old you have to wait, if you are very old you can try to enter your birthdate in the dd/MM/yyyy format):");
    string dateString = Console.ReadLine();
    DateTime date;
    CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
    ci.Calendar.TwoDigitYearMax = DateTime.Now.Year - 16;
    
    if (!DateTime.TryParseExact(dateString, new string[] { "dd/MM/yyyy", "dd/MM/yy" }, ci, DateTimeStyles.None, out date))
    {
        throw new InvalidOperationException("Not a valid date");
    }
    Console.WriteLine(date.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
    // dateString = "17/04/99" => 17/04/1999
    // dateString = "17/04/16" => 17/04/1900
    

    .NET Fiddle

    就这篇文章而言,您可以继续自定义它,例如:

    • 能够配置最小年龄
    • 添加检查以验证日期不是将来的日期(如果输入31/12/&lt;TwoDigitYearMax&gt;,使用上述代码仍然有效)

    【讨论】:

    • +1 这个答案非常彻底,并且涵盖了不同的变化以满足大多数可能的需求。教我有关 .NET Fiddle 的加分点!我以前用过 SQL Fiddle,但甚至没有意识到 .NET Fiddle 的存在......
    猜你喜欢
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2012-03-05
    • 2019-01-26
    • 1970-01-01
    相关资源
    最近更新 更多