ovedpo15 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I though it will be an easy question but it looks like a more complex one.
My script gets a date in the following format: MM.DD.YY
Unfortunately I can't change the format of the date.
I'm trying to verify its a valid date. What is the best way to do so?
I prefer not to use eval as it considered bad practice.
Thank you all :)

Replies are listed 'Best First'.
Re: Verifying a date
by choroba (Cardinal) on Oct 02, 2019 at 15:38 UTC
    String eval is considered a bad practice. Block eval is safe, and if you don't like it, use any of the try/catch modules available for a more mainstream look.

    #!/usr/bin/perl use warnings; use strict; use Time::Piece; sub validate_date { my ($date) = @_; return eval { $date eq Time::Piece->strptime($date, '%m.%d.%y')->s +trftime('%m.%d.%y') } } use Test::More tests => 5; ok validate_date('02.28.19'); ok ! validate_date('02.32.19'); ok ! validate_date('02.29.19'); ok validate_date('02.29.16'); ok ! validate_date('02.30.16');

    The eq is needed because 02.29.19 is parsed without an error by Time::Piece, returning 03.01.19 when formatted back to a string.

    Update: It passes Corion's test cases correctly.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Verifying a date
by Corion (Patriarch) on Oct 02, 2019 at 15:38 UTC

    What do you consider a "valid date"?

    Maybe try writing down what the program should do and what rules it should enforce. Then take those rules and write them in Perl code.

    For a start, the following program provides a framework for you:

    #!perl use strict; use warnings; use Test::More tests => 'no_plan'; sub verify_date { my( $date ) = @_; }; my @testcases = ( [ '01-01-70', 1 ], # ok [ '01-12-70', 1 ], # ok [ '12-01-70', 1 ], # ok [ '12-01-12', 1 ], # ok [ '12-12-01', 1 ], # ok [ '70-01-01', 0 ], # not ok [ '02-30-70', 0 ], # not ok [ '02-02-1970', 0 ], # not ok [ 'ab-02-1970', 0 ], # not ok ); for my $testcase ( @testcases ) { my( $value, $expected ) = @$testcase; is verify_date( $value ), $expected, $value; }; done_testing;
Re: Verifying a date
by daxim (Curate) on Oct 02, 2019 at 16:24 UTC
    Mind the behaviour of the %y token.
    $strp = DateTime::Format::Strptime->new(pattern => '%m.%d.%y'); $dt = $strp->parse_datetime('02.29.16'); # defined $dt = $strp->parse_datetime('02.29.19'); # undefined
Re: Verifying a date
by hippo (Archbishop) on Oct 02, 2019 at 15:30 UTC
    I prefer not to use eval as it considered bad practice.

    By whom?