How can I check for a valid date format in Perl?


I am getting a date field from a database in one of my variables, at the moment I am using the following code to check if the date is in the format "yyyy-mm-dd"

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

      

My question is, is there a better way to achieve this.

Many thanks

+1


a source to share


7 replies


As others have noted, if this is a date field from a database, it must appear in a well-defined format, so you can use a simple regexp, such as given by the toolkit.

But this has the disadvantage that it will accept invalid dates like 2009-02-30. Again, if you are handling dates that have successfully turned them into a date field in the DB, you should be safe.



A more reliable approach would be to use one of the many Date / Time modules from CPAN. Date :: Manip would probably be a good choice and in particular will check the ParseDate () function.

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

+4


a source


OWASP Validation Regex Repository US version of dates with leap year support:

^ (:( :( ?: 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}) $



The regex library contains a simpler version as per other suggestions, which translates to your problem:

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

      

+5


a source


What about

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

      

+3


a source


\ d can match character numbers in other languages. And is YYY really a year? If it should be four digits, dash, two digits, dash, two digits, I would prefer /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/

or /^[12][0-9]{3}-[0-9]{2}-[0-9]{2}$/

. Be aware of the run characters around the string you match.

Of course, this does not check the validity of the characters that are, except for the first character in the second example. If needed, you just need to pass it to the date parsing module and then check its output for boolean results.

+2


a source


Ok, you can start with:

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

      

+1


a source


The best and lightweight solution is using the Date :: Calc check_date subroutine, here's an example:

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!";
}

      

I hope this was helpful :-)

+1


a source


I would highly recommend AGAINST to write your own regex to do this. Date and time parsing is simple, but there are some tricky aspects and this is a problem that has been solved hundreds of times. You don't need to design, write and debug yet another solution.

If you want a regex, the best solution is probably using my Regexp :: Common :: time plugin for the Regexp :: Common module. You can specify simple or complex, hard or fuzzy date and time matching, and it has a very extensive set of tests.

If you just want to parse specific date formats, you might be better off using one of the many parsing / formatting plugins for Dave Rolsky's excellent DateTime module.

If you want to check the date / time values ​​after they match, I would suggest my Time :: Normalize module.

Hope it helps.

0


a source







All Articles