Find last Friday’s Date in Perl 6?

不羁的心 提交于 2019-12-07 04:46:45

问题


I want to generate a sequence that ends last Friday from Monday to Thursday, and the Friday of the previous week if the sequence starts on Saturday and Sunday. That is, assuming that today is 2018-05-09, then last Friday is 2018-05-04, If today is 2018-05-12, then last Friday is also 2018-05-04. So I write:

(Date.today, *.earlier(:1day) ... ( *.day-of-week==5 && *.week[1]+1==Date.today.week[1] )).tail # Output: 2018-05-06

But the result is 2018-05-06 instead of 2018-05-04.

Then I used a Junction:

(Date.today, *.earlier(:1day) ... all( *.day-of-week==5,  *.week[1]+1==Date.today.week[1] )).tail # Output: 2018-05-04

Why && in the first situation is wrong? The ... operator says that:

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.

What's wrong with the && operator?


回答1:


The problem is your ending condition

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

That is two WhateverCode lambdas that each take 1 argument.

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

Since a code object is a true value, the && operator moves onto the second one. So the sequence stops when it reaches sunday of the previous week.

Even if the code was a single lambda it wouldn't work like you expect as it would be a lambda that takes two arguments.

The right way to do this check is to use some sort of block.

{.day-of-week==5 && .week-number+1 == Date.today.week-number}

It might be a good idea to wrap it in a subroutine so that you can test it.

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

You could also just calculate the proper date.

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



回答2:


This sequence will go from today to last Friday:

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)␤» 

Also

say Date.new("2018-05-11"), *.earlier(:1day) ...  *.day-of-week==5;
# OUTPUT: «(2018-05-11)␤»

The last argument of the ... operator is the sequence terminator, or a condition it must meet. If the sequence must end on Friday, the simplest condition is that one above.



来源:https://stackoverflow.com/questions/50245452/find-last-friday-s-date-in-perl-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!