2010-08-16 3 views
4

В моем сценарии мне нужно выполнить итерацию по датам с датой начала и датой окончания. Как я могу это сделать в Perl?Как перебирать диапазон дат?

+0

В каком формате указаны даты? гггг-мм-дд? – Zaid

+0

Формат должен быть YYYY/MM/DD – nimo

ответ

5

Использование DateTime модуль. Вот простой пример, который перечисляет десять предыдущих дней:

use 5.012; 
use warnings; 
use DateTime; 

my $end = DateTime->now; 
my $day = $end->clone->subtract(days => 10); # ten days ago 

while ($day < $end) { 
    say $day; 
    $day->add(days => 1); # move along to next day 
} 

 

Update (после просмотра вашего комментария/обновления):

Для разбора в строках даты, то смотрите на DateTime::Format на модулях CPAN.

Вот пример использования DateTime::Format::DateParse, который делает синтаксический YYYY/MM/DD:

use DateTime::Format::DateParse; 
my $d = DateTime::Format::DateParse->parse_datetime('2010/06/23'); 
-1

Perl имеет богатый набор временных и манипуляционную дату модулей, как показано здесь:

http://datetime.perl.org/?Modules

И есть некоторые примеры дата и время проблем там.

С Perl всегда есть много способов сделать это.

0

Вы можете попробовать Date::Calc::Iterator

# This puts all the dates from Dec 1, 2003 to Dec 10, 2003 in @dates1 
    # @dates1 will contain ([2003,12,1],[2003,12,2] ... [2003,12,10]) ; 
    my $i1 = Date::Calc::Iterator->new(from => [2003,12,1], to => [2003,12,10]) ; 
    my @dates1 ; 
    push @dates1,$_ while $_ = $i1->next ; 
+2

Конечно, в чем смысл использования итератора, если вы просто собираетесь вывести значения в массив? –

4

Один простой подход заключается в использовании Date::Simple модуль, который использует от оператора-перегрузки:

use strict; 
use warnings; 
use Date::Simple; 

my $date = Date::Simple->new ('2010-01-01'); # Stores Date::Simple object 
my $endDate = Date::Simple->today;     # Today's date 

while (++$date < $endDate) { 

    print ($date - $endDate) , "day", 
      (($date-$endDate) == 1 ? '' : 's'), " ago\n"; 
} 
3
use DateTime::Format::Strptime qw(); 
my $start = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d')->parse_datetime('2010/08/16'); 
my $end = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d')->parse_datetime('2010/11/24'); 

while ($start < $end) { 
    $start->add(days => 1); 
    say $start->ymd('/'); 
} 
2

Я хотел бы использовать тот факт, что strftime нормализуется дату для меня:

#!/usr/bin/perl 

use strict; 
use warnings; 

use POSIX qw/strftime/; 

my $start = "2010/08/16"; 
my $end = "2010/09/16"; 

my @time  = (0, 0, 0); 
my ($y, $m, $d) = split "/", $start; 
$y -= 1900; 
$m--; 
my $offset  = 0; 

while ((my $date = strftime "%Y/%m/%d", @time, $d + $offset, $m, $y) le $end) { 
    print "$date\n"; 
} continue { 
    $offset++; 
} 
0

При установке дополнительных модулей перл не является предпочтительным, можно использовать этот подход, основанный на основном библиотека Perl POSIX:

#!/usr/bin/perl 

use strict; 
use warnings; 
use POSIX qw(strftime); 

# CREATE CALENDAR 
my @Calendar =(); 
my $years = 3; 
my @Now = localtime(); # An array of 9 date-time parameters. 

for my $count (0 .. (365 * $years)) { 
    # If date is January 1st, manual shift to December 31st is needed, 
    # because days ([yday][2]) are counted from January 31st and never shift back one year. 
    if($Now[4] == 0 && $Now[3] == 1) { 
     unshift @Calendar, strftime("%Y-%m-%d", @Now); 
     $Now[5] --; # Reduce by one the sixth array element #5 - year. 
     $Now[4] = 11; # Set fifth array element № 4 - to December. 
     $Now[3] = 31; # Set fourth array element № 3 - to 31st. 
    } else { 
     unshift @Calendar, strftime("%Y-%m-%d", @Now); 
     $Now[3] --; 
    } 
} 

# Print out. 
my $size = @Calendar; 
for (my $i = 0; $i < $size; $i++) { 
    print $Calendar[$i]."\n"; 
} 
Смежные вопросы