在 Perl 中,如何确保字符串对应于有效日期?

发布于 2025-01-08 22:34:56 字数 91 浏览 0 评论 0原文

我想知道 Perl 中是否有一种简单的方法来确保日期字符串对应于有效日期。

例如,2012 02 30 不正确,因为它不存在。

I was wondering if there is a simple way in Perl to ensure that a date string corresponds to a valid date.

For example, 2012 02 30 is incorrect because it doesn't exist.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凉城已无爱 2025-01-15 22:34:56

DateTime 模块将在创建新对象时验证日期。

$ perl -we 'use DateTime; my $dt; 
    eval { $dt = DateTime->new( 
        year => 2012, 
        month => 2, 
        day => 30);
    }; print "Error: $@" if $@;'

错误:-e 第 1 行处的月份日期无效(日 = 30 - 月 = 2 - 年 = 2012)

它也可以在给定的 DateTime 对象上动态运行:

$dt->set(day => 30);

The DateTime module will validate dates when creating a new object.

$ 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

It also works dynamically on a given DateTime object:

$dt->set(day => 30);
甜心小果奶 2025-01-15 22:34:56

像这样使用 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;

Something like this using Class::Date should work

perl testit.pl
Range check on date or time failed

use Class::Date;


my $d=Class::Date->new('2021-02-30');
unless ( $d->error ) {
  print "good date\n";
} else {
   print $d->errstr(). "\n";
}
exit;
迷你仙 2025-01-15 22:34:56

检查这里:
http://www.perlmonks.org/?node_id=564594

我相信你会得到您向明智的僧侣寻求答案。

Check here:
http://www.perlmonks.org/?node_id=564594

I believe you'll get the answers you seek from the wise monks.

熊抱啵儿 2025-01-15 22:34:56

您可以通过使用 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

You can do this through the use of POSIX mktime, but apparently only if you have a flexible-enough implementation of mktime.

What I do is plug the numbers in and then use local time to get them back and if I get the same day value back, it's a valid number. So, given your string:

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] )
    ; 

See, in the versions of mktime that I'm used to, mktime( 0, 0, 0, 30, 1, 112 ) would make '2012-03-01' and 30 != 1

旧夏天 2025-01-15 22:34:56

您还可以使用 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;
}

You can also use 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;
}
醉梦枕江山 2025-01-15 22:34:56

也许这也会有帮助:

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

May be this will help too:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文