В Perl, как я могу гарантировать, что строка соответствует допустимой дате?

104
10

Мне было интересно, есть ли в Perl простой способ убедиться, что строка даты соответствует допустимой дате.


Например, 2012 02 30 неверен, потому что он не существует.

спросил(а) 2012-02-24T17:31:00+04:00 9 лет назад
1
Решение
61

Проверьте здесь:
http://www.perlmonks.org/?node_id=564594

Я верю, что вы получите ответы от мудрых монахов.

ответил(а) 2012-02-24T17:36:00+04:00 9 лет назад
122

Модуль 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);

ответил(а) 2012-02-24T17:59:00+04:00 9 лет назад
85

Что-то вроде этого, используя 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;

ответил(а) 2012-02-24T17:48:00+04:00 9 лет назад
61

Вы также можете использовать 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;
}

ответил(а) 2012-02-25T22:58:00+04:00 9 лет назад
61

Вы можете сделать это с помощью 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

ответил(а) 2012-02-24T18:39:00+04:00 9 лет назад
44

Возможно, это тоже поможет:


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

ответил(а) 2012-02-24T18:26:00+04:00 9 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема