2010-05-26 29 views
6

我有以下循環來計算當前周的日期並將其打印出來。它的工作原理,但我在Perl中游泳的日期/時間的可能性,並希望得到你的意見是否有更好的方法。下面是我寫的代碼:如何在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); 
} 

如前所述,這個工作,但它是最快捷,最有效的?我猜測速度和效率可能不一定會一起,但您的反饋非常感謝。

回答

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

+0

感謝您的更新代碼。 – ABach 2010-05-26 21:45:57

+0

一個簡單的問題 - 是否爲循環創建一個新的日期時間克隆每次迭代?這在Perl中可以嗎? – ABach 2010-05-26 21:56:32

+0

請注意,星期日版本無法正常工作。你需要在' - > truncate'之前加'(> = 1)',或者從星期天開始給你開始前一週。 – cjm 2010-05-26 22:24:49

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

以上是未經測試,但該想法應該工作。

+0

哇,這簡單得多。謝謝! – ABach 2010-05-26 20:53:31

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以獲取當地時區星期。

+1

如果你只使用POSIX作爲strftime(這確實是一個很好的理由使用它),那麼最好是說:使用POSIX QW(的strftime); 另外,%F給出了原始海報之後的YYYY-MM-DD格式。 – 2010-05-27 05:22:33

+0

謝謝。還有很多其他的代碼可以在代碼中選擇('$ wday'是做什麼的?),但基本上我想提供一個沒有'DateTime'的例子,這對於這個任務來說不是必需的。 – 2010-05-27 05:36:19

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; 
+0

你是對的。抱歉。 – 2010-05-28 03:02:01

+0

@Snake Plissken:沒有問題。名字真酷。 :) – Axeman 2010-05-28 03:59:35

+0

謝謝Axeman,你的代碼是在沒有安裝DateTime模塊的情況下使用perl v5.8.8。這很棒。我無法在我的prod服務器上安裝任何模塊。 – Gary 2016-03-28 14:19:44

相關問題