What is the optimal/clearest way to loop between two dates in Perl? There are plenty of modules on CPAN that deal with such matter, but is there any rule of thumb for iterating between two dates?
问题:
回答1:
For everything that uses Date manipulation DateTime
is probably the best module out there. To get all dates between two dates with your own increment use something like this:
#!/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('-');
}
This will output:
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:
These days, most people would recommend using 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:
I'm offering up a Time::Piece
solution, because - unlike DateTime
it's a core module (as of 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;
}
Both Time::Piece
and Time::Seconds
are core as of perl 5.9.5. The latter is only needed for ONE_DAY
- otherwise you can just add 60 * 60 * 24
instead.
This has the advantage of being able to parse fairly arbitrary date formats.
回答4:
I think the "best" way to do that depends a lot on what you're doing between these two days.
In many cases, a simple for (0..31)
loop will suffice.
In other cases, you may wish to use an epoch value, and add/subtract 86400 seconds on each itteration.
In one application I've written, I do exactly this, using a DateTime object that I add one day to for each iteration. This is likely overkill for many applications, though.