File Coverage

blib/lib/Time/Crontab.pm
Criterion Covered Total %
statement 72 72 100.0
branch 17 20 85.0
condition 7 12 58.3
subroutine 17 17 100.0
pod 2 4 50.0
total 115 125 92.0


line stmt bran cond sub pod time code
1             package Time::Crontab;
2              
3 2     2   24566 use 5.008005;
  2         9  
  2         85  
4 2     2   11 use strict;
  2         3  
  2         68  
5 2     2   11 use warnings;
  2         13  
  2         76  
6 2     2   12 use Carp qw/croak/;
  2         3  
  2         150  
7 2     2   2032 use List::MoreUtils qw/all any uniq/;
  2         2710  
  2         204  
8 2     2   2006 use Set::Crontab;
  2         1972  
  2         2199  
9              
10             our $VERSION = "0.02";
11              
12             my @keys = qw/minute hour day month day_of_week/;
13             my @ranges = (
14             [0..59], #minute
15             [0..23], #hour
16             [1..31], #day
17             [1..12], #month
18             [0..7], #day of week
19             );
20             my %month_strs = (
21             jan => 1,
22             feb => 2,
23             mar => 3,
24             apr => 4,
25             may => 5,
26             jun => 6,
27             jul => 7,
28             aug => 8,
29             sep => 9,
30             oct => 10,
31             nov => 11,
32             dec => 12,
33             );
34             my %dow_strs = (
35             sun => 0,
36             mon => 1,
37             tue => 2,
38             wed => 3,
39             thu => 4,
40             fri => 5,
41             sat => 6,
42             );
43              
44             sub includes {
45 82     82 0 112 my ($list,$include) = @_;
46 2319         3808 my %include = map {
47 82         114 $_ => 1
48             } @$include;
49 82     1586   534 all { exists $include{$_} } @$list;
  1586         2409  
50             }
51              
52             sub new {
53 21     21 1 1487 my ($class,$str) = @_;
54 21         52 my $self = bless {}, $class;
55 21         44 $self->_compile($str);
56 13         47 $self;
57             }
58              
59             sub _compile {
60 21     21   30 my ($self, $str) = @_;
61              
62 21         53 $str =~ s/^\s+//g;
63 21         60 $str =~ s/\s+$//g;
64 21         76 my @rules = split /\s+/, $str;
65 21 100       362 croak 'incorrect cron field:'.$str if @rules != 5;
66 19         27 my %rules;
67 19         23 my $i=0;
68 19         31 for my $rule_o ( @rules ) {
69 86         116 my $rule = $rule_o;
70 86         113 my $key = $keys[$i];
71 86         101 my $range = $ranges[$i];
72 86 100       273 if ( $key eq 'month' ) {
73             my $replace = sub {
74 2     2   7 my $month = lc(shift);
75 2 50       12 exists $month_strs{$month} ? $month_strs{$month} : $month;
76 17         45 };
77 17         56 $rule =~ s!^([a-z]{3})$!$replace->($1);!ie;
  2         5  
78             }
79 86 100       162 if ( $key eq 'day_of_week' ) {
80             my $replace = sub {
81 2     2   6 my $dow = lc(shift);
82 2 50       12 exists $dow_strs{$dow} ? $dow_strs{$dow} : $dow;
83 16         42 };
84 16         54 $rule =~ s!^([a-z]{3})$!$replace->($1)!ie;
  2         4  
85             }
86 86         250 my $set_crontab = Set::Crontab->new($rule, $range);
87 86         7220 my @expand = $set_crontab->list();
88 86 100       1291 croak "bad format $key: $rule_o($rule)" unless @expand;
89 82 100       148 croak "bad range $key: $rule_o($rule)" unless includes(\@expand, $range);
90 80 100       455 if ( $key eq 'day_of_week' ) {
91             #day of week
92 13 100   55   73 if ( any { $_ == 7 } @expand ) {
  55         64  
93 7         15 unshift @expand, 0;
94             }
95 13         99 @expand = uniq @expand;
96             }
97 80         171 $rules{$key} = \@expand;
98 80         434 $i++;
99             }
100              
101 13         45 $self->{rules} = \%rules;
102             }
103              
104             sub _contains {
105 35     35   48 my ($self, $key, $num) = @_;
106 35     264   80 any { $_ == $num } @{$self->{rules}->{$key}};
  264         437  
  35         94  
107             }
108              
109             sub match {
110 9     9 1 10 my $self = shift;
111 9         201 my @lt = localtime($_[0]);
112 9 50 66     26 if ( $self->_contains('minute', $lt[1])
      66        
      66        
      33        
113             && $self->_contains('hour', $lt[2])
114             && ( $self->_contains('day', $lt[3]) || $self->_contains('day_of_week', $lt[6]) )
115             && $self->_contains('month', $lt[4]+1) ) {
116 8         146 return 1;
117             }
118 1         22 return;
119             }
120              
121             sub dump {
122 4     4 0 21 shift->{rules};
123             }
124              
125             1;
126             __END__