在Perl中如何查找给定日期的上一个星期一的日期?

时间:2011-06-07 07:51:44

标签: perl date

我正在寻找一个Perl脚本,可以在任何指定的日期给我上周一。

e.g。对于2011-06-11日期,脚本应返回2011-06-06

9 个答案:

答案 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