#!/usr/bin/perl
use strict;
use Benchmark qw(cmpthese);
my @possible_timestamps = (
    '1880-08-82 62:58:49',
    '2006-11-24 04:39:24',
    '2390-72-50 55:07:29',
    '6850-80-31 83:12:39',
    '2007-04-11 05:56:41',
    '2007-06-05 21:59:18',
    '2006-09-16 02:49:57',
    '2006-12-30 09:17:40',
    '7697-29-34 14:48:83',
    '2007-04-05 04:50:42',
    '2007-06-06 13:57:41',
    '2006-08-28 11:53:03',
    '2007-04-08 14:42:39',
    '2007-01-19 03:06:55',
    '6416-98-68 02:99:12',
    '2007-02-25 00:01:10',
    '2006-10-29 05:39:55',
    '9874-89-96 08:44:19',
    '2006-09-30 17:29:26',
    '2006-08-21 14:18:06',
    '6746-43-51 10:34:90',
    '2007-04-19 07:03:52',
    '2007-03-08 08:21:41',
    '5309-92-71 22:70:83',
    '0433-18-10 33:82:44',
    '2006-08-04 14:00:14',
    '2007-01-27 02:54:19',
    '7860-74-70 49:27:65',
    '2006-09-15 00:56:59',
    '2007-06-15 12:08:27',
);

cmpthese(
    50000,
    {
        'regexp' => sub {
            for my $stamp (@possible_timestamps) { 
                my $q = validate_regexp($stamp);
            }
        },
        'function' => sub {
            for my $stamp (@possible_timestamps) { 
                my $q = validate_function($stamp);
            }
        },
    }
);

exit;

sub validate_regexp {
    my $date = shift;
    return $date =~ m{
        \A
        (?:
            \d\d\d\d - (?:0[13578]|1[02]) - (?:[012]\d|3[01])
            |
            \d\d\d\d - (?:0[469]|11) - (?:[012]\d|30)
            |
            \d\d (?: 0[48] | [2468][048] | [13579][26] ) - 02 - [012]\d
            |
            (?: 0[48] | [2468][048] | [13579][26] ) 00 - 02 - [012]\d
            |
            \d\d\d\d - 02 - (?:[01]\d|2[0-8])
        )
        \s
        (?: [01]\d | 2[0-3] ) : [0-5]\d : [0-5]\d
        \z
    }xo;
}

sub validate_function {
    my $date = shift;
    return undef unless $date =~ m{\A(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\z}o;
    my ($year, $month, $day, $hour, $min, $sec) = ($1, $2, $3, $4, $5, $6);

    return undef if $min > 59;
    return undef if $sec > 59;
    return undef if $hour > 23;

    return undef if ( $month == 0 ) || ( $month > 12 );
    return undef if $day == 0;

    my $max_day = 31;
    if (
        ($month == 4) ||
        ($month == 6) ||
        ($month == 9) ||
        ($month == 11)
    ) {
        $max_day = 30;
    }
    if ($month == 2) {
        $max_day = 28;
        if ( 0 == $year % 4 )  {
            if ( 0 == $year % 100 ) {
                if ( 0 == $year % 400 ) {
                    $max_day = 29;
                }
            }
            else {
                $max_day = 29;
            }
        }
    }
    return undef if $day > $max_day;
    return 1;
}
