快速入门
教程
工具和语言
示例
参考
书评
示例
正则表达式示例
数字范围
浮点数
电子邮件地址
IP 地址
有效日期
数字日期转文本
信用卡号
匹配完整行
删除重复行
编程
两个相邻词语
陷阱
灾难性回溯
重复次数过多
拒绝服务
使所有内容可选
重复捕获组
混合 Unicode 和 8 位
本网站上的更多内容
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用程序和语言
正则表达式示例
正则表达式参考
替换字符串参考
书评
可打印 PDF
关于本网站
RSS 源和博客
RegexMagic—Generate regular expressions matching dates and times

匹配有效日期的正则表达式

^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$ 匹配 1900-01-01 至 2099-12-31 之间的 yyyy-mm-dd 格式的日期,可选择四种分隔符。锚点 确保整个变量是一个日期,而不是包含日期的文本片段。年份由 (19|20)\d\d 匹配。我使用了 交替 来允许前两个数字为 19 或 20。必须使用括号。如果我省略了它们,则正则表达式引擎将查找 19 或正则表达式的其余部分,该部分匹配 2000-01-01 至 2099-12-31 之间的日期。括号是阻止竖线将整个正则表达式拆分为两个选项的唯一方法。

月份由 0[1-9]|1[012] 匹配,再次用括号括起来以将两个选项放在一起。通过使用 字符类,第一个选项匹配 01 到 09 之间的数字,第二个选项匹配 10、11 或 12。

正则表达式的最后部分包含三个选项。第一个匹配 01 到 09 的数字,第二个匹配 10 到 29 的数字,第三个匹配 30 或 31。

巧妙地使用交替选项允许我们排除无效日期,例如 2000-00-00,如果不使用交替选项,则无法排除此类日期。要做到真正完美,您必须将月份拆分为各种选项,以考虑月份的长度。上述正则表达式仍然匹配 2003-02-31,这不是一个有效日期。使前导零可选可能是另一个增强功能。

如果您想要求分隔符一致,可以使用 反向引用^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$ 将匹配 1999-01-01,但不会匹配 1999/01-01

同样,您希望使正则表达式变得多么复杂取决于您在其中使用它的数据,以及如果出现不需要的匹配,问题有多大。如果您在脚本中验证用户输入的日期,则可能更容易在正则表达式之外执行某些检查。例如,当年份不是闰年时排除 2 月 29 日在脚本语言中要容易得多。使用简单的算术比使用正则表达式更容易检查年份是否可以被 4 整除(并且不能被 100 整除,除非可以被 400 整除)。

以下是您可以在 Perl 中检查有效日期的方法。我还添加了括号以将年份捕获到反向引用中。

sub isvaliddate {
  my $input = shift;
  if ($input =~ m!^((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$!) {
    # At this point, $1 holds the year, $2 the month and $3 the day of the date entered
    if ($3 == 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11)) {
      return 0; # 31st of a month with 30 days
    } elsif ($3 >= 30 and $2 == 2) {
      return 0; # February 30th or 31st
    } elsif ($2 == 2 and $3 == 29 and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0))) {
      return 0; # February 29th outside a leap year
    } else {
      return 1; # Valid date
    }
  } else {
    return 0; # Not a date
  }
}

若要匹配 mm/dd/yyyy 格式的日期,请将正则表达式重新排列为 ^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$。对于 dd-mm-yyyy 格式,请使用 ^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$。您可以在 RegexBuddy 库 中找到这些正则表达式的其他变体。