Problems? Is your data what you think it is? PerlMonks

### Re: Numeric Date Validation

by qq (Hermit)
 on Sep 30, 2003 at 23:22 UTC ( #295472=note: print w/replies, xml ) Need Help??

in reply to Numeric Date Validation

I agree that the requirements seem slightly misguided, but here is an attempt anyway. The approach is to make two subs, one that validates a year, month and date, and one that splits a number into all possible year,month and date combos and to pass to the first.

Its late, I'm tired, so this could definitely be improved, but its a start.

```#!/usr/bin/perl -w

use strict;

=pod

yyyymmdd
yyyyddmm
ddmmyyyy
mmddyyyy
yymmdd
yyddmm
ddmmyy
mmddyy

=cut

my %months = (
1=>31, 2=>28, 3=>31, 4=>30, 5=>31, 6=>30,
7=>31, 8=>31, 9=>31, 10=>31, 11=>30, 12=>31 );

for (<DATA> ) {
chomp;
print "\$_ ";
print validate( \$_ ) ? 'yep' : 'nope';
print "\n";
}

sub validate_ymd {
my (\$y,\$m,\$d) = @_;

# last minute addition / hack to make year 4 digit
if ( length( \$y ) == 2 ) {
if ( \$y > 3 ) {
\$y += 1900;
} else {
# close readers will see that these are equivalent...
return 1 if validate_ymd( 1900 + \$y, \$m, \$d );
return 1 if validate_ymd( 2000 + \$y, \$m, \$d );
return 0;
}
}

\$y = int(\$y); \$m=int(\$m); \$d=int(\$d);

return 0 if \$y > 2003;
return 0 if \$y < 1900;

my \$leap = 0;
if ( \$m == 2 and !\$y or !(\$y % 4) ) {
\$leap = 1;
}

return 0 unless exists \$months{\$m};
return 0 unless \$d and \$d <= \$months{\$m} + \$leap;
print " (y \$y m \$m d \$d) ";
return 1;
}

sub validate {
my \$date = shift;
return 0 if \$date =~ /\D/;

my \$length = length( \$date );
return 0 unless \$length == 6 or \$length == 8;

my @attempts;
if ( \$length == 6 ) {
\$date =~ /(..)(..)(..)/;
push @attempts, [\$1,\$2,\$3], [\$1,\$3,\$2], [\$3,\$1,\$2], [\$3,\$2,\$1];

} elsif ( \$length == 8 ) {
\$date =~ /(....)(..)(..)/;
push @attempts, [\$1,\$2,\$3], [\$1,\$3,\$2];
\$date =~ /(..)(..)(....)/;
push @attempts, [\$3,\$1,\$2], [\$3,\$2,\$1];
}
foreach ( @attempts ) {
return 1 if validate_ymd( @\$_ );
}
return 0;
}

__DATA__
20000229
19970229
29020300
291254
002902
19990223
101172

gives:

```20000229  (y 2000 m 2 d 29) yep
19970229 nope
29020300 nope
291254  (y 1954 m 12 d 29) yep
002902  (y 1900 m 2 d 29) yep
19990223  (y 1999 m 2 d 23) yep
101172  (y 1972 m 10 d 11) yep

Create A New User
Node Status?
node history
Node Type: note [id://295472]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2021-06-22 11:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
What does the "s" stand for in "perls"? (Whence perls)

Results (104 votes). Check out past polls.

Notices?