right sub parse_datestring { # parses a datestring # - allows to provide a format of how to interprete day,month,year in the datestring. # default format is: DD/MM/YY # -> calling this method with format=>'d.m.y' computes faster than format=>'dd.mm.yy' ! # - any non-digit character in the datestring is considered a delimiter! # - 2-digit years will be considered 1930-2029 # - by default the date calculated from the datestring will be validated # -> validate=>'0' disables validation # - return value is an array of ($day, $month, $year) # -> $day and $month are returned 2-digit # -> $year is returned 4 digit # ===> in case of invalid date ALL of the above will be undef # ===> in case of omitted day or month, the appropriate array elements will be undef # - in case of errors such as invalid date $errstr is set and might be retrieved by $handle->errstr(); # - example call: # my ($day,$mon,$year) = $handle->parse_datestring( 'datestring' => '02.02.02', # 'format' => 'd.m.y', # optional # 'validate' => 0, # optional # ) # my $self = shift; my %classargs = (@_); # reset $errstr $errstr = ''; my ($d,$m,$y); # make sure 'datestring' is not ommited! if (! $classargs{'datestring'}) { $errstr = 'ERROR parsing datestring: \'datestring\' is missing'; } # make sure delimiter becomes '/' $classargs{'datestring'} =~ s/\D+/\//gi; # handle input like '06.2004' or '6.06' - assuming month of year if ($classargs{'datestring'} =~ /^(\d{1,2})\/(\d{2,4})$/gi ) { $m = $1; $y = $2; } # handle input like '2004' - assuming year elsif ($classargs{'datestring'} =~ /^\d{2,4}$/gi ) { $y = $classargs{'datestring'}; } # handle all other input - requesting days (possibly regardless of the year like '06.08' # need to reorder according to format and delimiter else { if (! $classargs{'format'}) { # assume default format DD/MM/YY(YY) ($d, $m, $y) = split(/\//, $classargs{'datestring'}); } else { # parse with provided formatting information my (%lookup,$first,$second,$third); #%position); # make sure delimiter becomes '/' $classargs{'format'} =~ s/[^dmyDMY]+/\//gi;right # need lower case $classargs{'format'} = lc ($classargs{'format'}); if (length($classargs{'format'}) >5) { $classargs{'format'} =~ s/([dmyDMY])+/$1/g; } ($first,$second,$third) = split(/\//, $classargs{'format'}); ($lookup{$first}, $lookup{$second}, $lookup{$third}) = split(/\//, $classargs{'datestring'}); $d = $lookup{'d'}; $m = $lookup{'m'}; $y = $lookup{'y'}; } } if (length($d) == 1) { $d = '0'.$d; } if (length($m) == 1) { $m = '0'.$m; } if (length($y) == 2) { if ($y >= 30) { $y += 1900; } else { $y += 2000; } } # validate date # NOTE: validate only if $m or $d are available! unless ($classargs{'validate'} eq '0') { my $m_index = int($m)-1; # validate month if ($m) { if (($m_index <0) || ($m_index >11)) { $errstr = "ERROR parsing datestring: not a valid month"; } } if ($d) { # validate day my @days_per_month = (31,28,31,30,31,30,31,31,30,31,30,31); # check for leap-year if ( ((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0) ) { $days_per_month[1] ++; } # check day my $d_integer = int($d); if ( ($d_integer < 1) || ($d_integer > $days_per_month[$m_index]) ) { $errstr = "ERROR parsing datestring: not a valid day in month $m"; } } } return ($d, $m, $y); }