File Coverage

lib/Cron/Toolkit/Pattern/Last.pm
Criterion Covered Total %
statement 41 43 95.3
branch 16 20 80.0
condition 2 4 50.0
subroutine 8 8 100.0
pod 0 4 0.0
total 67 79 84.8


line stmt bran cond sub pod time code
1             package Cron::Toolkit::Pattern::Last;
2 2     2   14 use strict;
  2         5  
  2         79  
3 2     2   11 use warnings;
  2         3  
  2         137  
4 2     2   12 use parent 'Cron::Toolkit::Pattern';
  2         3  
  2         14  
5 2     2   172 use Cron::Toolkit::Utils qw(:all);
  2         4  
  2         1671  
6              
7 55672     55672 0 118305 sub type { return 'last'; }
8              
9             sub new {
10 10     10 0 58 my ($class, %args) = @_;
11 10         71 my $self = $class->SUPER::new(%args);
12              
13 10 100       76 if ($args{field_type} eq 'dow') {
    50          
14             # DOW: dayL or L (L = 7L)
15 4 100       64 if ($args{value} =~ /^(\d+)L$/i) {
16 3         18 $self->{dow} = $1;
17             } else {
18 1         6 $self->{dow} = 7; # L alone = last Saturday
19             }
20             } elsif ($args{field_type} eq 'dom') {
21             # DOM: L or L-offset
22 6 50       55 if ($args{value} =~ /^L-?(\d*)$/i) {
23 6 100       34 $self->{offset} = $1 eq '' ? 0 : $1;
24             }
25             }
26              
27 10         39 return $self;
28             }
29              
30             sub match {
31 55601     55601 0 91861 my ($self, $value, $tm) = @_;
32              
33 55601 100       96816 if ($self->field_type eq 'dom') {
34 55495   50     173853 my $target = $tm->length_of_month - ($self->{offset} // 0);
35 55495         242204 return $tm->day_of_month == $target;
36             }
37              
38 106 50       140 if ($self->field_type eq 'dow') {
39 106         127 my $target_dow = $self->{dow};
40              
41             # Find the last occurrence of target_dow in this month
42 106         189 my $last_day = $tm->length_of_month;
43 106         232 my $last_tm = $tm->with_day_of_month($last_day);
44 106         190 my $days_back = ($last_tm->day_of_week - $target_dow + 7) % 7;
45 106         97 my $last_occurrence = $last_day - $days_back;
46              
47 106         392 return $tm->day_of_month == $last_occurrence;
48             }
49              
50 0         0 return 0;
51             }
52              
53             sub to_english {
54 10     10 0 55 my ($self) = @_;
55              
56 10 100       47 if ($self->field_type eq 'dom') {
57 6 100       25 if ($self->{offset} == 0) {
58 5         39 return "on the last day";
59             } else {
60 1         6 return "on the " . num_to_ordinal($self->{offset}) . " to last day";
61             }
62             }
63              
64 4 50       12 if ($self->field_type eq 'dow') {
65 4   50     35 my $day_name = $DAY_NAMES{$self->{dow}} // 'day';
66 4         24 return "on the last $day_name";
67             }
68              
69 0           return "last";
70             }
71              
72             1;