Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
Do you know where your variables are?
 
PerlMonks  

Script to validate date fails

by madhum21 (Initiate)
on Feb 16, 2012 at 14:39 UTC ( #954253=perlquestion: print w/ replies, xml ) Need Help??
madhum21 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, Am Madhu and am new to Perl programming. I was trying to write a simple script to validate valid date. Though it works for some input data, it again fails for some data as below.

#!/usr/bin/perl print ("Enter the date in dd-mm-yy format : ") ; $date = <STDIN> ; chomp ($date) ; while ($date ne "") { if ($date =~ /[1-31]-[1-12]-[1-99]/) { print("You have entered valid data \n") ; } else { print ("You have entered invalid data \n") ; } $date = <STDIN> ; chomp($date) ; }

The above script works fine for input data like 2-2-2 but fails for 3-3-3. Please let me understand, if I am doing something wrong here. Thanks Madhu

Comment on Script to validate date fails
Download Code
Re: Script to validate date fails
by moritz (Cardinal) on Feb 16, 2012 at 14:59 UTC

    You need to understand that [...] in a regex is a character class, which matches just a single character. If you write [1-31], it can match the digits 1, 2 or 3, but only one of them. See perlretut for details.

    The best thing to do is to first validate the syntax, with something like /\d\d?-\d\d?\d\d?/, and then check the ranges in perl code later.

Re: Script to validate date fails
by runrig (Abbot) on Feb 16, 2012 at 15:09 UTC
    Besides the error in your regex (already pointed out), validating dates would be better done by a date library, like DateTime, Time::Piece, or Time::Local.
Re: Script to validate date fails
by Your Mother (Canon) on Feb 16, 2012 at 15:46 UTC

    Adding to what runrig said, Date::Calc has the fastest date validation.

    use strict; use warnings; use Date::Calc "check_date"; print "Enter the date in yyyy-mm-dd format : "; # More "native" format +. while ( my $date = <STDIN> ) { last if $date =~ /^$/; my @date = $date =~ /(\d+)/g; # Allows any separator and mushy inp +ut. if ( eval { check_date( @date ) } ) { print "You have entered valid data\n"; } else { print "You have entered invalid data\n"; } print "Enter the date in yyyy-mm-dd format : "; } __END__ Enter the date in yyyy-mm-dd format : ohai You have entered invalid data Enter the date in yyyy-mm-dd format : 2012-2-29 You have entered valid data Enter the date in yyyy-mm-dd format : 2011-2-29 You have entered invalid data Enter the date in yyyy-mm-dd format :
      if ( eval { check_date( @date ) } )

      Why eval?

      if ( check_date( @date ) )

      works just as well.

      Update: Oops, no it doesn't! My version dies nastily if fed random alphanumerics or whatever.

Re: Script to validate date fails
by brx (Pilgrim) on Feb 16, 2012 at 15:49 UTC
    $date =~ /[1-31]-[1-12]-[1-99]/; doesn't do what you want.

    [...] is used for class of characters : you must list characters one-by-one "abcd" or a range like "a-k" or "0-6" (see http://perldoc.perl.org/perlrecharclass.html => 1) Bracketed Character Classes -- 2) Character Ranges )

    Here is a "DIY" validation :

    $date =~ /(0?[1-9]|[12][0-9]|3[01])-(0?[1-9]|1[012])-(\d?\d)$/

    (0?[1-9]|[12][0-9]|3[01]) means...

    accepts :
    1 to 9 with an optional 0 prefix => 01,02,03...09 and 1,2,3...9
    *OR*
    (1 or 2) before (0 to 9) => 10,11,...,29
    *OR*
    30 or 31
    

    ...but it's not the good way to do it (what about 29-02-01 for example?) It's better to use a module which knows the calendar.

    Last thing : year with 2 digits ? not good ! :)

    My first try :

    #!/usr/bin/perl use DateTime; print ("Enter the date in dd-mm-yyyy format : ") ; $date = <STDIN> ; chomp ($date) ; while ($date ne "") { my ($d,$m,$y) = split '-',$date; warn "/!\\ wrong year format? $y\n" if $y!~/^\d{4}$/ ; if ( eval {DateTime->new(year=> $y,month=> $m, day=> $d)} +) { print("You have entered valid data \n") ; } else { print ("You have entered invalid data \n") ; } $date = <STDIN> ; chomp($date) ; }
Re: Script to validate date fails
by toolic (Chancellor) on Feb 16, 2012 at 16:34 UTC
    Basic debugging checklist, Tip #9: Demystify regular expressions by installing and using the CPAN module YAPE::Regex::Explain
    The regular expression: (?-imsx:[1-31]-[1-12]-[1-99]) matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- [1-31] any character of: '1' to '3', '1' ---------------------------------------------------------------------- - '-' ---------------------------------------------------------------------- [1-12] any character of: '1' to '1', '2' ---------------------------------------------------------------------- - '-' ---------------------------------------------------------------------- [1-99] any character of: '1' to '9', '9' ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------

    BTW, "validate valid date" has a nice ring to it :)

      Thanks all. Thanks for all the help

      BTW, "validate valid date" has a nice ring to it :)

      Good point. If we only need to validate valid dates, then the following should work:

      print("Enter the date in dd-mm-yy format: "); while(<STDIN>) { print("You have entered valid data\n"); }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://954253]
Approved by marto
Front-paged by MidLifeXis
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (8)
As of 2014-04-18 12:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (467 votes), past polls