【问题标题】:Find last Friday’s Date in Perl 6?在 Perl 6 中查找上周五的日期?
【发布时间】:2018-05-09 04:19:26
【问题描述】:

我想生成一个从周一到周四在上周五结束的序列,如果序列从周六和周日开始,则生成前一周的周五。也就是说,假设今天是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 .

&& 运算符有什么问题?

【问题讨论】:

  • 第一个序列发出关于在接收器上下文中无用使用的错误。第二个也有同样的问题。我不认为 && 本身有什么问题。
  • 我认为在第一个序列中,“tail”只影响序列终止符。在第二种情况下,它的位置很好,但实际上关闭序列的是*.day-of-week==5 条件,这与我在下面使用的相同。
  • 对不起,我加了括号

标签: date sequence raku


【解决方案1】:

问题是你的结束条件

*.day-of-week==5 && *.week[1]+1==Date.today.week[1]

这是两个whateverCode lambda,每个都有一个参数。

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

【讨论】:

  • 我不认为 *.day-of-week==5 && *.week[1]+1==Date.today.week[1] 是一个带有 2 参数的 WhateverCode lambda。事实上,它只需要 1 个参数。例如:my $d = * > 12 && * %% 5; say $d.arity 将给出 1。等于my $f = -> $a { $a > 12 && $a %% 5},如果传入2个参数,会抛出错误Too many positionals passed; expected 1 argument but got 2
  • @chenyf 你是对的,它是两个WhateverCode lambdas。
  • @chenyf 我想知道为什么它没有通过第一次检查,为什么它没有在周六而不是周日登陆。固定。
【解决方案2】:

这个序列将从今天持续到上周五:

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 是序列终止符,或者它必须满足的条件。如果序列必须在星期五结束,最简单的条件就是上面的那个。

【讨论】:

  • 在我看来,上周是基于本周的前一周。我不希望本周(2018,19)的星期五,而是上周上一周(2018,18)的星期五。对不起我的英语:)
  • @chenyf 所以你的意思是,如果是星期六或星期日,你不想要那个星期五,但是前一个......
  • 是的,if Date.today == '2018-05-12' | '2018-05-13',输出应该是2018-05-04,而不是2018-05-11(这个星期五)。所以我使用week 方法来获取周数。
  • 在序列之外解决这个问题可能更容易......但我会试一试。
猜你喜欢
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
相关资源
最近更新 更多