Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

ultimate date check regexp

by Anonymous Monk
on Oct 30, 2006 at 08:52 UTC ( #581230=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

if we have date f.e. '2006.10.30' we can easily check it with
/\d+\.\d+\.\d+/
or
/^(([1-9]|1[1,2]]).([1-9]|1[0-9]|2[0-9]|3[0,1]))$/
etc.. but those are minimal checks, some months have 28..31, and every 4 years 02.28 becomes 02.29

so my question is "is there any ultimate date check regexp, how would it look like" (i didn't manage to find one)

thanks for your time.

Replies are listed 'Best First'.
Re: ultimate date check regexp
by mickeyn (Priest) on Oct 30, 2006 at 09:04 UTC
Re: ultimate date check regexp
by davorg (Chancellor) on Oct 30, 2006 at 09:27 UTC

    A regex that checks values like that is going to be far too complex to maintain. You're better off using a function that checks for valid dates. The timelocal function from Time::Local, converts a list of values (like those returned from localtime) into a epoch seconds value and it dies if passed an invalid date. You can use eval to catch and report on those errors.

    #!/usr/bin/perl use strict; use warnings; use Time::Local; while (<DATA>) { chomp; my ($y, $m, $d) = split /-/; eval { timelocal 0, 0, 0, $d, $m-1, $y-1900 }; if ($@) { print "$_ is not a valid date\n"; } else { print "$_ is a valid date\n"; } } __DATA__ 2006-10-30 2006-10-32 2006-02-29 2004-02-29

    It's simple enough to wrap that up into a is_valid_date function.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: ultimate date check regexp
by fenLisesi (Priest) on Oct 30, 2006 at 10:41 UTC
Re: ultimate date check regexp
by borisz (Canon) on Oct 30, 2006 at 09:29 UTC
    Yes there is, just use the output of the script. true for all valid dates from 1900 .. 2100. I use it in all my scripts!
    use Regexp::Assemble; use Date::Calc; my $re = Regexp::Assemble->new; for my $y ( 1900 .. 2100 ) { for my $m ( 1 .. 12 ) { for my $d ( 1 .. 31 ) { if ( Date::Calc::check_date( $y, $m, $d ) ) { $re->add( sprintf( "^%4d.%02d\.%02d\$", $y, $m, $d ) ); } } } } print $re;
    Boris

      It seems a little counterproductive to call Date::Calc::check_date almost 75,000 times in order to create that regular expression. Unless you're planning to process more than 75,000 records then it would be more efficient to just call Date::Calc::check_date once for each date you want to check.

      --
      <http://dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

        Hey, thats more a joke, but Im the only one that does it with a regexp. And I call the script only once and put the resulting regexp into the script. If I need to do it with a regexp.
        Boris
Re: ultimate date check regexp
by Anonymous Monk on Oct 30, 2006 at 09:47 UTC
    Date::Calc::check_date is C,
    boolean DateCalc_check_date(Z_int year, Z_int month, Z_int day) { if ((year >= 1) and (month >= 1) and (month <= 12) and (day >= 1) and (day <= DateCalc_Days_in_Month_[DateCalc_leap_year(year)][mont +h])) return(true); return(false); }
    and it basicly uses:
    boolean DateCalc_leap_year(Z_int year) { Z_int yy; return( ((year AND 0x03) == 0) and ( (((yy = (Z_int) (year / 100)) * 100) != year) or ((yy AND 0x03) == 0) ) ); } const Z_int DateCalc_Days_in_Year_[2][14] = { { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; const Z_int DateCalc_Days_in_Month_[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
    how to use (rewrite) it in perl

      If you install the Date::Calc module correctly, then the C portions will be compiled, installed and linked to the Perl code in Date/Calc.pm. You'll then be able to call it from your Perl code by following the examples in the documentation. The fact that it's written in C won't effect you at all.

      Maybe it's worth pointing out that my solution works with a standard Perl installation.

      --
      <http://dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

Re: ultimate date check regexp
by Anonymous Monk on Oct 30, 2006 at 09:27 UTC
    but it also checks minimum data:
     return undef
    	unless($month <= 11 && $day >= 1 && $day <= 31
    		&& $hh <= 23 && $mm <= 59 && $ss <= 59);
    

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://581230]
Approved by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2018-06-21 18:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?



    Results (118 votes). Check out past polls.

    Notices?