2011-06-07 56 views

回答

24

我假設如果給定的日期是星期一,你想要相同的日期(而不是前一個星期一)。下面是與DateTime做到這一點的一種方法:

use DateTime; 

my $date = DateTime->new(year => 2011, month => 6, day => 11); 
my $desired_dow = 1;   # Monday 
$date->subtract(days => ($date->day_of_week - $desired_dow) % 7); 
print "$date\n"; 

(事實上,週一的特殊情況下,% 7是沒有必要的,因爲$date->day_of_week - 1將始終爲0 – 6,並認爲國防部7是無糖。OP但隨着% 7,它適用於任何所需日的一週,而不僅僅是星期一)

如果你確實想在上週一,你可以改變減法:

$date->subtract(days => ($date->day_of_week - $desired_dow) % 7 || 7); 

如果您需要解析在命令行中輸入的日期,則可能需要查看DateTime::Format::Natural

+2

在CPAN上有很多方法可以做到這一點和很多日期/時間模塊,但DateTime是迄今爲止用於處理日期和時間的最佳模塊。 – 2011-06-07 09:42:38

1

Zeller's congruence會給你星期幾。從那裏它應該很容易。

+1

這是一篇newspost的新聞郵件。原始發佈的替代鏈接,可讀性更好:[''](http://groups.google.com/group/comp.lang.perl/msg/dbd4d19f71ec6b9a) – daxim 2011-06-07 08:50:33

+2

@daxim,更不用說在Perl 5中完全沒有必要。'(localtime)[6]'是星期幾。 – Axeman 2011-06-07 12:50:25

12

你也可以使用Time :: ParseDate,它理解「上週一」。

一個班輪維護Perl的聲譽:

perl -MTime::ParseDate -M'POSIX qw(strftime)' -l -e'foreach (@ARGV) { my $now= parsedate($_); my $e= parsedate("last Monday", NOW => $now) ; print "$_ : ", strftime "%F", localtime($e)}' 2011-06-11 2011-06-12 2011-06-13 2011-06-14 

而一個健全的腳本:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Time::ParseDate; # to parse dates 
use POSIX qw(strftime); # to format dates 

foreach my $date (@ARGV) 
    { my $date_epoch= parsedate($date) || die"'cannot parse date '$date'\n"; 
    my $monday= parsedate("last Monday", NOW => $date_epoch);     # last Monday before NOW 
    print "Monday before $date: ", strftime("%F", localtime($monday)), "\n"; # %F is YYYY-MM-DD 
    } 

有兩點要注意:如果日期是星期一,那麼你得到的以前星期一,這可能會或可能不是你想要的,改變現在只需設置到第二天(每天添加60 * 60 * 24,到$ date_epoch)。然後Time :: ParseDate非常自由,例如2011-23-38會很高興解析(如2012-12-09)。

+1

雖然'DateTime'是一種在Perl中處理日期和時間的規範方法,'Time :: ParseDate'一直是我對這類事情的最愛。 – Grrrr 2011-06-07 08:49:09

+1

我其實很少需要處理日期,這可能是爲什麼我找到parsedate(「上週一」,NOW => $ date_epoch);可愛,更重要的是,易於記憶。 – mirod 2011-06-07 09:08:27

3

很簡單的東西,使用標準的Perl庫。

#!/usr/bin/perl 

use strict; 
use warnings; 
use 5.010; 

use Time::Local; 
use POSIX 'strftime'; 

my $date = shift || die "No date given\n"; 

my @date = split /-/, $date; 
$date[0] -= 1900; 
$date[1]--; 

die "Invalid date: $date\n" unless @date == 3; 

my $now = timelocal(0, 0, 12, reverse @date); 

while (strftime('%u', localtime $now) != 1) { 
    $now -= 24 * 60 * 60; 
} 

我將把它留作練習,讓讀者查閱所使用的各種模塊和功能。

如果您使用DateTime,它可能會更簡單。

3

本着Perl的精神,有很多方法可以做到這一點。

use Modern::Perl; 
use Date::Calc qw/Day_of_Week/; 
my $date = '2011/6/11'; 
my @fields = split /\//, $date; 
my @new_date = Add_Delta_Days(@fields , 1 - Day_of_Week(@fields)); 
say join "/", @new_date; 
2

你可以使用Date::Manip,其中有一個Date_GetPrev功能和理解 「星期一」

$ perl -MDate::Manip -le 'print UnixDate(Date_GetPrev(shift, "Monday", 0), "%Y-%m-%d")' 2011-06-11 
2011-06-06 
1

在本月底,$tstamp將有時間戳你想:

use strict; 
use warnings; 
use POSIX qw<mktime>; 

my $time = '2011-06-11'; 

my ($year, $month, $day) = split /-0?/, $time; 
my $tstamp = mktime(0, 0, 0, $day, $month - 1, $year - 1900); 
my $dow = (localtime $tstamp)[6]; 
$tstamp -= (($dow > 1 ? 0 : 7) + $dow - 1) * 24 * 60 * 60; 

這假定「上週一」是指最近一次發生在星期一之前的到指定日期。「因此,如果星期幾是星期一(1),那麼它會減去另外的7。

+0

你對你的偏好進行測試,2011-06-07(星期二)將返回2011-05-30的時間戳。 – 2011-06-07 15:31:51

+0

@ Ven'Tatsu啊,我超過了自己。我測試,發佈,然後閱讀比較錯誤,並急匆匆地將其更改爲2. – Axeman 2011-06-07 15:36:57

0

如果你是一個像我這樣的奴隸,並且必須使用沒有庫的公司Perl,並且不允許你安裝它們,老式方法:

my $datestring = ""; 
my $secondsEpoc = time(); #gives the seconds from system epoch 
my $secondsWantedDate; 
my $seconds2substract; 

$datestring = localtime($secondsEpoc); 
print "Today's date and time ".$datestring."\n"; 
my ($second,$minute,$hour,$d,$M,$y,$wd,$yd) = (localtime)[0,1,2,3,4,5,6,7]; 
#print "hour: ".$hour; 
#print "minute: ".$minute; 
#print "second: ".$second; 
#print "week day: ".$wd; #week day is 1=Monday .. 7=Sunday 

$seconds2substract = 24 * 60 * 60; # seconds in 24 hours 
$secondsWantedDate=$secondsEpoc-$seconds2substract; 
$datestring = localtime($secondsWantedDate); 
print "Yesterday at the same time ".$datestring."\n"; 


my $days2Substract = $wd-1; 
$seconds2substract = ($days2Substract * 24 * 60 * 60); 
$secondsWantedDate=$secondsEpoc-$seconds2substract; 
$datestring = localtime($secondsWantedDate); 
print "Past Monday same time ".$datestring."\n"; 

$seconds2substract = ($days2Substract * 24 * 60 * 60) + ($hour *60 *60) + ($minute * 60) + $second; 
$secondsWantedDate = $secondsEpoc-$seconds2substract; 
$datestring = localtime($secondsWantedDate); 
print "Past Monday at 00:00:00 ".$datestring."\n"; 

希望它可以幫助別人

+0

這不涉及閏秒,http://en.wikipedia.org/wiki/Leap_second – Toto 2014-02-13 16:32:29

+0

你是對的,但它閏秒不重要的許多用途:相信我,沒有被允許添加庫是地獄,它可以讓你的代碼成爲可笑地增長,你只要找到一個足夠好的快速解決方案必需的任務:) – Cristina 2014-05-09 08:17:08

0

有很多方法可以做到這一點在Perl下面是如何將其與Perl庫進行Moment

#!/usr/bin/perl 

use strict; 
use warnings FATAL => 'all'; 
use feature 'say'; 

use Moment; 

sub get_monday_date { 
    my ($date) = @_; 

    my $moment = Moment->new(dt => "$date 00:00:00"); 

    my $weekday_number = $moment->get_weekday_number(first_day => 'monday'); 

    my $monday = $moment->minus(day => ($weekday_number - 1)); 

    return $monday->get_d(); 
} 

say get_monday_date('2011-06-11'); # 2011-06-06 
相關問題