我试图在Perl中获取开始日期和结束日期之间的每个日期。我最初使用以下代码完成了7天:
use Time::ParseDate;
my $newdate;
my $newtime;
my @dates = ();
my $newtime->[0] = parsedate($start_datetime);
my $newdate->[0] = strftime("%Y-%m-%d",localtime($newtime->[0]));
push(@dates, $newdate->[0]);
my $newtime->[1] = parsedate($newdate->[0]) + (1 * 24 * 60 * 60);
my $newdate->[1] = strftime("%Y-%m-%d",localtime($newtime->[1]));
push(@dates, $newdate->[1]);
my $newtime->[2] = parsedate($newdate->[1]) + (1 * 24 * 60 * 60);
my $newdate->[2] = strftime("%Y-%m-%d",localtime($newtime->[2]));
push(@dates, $newdate->[2]);
my $newtime->[3] = parsedate($newdate->[2]) + (1 * 24 * 60 * 60);
my $newdate->[3] = strftime("%Y-%m-%d",localtime($newtime->[3]));
push(@dates, $newdate->[3]);
my $newtime->[4] = parsedate($newdate->[3]) + (1 * 24 * 60 * 60);
my $newdate->[4] = strftime("%Y-%m-%d",localtime($newtime->[4]));
push(@dates, $newdate->[4]);
my $newtime->[5] = parsedate($newdate->[4]) + (1 * 24 * 60 * 60);
my $newdate->[5] = strftime("%Y-%m-%d",localtime($newtime->[5]));
push(@dates, $newdate->[5]);
my $newtime->[6] = parsedate($newdate->[5]) + (1 * 24 * 60 * 60);
my $newdate->[6] = strftime("%Y-%m-%d",localtime($newtime->[6]));
push(@dates, $newdate->[6]);
my $newtime->[7] = parsedate($newdate->[6]) + (1 * 24 * 60 * 60);
my $newdate->[7] = strftime("%Y-%m-%d",localtime($newtime->[7]));
push(@dates, $newdate->[7]);
但意识到它应该能够工作任何天数。 所以我尝试了下面的循环,但它对我来说不是很有用
my $newdate;
my $newtime;
my @dates = ();
my $start_date = substr($start_datetime, 0, 10) ;
$start_date =~ s/-//gi;
my $end_date = substr($end_datetime, 0, 10) ;
$end_date =~ s/-//gi;
my $days = yyyymmdd_to_rata_die($end_date) - yyyymmdd_to_rata_die($start_date);
my $newtime->[0] = parsedate($xml->{action_content}->{start_date});
my $newdate->[0] = strftime("%Y-%m-%d",localtime($newtime->[0]));
push(@dates, $newdate->[0]);
for(my $x=1;$x<$days;$x++)
{
my $newtime->[$x] = parsedate($newdate->[$x-1]) + (1 * 24 * 60 * 60);
my $newdate->[$x] = strftime("%Y-%m-%d",localtime($newtime->[$x]));
push(@dates, $newdate->[$x]);
}
我在Stackoverflow上的问题中得到了以下函数
sub yyyymmdd_to_rata_die
{
use integer;
my ( $y, $m, $d ) = $_[0] =~ /\A([0-9]{4})([0-9]{2})([0-9]{2})\z/
or return;
my $adj;
if ( $m <= 2 )
{
$y -= ( $adj = ( 14 - $m ) / 12 );
$m += 12 * $adj;
}
elsif ( $m > 14 )
{
$y += ( $adj = ( $m - 3 ) / 12 );
$m -= 12 * $adj;
}
$d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 + ( $y / 100 * 36524 + $y / 400 ) - 306;
}
任何援助都会受到极大的谴责
编辑: $ start_datetime =&#34; 2014-09-01 00:00:00&#34 ;; $ end_datetime =&#34; 2014-09-07 23:59:59&#34 ;;
我需要在开始和结束日期之间的所有日子,即。
2014-09-01
2014-09-02
2014-09-03
2014-09-04
2014-09-05
2014-09-06
2014-09-07
答案 0 :(得分:5)
我建议您使用Time::Piece
模块。它不应该需要安装,因为它是Perl 5版本10以来的核心模块。
看起来像这样
use strict;
use warnings;
use Time::Piece;
print days_between('2014-01-01', '2014-12-01'), "\n";
sub days_between {
my ($start, $end) = map Time::Piece->strptime($_, '%Y-%m-%d'), @_;
($end - $start)->days;
}
<强>输出强>
334
<强>更新强>
我道歉。我误解了您的要求,并认为您希望两个日期之间的天数。该程序打印一个列表,其中包含两个限制之间的所有日期。如果在标量上下文中调用,它将像以前一样在列表中提供数字天。
use strict;
use warnings;
use Time::Piece;
use Time::Seconds qw/ ONE_DAY /;
printf "%d days:\n", scalar days_from_to('2014-09-01 00:00:00', '2014-09-07 23:59:59');
print "$_\n" for days_from_to('2014-09-01 00:00:00', '2014-09-07 23:59:59');
sub days_from_to {
my @limits = map /(\d\d\d\d-\d\d-\d\d)/, @_;
@limits = map Time::Piece->strptime($_, '%Y-%m-%d'), @limits;
my @dates = ( $limits[0] );
push @dates, $dates[-1] + ONE_DAY while $dates[-1] < $limits[-1];
map $_->ymd, @dates;
}
<强>输出强>
7 days:
2014-09-01
2014-09-02
2014-09-03
2014-09-04
2014-09-05
2014-09-06
2014-09-07
<强>更新强>
如果需要更严格的正则表达式拒绝0123-45-67
之类的字符串,那么你可以使用这个
my $date_re = qr/(?:
(?: (?:19|20)[0-9][0-9] ) -
(?:
(?: 0?[469] | 11 ) -
(?: 0?[1-9] | [12][0-9] | 30 )
|
(?: 0?[13578] | 1[02] ) -
(?: 0?[1-9] | [12][0-9] | 3[01] )
|
(?: 0?2 ) -
(?: 0?[1-9] | [12][0-9] )
)
)/x;
将接受1900年到2099年之间的日期,并确保该月的某一天对该月有效。唯一的附带条件是它将允许任何一年的2月29日。
或者您可能更喜欢使用Regexp::Common::time
这样的
use Regexp::Common qw/ time /;
my $date_re = $RE{time}{strftime}{-pat => '%Y-%m-%d'};
但这与2月29日的问题相同。
子程序将如下所示
sub days_from_to {
my @limits = map /($date_re)/, @_;
@limits = map Time::Piece->strptime($_, '%Y-%m-%d'), @limits;
my @dates = ( $limits[0] );
push @dates, $dates[-1] + ONE_DAY while $dates[-1] < $limits[-1];
map $_->ymd, @dates;
}
答案 1 :(得分:0)
使用Time::Piece;
等内容可以让您的生活更轻松#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
use Time::Seconds;
my $fmt = '%Y-%m-%d';
my $start_date = '2014-09-08';
my $days = 30;
my @dates;
my $date = Time::Piece->strptime($start_date, $fmt);
foreach (1 .. $days) {
push @dates, $date;
$date += ONE_DAY;
}
say $_ for @dates;
更新:Borodin's answer看起来使用非常类似的方法处理您添加到问题中的输入和所需输出。