我正在寻找一个Perl脚本,可以在任何指定的日期给我上周一。
e.g。对于2011-06-11日期,脚本应返回2011-06-06
答案 0 :(得分: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,而mod 7是无操作。但是% 7
,它适用于任何所需的星期几,而不仅仅是星期一。)
如果您确实想要上一个星期一,可以更改减法:
$date->subtract(days => ($date->day_of_week - $desired_dow) % 7 || 7);
如果您需要解析在命令行中输入的日期,您可能需要查看DateTime::Format::Natural。
答案 1 :(得分: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)。
答案 2 :(得分: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 :(得分: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;
答案 4 :(得分: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
答案 5 :(得分:1)
Zeller's congruence会为您提供一周中的某一天。从那里它应该很容易。
答案 6 :(得分: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
答案 7 :(得分: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";
希望它有所帮助!
答案 8 :(得分: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