В Perl, как я могу гарантировать, что строка соответствует допустимой дате?
Проверьте здесь:
http://www.perlmonks.org/?node_id=564594
Я верю, что вы получите ответы от мудрых монахов.
Модуль DateTime будет проверять даты при создании нового объекта.
$ perl -we 'use DateTime; my $dt;
eval { $dt = DateTime->new(
year => 2012,
month => 2,
day => 30);
}; print "Error: $@" if $@;'
Error: Invalid day of month (day = 30 - month = 2 - year = 2012) at -e line 1
Он также динамически работает с данным объектом DateTime
:
$dt->set(day => 30);
Что-то вроде этого, используя Class:: Date, должно работать
perl testit.pl
Не удалось проверить дату или время диапазона.
use Class::Date;
my $d=Class::Date->new('2021-02-30');
unless ( $d->error ) {
print "good date\n";
} else {
print $d->errstr(). "\n";
}
exit;
Вы также можете использовать Time:: Local:
#!/usr/bin/env perl
use strict; use warnings;
use Carp qw( croak );
use Time::Local qw( timegm );
my @to_check = ('1927 06 18', '2012 02 30');
for my $date ( @to_check ) {
printf "'%s' is %s\n", $date, check_date($date) ? 'valid' : 'invalid';
}
sub check_date {
my ($date) = @_;
my ($year, $month, $mday) = split ' ', $date;
my $ret;
eval {
$ret = timegm(0, 0, 0, $mday, $month - 1, $year - 1900);
};
return $ret && $ret;
}
Вы можете сделать это с помощью POSIX mktime
, но, по-видимому, только если у вас достаточно гибкая реализация mktime
.
То, что я делаю, это подключить номера, а затем использовать локальное время, чтобы вернуть их, и если я получу одно и то же значение дня, это допустимое число. Итак, учитывая вашу строку:
my ( $y, $m, $d ) = split ' ', $date_string;
die "$date_string is not a valid date!"
unless ( $d == ( localtime mktime( 0, 0, 0, $d, $m - 1, $y - 1900 ))[3] )
;
См. в версиях mktime
, к которым я привык, mktime( 0, 0, 0, 30, 1, 112 )
сделает '2012-03-01'
и 30 != 1
Возможно, это тоже поможет:
use Time::Piece; #in perl CORE distro since 5.10
use 5.010;
say Time::Piece->strptime("2011-02-29","%Y-%m-%d")->strftime("%Y-%m-%d");
#2011-03-01
say Time::Piece->strptime("2012-02-29","%Y-%m-%d")->strftime("%Y-%m-%d");
#2012-02-29