我正在使用Perl DateTime Module ,我想知道如何计算First
,Second
,Third
,{{1} }和指定月份的Fourth
Last
,Sunday's
,... Monday's
。
我的方法:
从i = 1 ... DateTime-> last_day_of_month(...)运行循环。
将日期i指定为日期($ dt)并使用$ dt-> day_of_week()获取星期几。
使用计数器跟踪第一,第二,第三,第四,最后一个。
如果星期几匹配所需的日期并且计数器与所需的间隔匹配,则打破循环。
你能建议比上面更好(或更短)的方法吗? 感谢任何帮助。
答案 0 :(得分:5)
这是对my answer for finding the previous Monday (or any specified day of the week)的直接修改。唯一的困难是找出你开始的日期。
use DateTime;
# Here $nth is 1, 2, 3... for first, second, third, etc.
# Or -1, -2, -3... for last, next-to-last, etc.
# $dow is 1-7 for Monday-Sunday
# $month is 1-12
sub nth_day_of_month {
my ($nth, $dow, $year, $month) = @_;
my $date = ($nth > 0
# For 1st etc. we want the last day of that week
# (i.e. 7, 14, 21, 28 ...). We have to use add because
# the last week may extend into next month.
? DateTime->new(year => $year, month => $month, day => 1)
->add( days => $nth * 7 - 1)
# For last etc. we want the last day of the month
# (minus a week if next-to-last, etc)
: DateTime->last_day_of_month(year => $year, month => $month)
->add( weeks => $nth + 1)); # $nth is negative
# Back up to the first $dow on or before $date
$date->subtract(days => ($date->day_of_week - $dow) % 7);
# If we're not in the right month, then that month doesn't have the
# specified date (e.g. there's no 5th Tuesday in Sept. 2013).
return (($date->month == $month) ? $date : undef);
}
更新:这是一个稍微高效的版本。它使用相同的算法,但它将调用add
和subtract
组合在一起,所以它只需要进行一次日期数学运算。
sub nth_day_of_month {
my ($nth, $dow, $year, $month) = @_;
my ($date, $delta);
if ($nth > 0) {
# For 1st etc. we want the last day of that week (i.e. 7, 14, 21, 28, "35")
$date = DateTime->new(year => $year, month => $month, day => 1);
$delta = $nth * 7 - 1;
} else {
# For last etc. we want the last day of the month
# (minus a week if next-to-last, etc)
$date = DateTime->last_day_of_month(year => $year, month => $month);
$delta = 7 * ($nth + 1); # $nth is negative
}
# Back up to the first $dow on or before $date + $delta
$date->add(days => $delta - ($date->day_of_week + $delta - $dow) % 7);
# If we're not in the right month, then that month doesn't have the
# specified date (e.g. there's no 5th Tuesday in Sept. 2013).
return (($date->month == $month) ? $date : undef);
}
答案 1 :(得分:1)
另一个选择是进入模块Date::Manip:
use strict;
use warnings;
use Date::Manip::Base;
my $dmb = new Date::Manip::Base;
# First Tuesday in October 2013
my $year = 2013;
my $Nth = 1; # 1 = first
my $dow = 2; # 2 = Tuesday (day of week)
my $month = 10; # October
# $ymd is an array reference
my $ymd = $dmb->nth_day_of_week( $year, $Nth, $dow, $month );
print join '-', @$ymd; # prints 2013-10-1
要解析日期字符串,您可以执行以下操作:
use strict;
use warnings;
use Date::Manip::Date;
my $date = new Date::Manip::Date;
$date->parse('First Tuesday in October 2013');
print $date->printf('%Y-%m-%d'); # prints 2013-10-01
希望这有帮助!