che*_*nyf 5 date sequence perl6 raku
我想生成一个序列,从上周五到周四结束,如果序列在周六和周日开始,则在前一周的周五结束.也就是说,假设今天是2018-05-09,那么上周五是2018-05-04,如果今天是2018-05-12,那么上周五也是 2018-05-04.所以我写道:
(Date.today, *.earlier(:1day) ... ( *.day-of-week==5 && *.week[1]+1==Date.today.week[1] )).tail # Output: 2018-05-06
Run Code Online (Sandbox Code Playgroud)
但结果2018-05-06却不是2018-05-04.
然后我用了一个Junction:
(Date.today, *.earlier(:1day) ... all( *.day-of-week==5, *.week[1]+1==Date.today.week[1] )).tail # Output: 2018-05-04
Run Code Online (Sandbox Code Playgroud)
为什么&&在第一种情况下是错的?该...经营者说:
右侧将有一个端点,可以是Inf或*表示"无限"列表(其元素仅按需生成),一个表达式将在True时结束序列,或其他元素如Junctions.
&&操作员出了什么问题?
问题是你的结局条件
*.day-of-week==5 && *.week[1]+1==Date.today.week[1]
Run Code Online (Sandbox Code Playgroud)
这是两个WhateverCode lambdas,每个lambdas都有1个参数.
*.day-of-week==5
Run Code Online (Sandbox Code Playgroud)
*.week[1]+1==Date.today.week[1]
Run Code Online (Sandbox Code Playgroud)
由于代码对象是真值,&&操作符移动到第二个.因此序列在到达前一周的星期日时停止.
即使代码是单个lambda,它也不会像你期望的那样工作,因为它将是一个带有两个参数的lambda.
执行此检查的正确方法是使用某种块.
{.day-of-week==5 && .week-number+1 == Date.today.week-number}
Run Code Online (Sandbox Code Playgroud)
将它包装在子程序中以便您可以测试它可能是个好主意.
sub last-friday ( Date:D $date ) {
# cache it so that it doesn't have to be looked up on each iteration
my $week-number = $date.week-number - 1;
(
$date,
*.earlier( :1day )
...
{
.day-of-week == 5
&&
.week-number == $week-number
}
).tail
}
say last-friday Date.new: :year(2018), :month( 5), :day( 9); # 2018-05-04
say last-friday Date.new: :year(2018), :month( 5), :day(12); # 2018-05-04
say Date.today.&last-friday; # 2018-05-04
Run Code Online (Sandbox Code Playgroud)
您也可以只计算正确的日期.
sub last-friday ( Date:D $date ) {
$date.earlier:
days => (
$date.day-of-week # reset to previous sunday
+ 2 # go two days earlier to get friday
)
}
say last-friday Date.new: :year(2018), :month( 5), :day( 9); # 2018-05-04
say last-friday Date.new: :year(2018), :month( 5), :day(12); # 2018-05-04
say Date.today.&last-friday; # 2018-05-04
Run Code Online (Sandbox Code Playgroud)