我如何在Perl中检查有效的日期格式?

时间:2009-05-13 10:59:18

标签: perl date format


我在我的一个变量中从数据库中获取了一个日期字段,目前我正在使用以下代码检查日期是否为“yyyy-mm-dd”格式

if ( $dat =~ /\d{3,}-\d\d-\d\d/ )

我的问题是,有没有更好的方法来实现这一目标。

非常感谢

8 个答案:

答案 0 :(得分:5)

美国格式的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(/ | - |?)。(?:( :( ?: 1 [6-9] | [2-9] \ d)?29 \ 3( ?: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})$

Regular Expression Library包含一个更简单的版本,与其他建议一致,转换为您的问题:

^\d{4}-\d{1,2}-\d{1,2}$

答案 1 :(得分:4)

正如其他人所指出的,如果这是来自数据库的日期字段,它应该以明确定义的格式出现,因此您可以使用简单的正则表达式,例如工具包提供的正则表达式。

但是它的缺点是它会接受无效日期,例如2009-02-30。同样,如果您正在处理成功将其作为数据库中的日期类型字段的日期,那么您应该是安全的。

更强大的方法是使用CPAN中的许多日期/时间模块之一。可能Date :: Manip将是一个不错的选择,特别是检查ParseDate()函数。

http://metacpan.org/pod/Date::Manip

答案 2 :(得分:3)

怎么样

/\d{2}\d{2}?-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/

答案 3 :(得分:2)

\ d可以匹配其他语言的数字字符。 YYY真的是有效的一年吗?如果必须是四位数字,短划线,两位数字,短划线,两位数字,我更喜欢/^[0-9]{4}-[0-9]{2}-[0-9]{2}$//^[12][0-9]{3}-[0-9]{2}-[0-9]{2}$/。请注意您匹配的字符串周围的空格字符。

当然,这不会检查那里的字符的合理性,除了第二个例子中的第一个字符。如果需要,您可以将其传递给日期解析模块,然后检查其输出以获得逻辑结果。

答案 4 :(得分:1)

嗯,你可以从:

开始
/\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|30|31)/ 

答案 5 :(得分:1)

最佳且轻量级的解决方案是使用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!";
}

我希望这有用: - )

答案 6 :(得分:0)

我非常强烈建议您自己编写自己的正则表达式来执行此操作。日期/时间解析很简单,但有一些棘手的方面,这是一个已经解决了数百次的问题。您无需设计,编写和调试另一种解决方案。

如果你想要一个正则表达式,最好的解决方案可能是使用我的Regexp :: Common :: time插件用于Regexp :: Common模块。您可以指定简单或复杂,严格或模糊的日期/时间匹配,并且它具有非常广泛的测试套件。

如果您只想解析特定的日期格式,最好使用Dave Rolsky出色的DateTime模块中的众多解析/格式化插件之一。

如果你想在匹配它们之后验证日期/时间值,我会建议我的Time :: Normalize模块。

希望这有帮助。

答案 7 :(得分:0)

我认为使用没有外部检查的正则表达式非常复杂!我用一个小子来获取它:

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 那里得到了这个想法(以及大部分代码)。还有其他例子。