我开始有两个日期。如何在两个日期之间获得星期日的阵列?
my $date1 = 01/01/2016;
my $date2 = 05/15/2016;
我需要把星期日的所有日期两个日期之间。
任何想法,我应该开始?
我开始有两个日期。如何在两个日期之间获得星期日的阵列?
my $date1 = 01/01/2016;
my $date2 = 05/15/2016;
我需要把星期日的所有日期两个日期之间。
任何想法,我应该开始?
Your solution is good,但它可能会消耗大量的内存制造周日的阵列,可能永远不会被使用。 DateTime对象不小也不便宜。
另一种方法是迭代器,它每次调用都会生成下一个星期日。它根据需求生成每个星期日,而不是事先全部计算它们。这节省了内存并支持潜在的无限星期日。
use strict;
use warnings;
use v5.10;
sub sundays_iterator {
my($start, $end) = @_;
# Since we're going to modify it, copy it.
$start = $start->clone;
# Move to Sunday, if necessary.
$start->add(days => 7 - $start->day_of_week);
# Create an iterator using a closure.
# This will remember the values of $start and $end as
# they were when the function was returned.
return sub {
# Clone the date to return it without modifications.
# We always start on a Sunday.
my $date = $start->clone;
# Move to the next Sunday.
# Do this after cloning because we always start on Sunday.
$start->add(days => 7);
# Return Sundays until we're past the end date
return $date <= $endDate ? $date :();
};
}
返回封闭,一个匿名的子程序,它可以记住它与创建的词法变量。有点像内外对象,附带数据的函数。然后您可以像调用任何子程序一样调用它。
my $sundays = sundays_iterator($startDate, $endDate);
while(my $sunday = $sundays->()) {
say $sunday;
}
的好处是可以节省大量的内存,如果你正在服用的日期作为用户输入这可以是特别重要的:恶意攻击者可以问你一个巨大的范围内消耗了大量的服务器内存。
它还允许您分开使用列表生成列表。现在,您可以在日期范围内生成星期日的通用方式(或稍微调整一周的任何一天)。
缺点是它可能比在循环中构建数组慢一点......但可能并不明显。函数调用在Perl中相对较慢,因此每个星期日进行一次函数调用将比循环慢,但调用那些DateTime方法(调用调用其他方法的其他方法)将浪费这些成本。与使用DateTime相比,调用迭代器函数是存储桶中的一项功能。
这是我想出来的,但请让我知道是否有更好的方法。
use DateTime;
my $date1 = "1/1/2016";
my $date2 = "5/15/2016";
my ($startMonth, $startDay, $startYear) = split(/\//, $date1);
my ($endMonth, $endDay, $endYear) = split(/\//, $date2);
my $startDate = DateTime->new(
year => $startYear,
month => $startMonth,
day => $startDay
);
my $endDate = DateTime->new(
year => $endYear,
month => $endMonth,
day => $endDay
);
my @sundays;
do {
my $date = DateTime->new(
year => $startDate->year,
month => $startDate->month,
day => $startDate->day
);
push @sundays, $date if ($date->day_of_week == 7);
$startDate->add(days => 1);
} while ($startDate <= $endDate);
foreach my $sunday (@sundays) {
print $sunday->strftime("%m/%d/%Y");
}
由于星期几是连续的(除非我们进入Julian vs Gregorian日历间隔),您可以通过首先将'$ startDate'移动到一个7(或6)来加速星期天一次使用'$ startDate-> day_of_week',然后增加7天来获得下个星期日,直到你通过'$ endDate'。它也可能是'my $ date = $ startDate-> clone'的快速发型。最后,Time :: Piece的工作速度可能比DateTime快,因为它的包袱少了很多。 – Schwern
@ikegami虽然你的修改非常好,但它们从根本上改变了别人的答案。相反,把它们作为自己的回答或评论。 – Schwern
我不同意。答案中的问题应该在答案中得到解决。不应该克隆。现在有三个答案都说'使用DateTime' – ikegami
您应该先挑选一个模块。我偏好DateTime,使用DateTime::Format::Strptime进行解析。
use DateTime qw();
use DateTime::Format::Strptime qw();
my $start_date = "01/01/2016";
my $end_date = "05/15/2016";
my $format = DateTime::Format::Strptime->new(
pattern => '%m/%d/%Y',
time_zone => 'local',
on_error => 'croak',
);
my $start_dt = $format->parse_datetime($start_date)->set_formatter($format);
my $end_dt = $format->parse_datetime($end_date )->set_formatter($format);
my $sunday_dt = $start_dt->clone->add(days => 7 - $start_dt->day_of_week);
while ($sunday_dt <= $end_dt) {
print "$sunday_dt\n";
$sunday_dt->add(days => 7);
}
注意:您真的不应该使用DateTime->new
比尔使用和Schwern拥有的认可。这不是推荐使用的DateTime,因为它会创建更加复杂且容易出错的代码。如您所见,使用格式化程序将代码大小减半。
注:Schwern拥有提倡使用迭代器的,有一些(他回答所有的代码)再更换我的回答的最后四行的4倍。没有理由导致高水平的复杂性!他详细说明了迭代器保存多少内存,但是根本没有保存。
的DateTime ::集使构建一个迭代容易:
use DateTime::Format::Strptime();
use DateTime::Set();
my $start_date = "01/01/2016";
my $end_date = "05/15/2016";
my $format = DateTime::Format::Strptime->new(
pattern => '%m/%d/%Y',
time_zone => 'local',
on_error => 'croak',
);
my $iterator = DateTime::Set->from_recurrence(
start => $format->parse_datetime($start_date)->set_formatter($format),
end => $format->parse_datetime($end_date)->set_formatter($format),
recurrence => sub { $_[0]->add(days => 7 - $_[0]->day_of_week || 7) }, # next Sunday after $_[0]
);
while (my $date = $iterator->next) {
say $date;
}
不错!我不知道这个模块。 – ikegami
[DATETIME](HTTPS:// metacpan。org/pod/DateTime) – stevieb
您应该先选择一个模块。我偏爱[DateTime](http://search.cpan.org/perldoc?DateTime),使用[DateTime :: Format :: Strptime](http://search.cpan.org/perldoc?DateTime ::格式:: Strptime)进行解析。 – ikegami
星期日是*还是包括*两个日期? – Borodin