How can I get this week's dates in Perl?
I have the following loop to calculate the dates of the current week and print them out. It works, but I am swimming in the开发者_如何学JAVA amount of date/time possibilities in Perl and want to get your opinion on whether there is a better way. Here's the code I've written:
#!/usr/bin/env perl
use warnings;
use strict;
use DateTime;
# Calculate numeric value of today and the
# target day (Monday = 1, Sunday = 7); the
# target, in this case, is Monday, since that's
# when I want the week to start
my $today_dt = DateTime->now;
my $today = $today_dt->day_of_week;
my $target = 1;
# Create DateTime copies to act as the "bookends"
# for the date range
my ($start, $end) = ($today_dt->clone(), $today_dt->clone());
if ($today == $target)
{
# If today is the target, "start" is already set;
# we simply need to set the end date
$end->add( days => 6 );
}
else
{
# Otherwise, we calculate the Monday preceeding today
# and the Sunday following today
my $delta = ($target - $today + 7) % 7;
$start->add( days => $delta - 7 );
$end->add( days => $delta - 1 );
}
# I clone the DateTime object again because, for some reason,
# I'm wary of using $start directly...
my $cur_date = $start->clone();
while ($cur_date <= $end)
{
my $date_ymd = $cur_date->ymd;
print "$date_ymd\n";
$cur_date->add( days => 1 );
}
As mentioned, this works, but is it the quickest or most efficient? I'm guessing that quickness and efficiency may not necessarily go together, but your feedback is very appreciated.
A slightly improved version of friedo's answer ...
my $start_of_week =
DateTime->today()
->truncate( to => 'week' );
for ( 0..6 ) {
print $start_of_week->clone()->add( days => $_ );
}
However, this assumes that Monday is the first day of the week. For Sunday, start with ...
my $start_of_week =
DateTime->today()
->truncate( to => 'week' )
->subtract( days => 1 );
Either way, it's better to use the truncate
method than re-implement it, as friedo did ;)
You can use the DateTime object to get the current day of the week as a number ( 1-7 ). Then just use that to find the current week's Monday. For example:
my $today = DateTime->now;
my $start = $today->clone;
# move $start to Monday
$start->subtract( days => ( $today->wday - 1 ) ); # Monday gives 1, so on monday we
# subtract zero.
my $end = $start->clone->add( days => 7 );
The above is untested but the idea should work.
Would this work:
use strict;
use warnings;
use POSIX qw<strftime>;
my ( $day, $pmon, $pyear, $wday ) = ( localtime )[3..6];
$day -= $wday - 1; # Get monday
for my $d ( map { $day + $_ } 0..6 ) {
print strftime( '%A, %B %d, %Y', ( 0 ) x 3, $d, $pmon, $pyear ), "\n";
}
I'm printing them only as an illustration. You could store them as timestamps, like this:
use POSIX qw<mktime>;
my @week = map { mktime(( 0 ) x 3, $day + $_, $pmon, $pyear ) } 0..6;
This should work:
use POSIX; # for strftime
my $time = time ();
my $seconds = 24*60*60;
my @time = gmtime ();
$time = $time - $time[6] * $seconds;
for my $wday (0..6) {
$time += $seconds;
my @wday = gmtime ($time);
print strftime ("%A %d %B %Y\n", @wday);
}
Gives me:
$ ./week.pl Monday 24 May 2010 Tuesday 25 May 2010 Wednesday 26 May 2010 Thursday 27 May 2010 Friday 28 May 2010 Saturday 29 May 2010 Sunday 30 May 2010
If you want to get weeks starting on Sunday, change $time[6]
to ($time[6] + 1)
.
This assumes you want the GMT weeks. Change gmtime
to localtime
to get local time zone weeks.
精彩评论