首页 > 解决方案 > 在 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

为什么&&在第一种情况下是错误的?...操作员说:

右侧将有一个端点,可以是 Inf 或 * 表示“无限”列表(其元素仅按需生成),一个表达式将在 True 时结束序列,或其他元素,如 Junctions。

运营商怎么了&&

标签: datesequenceraku

解决方案


问题是你的结束条件

*.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

推荐阅读