我从数据库中的一个变量中获取日期字段,目前我正在使用以下代码检查日期是否为“yyyy-mm-dd”格式
if ( $dat =~ /\d{3,}-\d\d-\d\d/ )
我的问题是,有没有更好的方法来实现这一点。
非常感谢
OWASP Validation Regex Repository的美国格式日期版本,支持闰年:
^(?:(?:(?:0?[13578]|1[02])(/|-|.)31)\1|(?:(?:0?[1,3-9]|1 [0-2])(/|-|.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2 })$|^(?:0?2(/|-|.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0 [48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^( ?:(?:0?[1-9])|(?:1[0-2]))(/|-|.)(?:0?[1-9]|1\d|2[0 -8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
正则表达式库包含一个更简单的版本,类似于其他建议,它被转换为您的问题:
^\d{4}-\d{1,2}-\d{1,2}$
正如其他人所指出的,如果这是来自数据库的日期字段,则它应该采用明确定义的格式,因此您可以使用简单的正则表达式,例如 toolkit 提供的正则表达式。
但这样做的缺点是它会接受无效的日期,例如 2009-02-30。同样,如果您正在处理成功地将其转换为数据库中日期类型字段的日期,那么您应该是安全的。
一种更强大的方法是使用 CPAN 中的众多日期/时间模块之一。Date::Manip 可能是一个不错的选择,特别是检查 ParseDate() 函数。
怎么样
/\d{2}\d{2}?-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
\d 可以匹配来自其他语言的数字字符。YYY 真的是有效的年份吗?如果它必须是四位数,破折号,两位数,破折号,两位数,我更喜欢/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/
or /^[12][0-9]{3}-[0-9]{2}-[0-9]{2}$/
。请注意要匹配的字符串周围的空格字符。
当然,这并没有检查那里的字符的合理性,除了第二个例子中的第一个字符。如果需要,您最好将其传递给日期解析模块,然后检查其输出以获取逻辑结果。
最好的轻量级解决方案是使用Date::Calc的check_date子例程,这是一个示例:
use strict;
use warnings
use Date::Calc qw[check_date];
## string in YYYY-MM-DD format, you can have any format
## you like, just parse it
my @dt_dob = unpack("A4xA2xA2",$str_dob_date);
unless(check_date(@dt_dob)) {
warn "Oops! invalid date!";
}
我希望这会有所帮助:-)
那么你可以开始:
/\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|30|31)/
我强烈建议您不要编写自己的正则表达式来执行此操作。日期/时间解析很简单,但有一些棘手的方面,这是一个已经解决了数百次的问题。您无需设计、编写和调试另一个解决方案。
如果你想要一个正则表达式,最好的解决方案可能是使用我的 Regexp::Common::time 插件用于 Regexp::Common 模块。您可以指定简单或复杂、严格或模糊的日期/时间匹配,它有一个非常广泛的测试套件。
如果您只想解析特定的日期格式,最好使用 Dave Rolsky 出色的 DateTime 模块的众多解析/格式化插件之一。
如果您想在匹配后验证日期/时间值,我建议您使用 Time::Normalize 模块。
希望这可以帮助。
我认为使用没有外部检查的正则表达式非常复杂!我用一个小子来得到它:
sub check_date {
my $date_string = shift;
# Check the string fromat and get year, month and day out of it.
# Best to use a regex.
return 0 unless $date_string =~ m/^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
# 31. in a month with 30 days
return 0 if ($3 >= 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11));
# February 30. or 31.
return 0 if ($3 >= 30 and $2 == 2);
# February 29. in not a leap year.
return 0 if ($2 == 2 and $3 == 29
and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0)));
# Date is valid
return 1;
}
我从regular-expressions.info得到了这个想法(以及大部分代码)。还有其他例子。