在 Perl 6 中查找上周五的日期?
Find last Friday’s Date in Perl 6?
我想生成一个从周一到周四结束于上周五的序列,如果该序列从周六和周日开始,则为前一周的周五。即假设今天是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
但结果是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
为什么第一种情况的&&
是错误的? ... 运算符表示:
The right-hand side will have an endpoint, which can be Inf or * for "infinite" lists (whose elements are only produced on demand), an expression which will end the sequence when True, or other elements such as Junctions.
&&
运算符有什么问题?
这个顺序将从今天到上周五:
say Date.today, *.earlier(:1day) ... *.day-of-week==5
# OUTPUT: «(2018-05-09 2018-05-08 2018-05-07 2018-05-06 2018-05-05 2018-05-04)»
还有
say Date.new("2018-05-11"), *.earlier(:1day) ... *.day-of-week==5;
# OUTPUT: «(2018-05-11)»
last argument of the ... operator是序列终止符,或者说它必须满足的条件。如果序列必须在星期五结束,最简单的条件就是上面那个。
问题是你的结束条件
*.day-of-week==5 && *.week[1]+1==Date.today.week[1]
这是两个 WhateverCode lambda,每个都有 1 个参数。
*.day-of-week==5
*.week[1]+1==Date.today.week[1]
因为代码对象是真值,所以 &&
运算符移动到第二个。所以序列在到达前一周的星期日时停止。
即使代码是单个 lambda,它也不会像您预期的那样工作,因为它是一个带有两个参数的 lambda。
进行此检查的正确方法是使用某种块。
{.day-of-week==5 && .week-number+1 == Date.today.week-number}
将它包装在子例程中可能是个好主意,以便您可以对其进行测试。
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
您也可以只计算正确的日期。
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
我想生成一个从周一到周四结束于上周五的序列,如果该序列从周六和周日开始,则为前一周的周五。即假设今天是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
但结果是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
为什么第一种情况的&&
是错误的? ... 运算符表示:
The right-hand side will have an endpoint, which can be Inf or * for "infinite" lists (whose elements are only produced on demand), an expression which will end the sequence when True, or other elements such as Junctions.
&&
运算符有什么问题?
这个顺序将从今天到上周五:
say Date.today, *.earlier(:1day) ... *.day-of-week==5
# OUTPUT: «(2018-05-09 2018-05-08 2018-05-07 2018-05-06 2018-05-05 2018-05-04)»
还有
say Date.new("2018-05-11"), *.earlier(:1day) ... *.day-of-week==5;
# OUTPUT: «(2018-05-11)»
last argument of the ... operator是序列终止符,或者说它必须满足的条件。如果序列必须在星期五结束,最简单的条件就是上面那个。
问题是你的结束条件
*.day-of-week==5 && *.week[1]+1==Date.today.week[1]
这是两个 WhateverCode lambda,每个都有 1 个参数。
*.day-of-week==5
*.week[1]+1==Date.today.week[1]
因为代码对象是真值,所以 &&
运算符移动到第二个。所以序列在到达前一周的星期日时停止。
即使代码是单个 lambda,它也不会像您预期的那样工作,因为它是一个带有两个参数的 lambda。
进行此检查的正确方法是使用某种块。
{.day-of-week==5 && .week-number+1 == Date.today.week-number}
将它包装在子例程中可能是个好主意,以便您可以对其进行测试。
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
您也可以只计算正确的日期。
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