cormanaz has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to get Date::Manip to list the date of each Friday in the first 5 months of this year. I have tried @date = ParseRecur('2020:1-5:0:5:0:0:0'); and @date = ParseRecur('every friday of every week in 2020'); and both return empty lists. What am I doing wrong?

Replies are listed 'Best First'.
Re: Date::Manip ParseRecur help needed
by haukex (Archbishop) on Jan 09, 2020 at 21:37 UTC

    Personally I find understanding Date::Manip::Recur patterns a bit too complicated for my taste. I prefer DateTime::Set - more verbose of course, but IMHO better understandable and therefore more maintainable and reusable:

    use warnings; use strict; use DateTime; use DateTime::Set; my $fridays = DateTime::Set->from_recurrence( start => DateTime->new( year=>2020, month=>1, day=>1 ), before => DateTime->new( year=>2020, month=>6, day=>1 ), recurrence => sub { my $dt = shift; return $dt if $dt->is_infinite; if ( $dt->dow>5 ) { $dt->add(days=>12-$dt->dow) } elsif ( $dt->dow<5 ) { $dt->add(days=> 5-$dt->dow) } else { $dt->add(weeks=>1) } die $dt unless $dt->dow==5; # double-check return $dt; } ); my $iter = $fridays->iterator; while ( my $dt = $iter->next ) { print $dt->strftime("%A, %B %e %Y"), "\n"; } __END__ Friday, January 3 2020 Friday, January 10 2020 Friday, January 17 2020 Friday, January 24 2020 Friday, January 31 2020 Friday, February 7 2020 Friday, February 14 2020 Friday, February 21 2020 Friday, February 28 2020 Friday, March 6 2020 Friday, March 13 2020 Friday, March 20 2020 Friday, March 27 2020 Friday, April 3 2020 Friday, April 10 2020 Friday, April 17 2020 Friday, April 24 2020 Friday, May 1 2020 Friday, May 8 2020 Friday, May 15 2020 Friday, May 22 2020 Friday, May 29 2020
Re: Date::Manip ParseRecur help needed
by poj (Abbot) on Jan 09, 2020 at 21:18 UTC

    Try

    my @date = ParseRecur("0:0:1*5:0:0:0","","Jan 1 2020","May 31 2020");

    or (update)

    my @date = ParseRecur("every Friday in every month","", "First day in Jan 2020", "Last day in May 2020");
    poj
      No dice. Running
      use Date::Manip; my @date = ParseRecur("0:0:1*5:0:0:0","","Jan 1 2020","May 31 2020"); foreach my $d (0..$#date) { print UnixDate($d,"%a %b %d %Y"),"\n"; }
      Yields:
      Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Wed Jan 01 1000 Mon Jan 01 1100 Sat Jan 01 1200 Fri Jan 01 1300 Wed Jan 01 1400 Mon Jan 01 1500 Sat Jan 01 1600 Fri Jan 01 1700 Wed Jan 01 1800 Mon Jan 01 1900 Sat Jan 01 2000 Fri Jan 01 2100
      Replacing the second line with the "update" version gives:
      Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Sat Jan 11 2020 Wed Jan 01 1000 Mon Jan 01 1100 Sat Jan 01 1200 Fri Jan 01 1300 Wed Jan 01 1400 Mon Jan 01 1500 Sat Jan 01 1600 Fri Jan 01 1700 Wed Jan 01 1800 Mon Jan 01 1900 Sat Jan 01 2000 Fri Jan 01 2100
        #foreach my $d (0..$#date) { foreach my $d (@date) { print UnixDate($d,"%a %b %d %Y"),"\n"; }
        poj
Re: Date::Manip ParseRecur help needed
by johngg (Canon) on Jan 10, 2020 at 14:21 UTC

    A solution using the, core since 5.10, Time::Piece module and its associated Time::Seconds for date arithmetic. I accept the strftime() default format for brevity but you could craft the output any way you like.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -MTime::Piece -MT +ime::Seconds -E ' my $ffJan = Time::Piece->strptime( q{2020/01/01}, q{%Y/%m/%d} ); $ffJan += ONE_DAY for 1 .. 5 - $ffJan->day_of_week(); my $end = Time::Piece->strptime( q{2020/06/01}, q{%Y/%m/%d} ); while ( $ffJan->epoch() < $end->epoch() ) { say $ffJan->strftime(); $ffJan += ONE_WEEK; }' Fri, 03 Jan 2020 00:00:00 UTC Fri, 10 Jan 2020 00:00:00 UTC Fri, 17 Jan 2020 00:00:00 UTC Fri, 24 Jan 2020 00:00:00 UTC Fri, 31 Jan 2020 00:00:00 UTC Fri, 07 Feb 2020 00:00:00 UTC Fri, 14 Feb 2020 00:00:00 UTC Fri, 21 Feb 2020 00:00:00 UTC Fri, 28 Feb 2020 00:00:00 UTC Fri, 06 Mar 2020 00:00:00 UTC Fri, 13 Mar 2020 00:00:00 UTC Fri, 20 Mar 2020 00:00:00 UTC Fri, 27 Mar 2020 00:00:00 UTC Fri, 03 Apr 2020 00:00:00 UTC Fri, 10 Apr 2020 00:00:00 UTC Fri, 17 Apr 2020 00:00:00 UTC Fri, 24 Apr 2020 00:00:00 UTC Fri, 01 May 2020 00:00:00 UTC Fri, 08 May 2020 00:00:00 UTC Fri, 15 May 2020 00:00:00 UTC Fri, 22 May 2020 00:00:00 UTC Fri, 29 May 2020 00:00:00 UTC

    I hope this is helpful.

    Update: It makes more sense to calculate the cut-off epoch once at the start rather than every loop.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -MTime::Piece -MT +ime::Seconds -E ' my $endEpoch = Time::Piece->strptime( q{2020/06/01}, q{%Y/%m/%d} )->ep +och(); my $ffJan = Time::Piece->strptime( q{2020/01/01}, q{%Y/%m/%d} ); $ffJan += ONE_DAY for 1 .. 5 - $ffJan->day_of_week(); while ( $ffJan->epoch() < $endEpoch ) { say $ffJan->strftime(); $ffJan += ONE_WEEK; }' Fri, 03 Jan 2020 00:00:00 UTC Fri, 10 Jan 2020 00:00:00 UTC Fri, 17 Jan 2020 00:00:00 UTC Fri, 24 Jan 2020 00:00:00 UTC Fri, 31 Jan 2020 00:00:00 UTC Fri, 07 Feb 2020 00:00:00 UTC Fri, 14 Feb 2020 00:00:00 UTC Fri, 21 Feb 2020 00:00:00 UTC Fri, 28 Feb 2020 00:00:00 UTC Fri, 06 Mar 2020 00:00:00 UTC Fri, 13 Mar 2020 00:00:00 UTC Fri, 20 Mar 2020 00:00:00 UTC Fri, 27 Mar 2020 00:00:00 UTC Fri, 03 Apr 2020 00:00:00 UTC Fri, 10 Apr 2020 00:00:00 UTC Fri, 17 Apr 2020 00:00:00 UTC Fri, 24 Apr 2020 00:00:00 UTC Fri, 01 May 2020 00:00:00 UTC Fri, 08 May 2020 00:00:00 UTC Fri, 15 May 2020 00:00:00 UTC Fri, 22 May 2020 00:00:00 UTC Fri, 29 May 2020 00:00:00 UTC

    Cheers,

    JohnGG