Каков оптимальный способ петли между двумя датами в Perl?

Мне было интересно, в Perl, какой оптимальный/ясный способ петли между двумя датами? Есть много модулей на CPAN, которые занимаются этим, но существует ли какое-либо эмпирическое правило для итерации между двумя датами?

Спасибо,

Ответ 1

Для всего, что использует манипуляцию с датами DateTime, вероятно, лучший модуль. Чтобы получить все даты между двумя датами с вашим собственным приращением, используйте что-то вроде этого:

#!/usr/bin/env perl
use strict;
use warnings;
use DateTime;

my $start = DateTime->new(
    day   => 1,
    month => 1,
    year  => 2000,
);

my $stop = DateTime->new(
    day   => 10,
    month => 1,
    year  => 2000,
);


while ( $start->add(days => 1) < $stop ) {
    printf "Date: %s\n", $start->ymd('-');
}

Это выведет:

Date: 2000-01-02
Date: 2000-01-03
Date: 2000-01-04
Date: 2000-01-05
Date: 2000-01-06
Date: 2000-01-07
Date: 2000-01-08
Date: 2000-01-09

Ответ 2

В наши дни большинство людей рекомендуют использовать DateTime:

use DateTime;   

my $start = DateTime->new(...); # create two DateTime objects
my $end   = DateTime->new(...);

while ($start <= $end) {
    print $start->ymd, "\n";
    $start->add(days => 1);
}

Ответ 3

Я думаю, что "лучший" способ сделать это во многом зависит от того, что вы делаете между этими двумя днями.

Во многих случаях достаточно простого цикла for (0..31).

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

В одном приложении, которое я написал, я делаю именно это, используя объект DateTime, который я добавляю за один день для каждой итерации, Это, вероятно, слишком много для многих приложений.

Ответ 4

Я предлагаю решение Time::Piece, потому что в отличие от DateTime это основной модуль (начиная с perl 5.9.5):

#!/usr/bin/env perl

use strict;
use warnings;
use Time::Piece;
use Time::Seconds;

my $FORMAT = '%Y-%m-%d';

my $start = '2016-01-22';
my $end   = '2016-03-11';


my $start_t = Time::Piece->strptime( $start, $FORMAT );
my $end_t   = Time::Piece->strptime( $end,   $FORMAT );

while ( $start_t <= $end_t ) {
   print $start_t ->strftime($FORMAT), "\n";
   $start_t += ONE_DAY;
}

Оба Time::Piece и Time::Seconds являются ядром по perl 5.9.5. Последнее необходимо только для ONE_DAY - иначе вы можете просто добавить 60 * 60 * 24.

Это имеет то преимущество, что можно разбирать довольно произвольные форматы дат.