我怎样才能在Perl中获得本周的日期?

时间:2010-05-26 20:26:53

标签: perl datetime

我有以下循环来计算当前周的日期并打印出来。它有效,但我在Perl的日期/时间可能性游泳,想要了解是否有更好的方法。这是我写的代码:

#!/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 );
}

如上所述,这是有效的,但它是最快还是最有效的?我猜测速度和效率可能不一定在一起,但您的反馈非常受欢迎。

4 个答案:

答案 0 :(得分:14)

friedo的答案略有改进......

my $start_of_week =
    DateTime->today()
            ->truncate( to => 'week' );

for ( 0..6 ) {
    print $start_of_week->clone()->add( days => $_ );
}

但是,这假设星期一是一周的第一天。星期天,从......开始。

my $start_of_week =
    DateTime->today()
            ->truncate( to => 'week' )
            ->subtract( days => 1 );

无论哪种方式,最好使用truncate方法而不是重新实现它,就像friedo所做的那样;)

答案 1 :(得分:4)

您可以使用DateTime对象将当前星期几作为数字(1-7)。然后用它来查找当周的星期一。例如:

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 );

以上是未经测试的,但这个想法应该有用。

答案 2 :(得分:2)

这会有效吗?

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";
}

我打印它们只是为了说明。您可以将它们存储为时间戳,如下所示:

use POSIX qw<mktime>;
my @week = map { mktime(( 0 ) x 3, $day + $_, $pmon, $pyear ) } 0..6;

答案 3 :(得分:1)

这应该有效:

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);
}

给我:

$ ./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

如果您希望从周日开始数周,请将$time[6]更改为($time[6] + 1)

这假设你想要GMT周。将gmtime更改为localtime以获取当地时区周。