Мне было интересно, в Perl, какой оптимальный/ясный способ петли между двумя датами? Есть много модулей на CPAN, которые занимаются этим, но существует ли какое-либо эмпирическое правило для итерации между двумя датами?
Спасибо,
Мне было интересно, в Perl, какой оптимальный/ясный способ петли между двумя датами? Есть много модулей на CPAN, которые занимаются этим, но существует ли какое-либо эмпирическое правило для итерации между двумя датами?
Спасибо,
Для всего, что использует манипуляцию с датами 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
В наши дни большинство людей рекомендуют использовать 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);
}
Я думаю, что "лучший" способ сделать это во многом зависит от того, что вы делаете между этими двумя днями.
Во многих случаях достаточно простого цикла for (0..31)
.
В других случаях вы можете использовать значение эпохи и добавить/вычесть 86400 секунд на каждую итерацию.
В одном приложении, которое я написал, я делаю именно это, используя объект DateTime, который я добавляю за один день для каждой итерации, Это, вероятно, слишком много для многих приложений.
Я предлагаю решение 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
.
Это имеет то преимущество, что можно разбирать довольно произвольные форматы дат.