File Coverage

blib/lib/Date/Span.pm
Criterion Covered Total %
statement 40 40 100.0
branch 34 34 100.0
condition 18 19 94.7
subroutine 11 11 100.0
pod 3 3 100.0
total 106 107 99.0


line stmt bran cond sub pod time code
1 2     2   1355 use strict;
  2         4  
  2         194  
2 2     2   10 use warnings;
  2         3  
  2         112  
3              
4             package Date::Span;
5             {
6             $Date::Span::VERSION = '1.127';
7             }
8             # ABSTRACT: deal with date/time ranges than span multiple dates
9              
10 2     2   10 use Exporter;
  2         2  
  2         99  
11 2     2   1305 BEGIN { our @ISA = 'Exporter' }
12              
13             our @EXPORT = qw(range_expand range_durations range_from_unit); ## no critic
14              
15              
16             sub _date_time {
17 8     8   15 my $date = $_[0] - (my $time = $_[0] % 86400);
18 8         15 ($date, $time)
19             }
20              
21             sub range_durations {
22 3     3 1 790 my ($start, $end) = @_;
23 3 100       13 return if $end < $start;
24              
25 2         6 my ($start_date, $start_time) = _date_time($start);
26 2         4 my ($end_date, $end_time) = _date_time($end);
27              
28 2 100       7 push my @results, [
29             $start_date,
30             (( $end_date != $start_date ) ? ( 86400 - $start_time ) : ($end - $start))
31             ];
32              
33 11         18 push @results,
34 2 100       8 map { [ $start_date + 86400 * $_, 86400 ] }
35             (1 .. ($end_date - $start_date - 86400) / 86400)
36             if ($end_date - $start_date > 86400);
37              
38 2 100       9 push @results, [ $end_date, $end_time ] if $start_date != $end_date;
39              
40 2         13 return @results;
41             }
42              
43              
44             sub range_expand {
45 3     3 1 4 my ($start, $end) = @_;
46 3 100       12 return if $end < $start;
47              
48 2         5 my ($start_date, $start_time) = _date_time($start);
49 2         3 my ($end_date, $end_time) = _date_time($end);
50              
51 2 100       8 push my @results, [
52             $start, ( ( $end_date != $start_date ) ? ( $start_date + 86399 ) : $end )
53             ];
54              
55 11         25 push @results,
56 2 100       8 map { [ $start_date + 86400 * $_, $start_date + 86400 * $_ + 86399 ] }
57             (1 .. ($end_date - $start_date - 86400) / 86400)
58             if ($end_date - $start_date > 86400);
59              
60 2 100       7 push @results, [ $end_date, $end ] if $start_date != $end_date;
61              
62 2         11 return @results;
63             }
64              
65              
66             my @monthdays = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
67              
68             sub _is_leap {
69 7 100 100 7   73 not($_[0] % 4) and (($_[0] % 100) or not($_[0] % 400)) and $_[0] > 0
      66        
70             }
71              
72             sub _leap_secs {
73 5 100 100 5   13 _is_leap($_[0]) && $_[1] == 1 ? 86400 : 0
74             }
75              
76             sub _begin_secs {
77 9     9   57 require Time::Local;
78 9   100     111 Time::Local::timegm(
      100        
      100        
      100        
79             0, # $sec
80             $_[4]||0, # $min
81             $_[3]||0, # $hour
82             $_[2]||1, # $mday
83             $_[1]||0, # $mon
84             $_[0] # $year
85             );
86             }
87              
88             sub range_from_unit {
89 11 100 100 11 1 9758 my $code = (ref($_[-1])||'' eq 'CODE') ? pop : \&_begin_secs;
90 11 100       65 return unless @_;
91 10         20 my ($year,$month,$day,$hour,$min) = @_;
92 10         25 my $begin_secs = $code->(@_);
93 10 100       316 my $length = defined $min ? 60
    100          
    100          
    100          
    100          
94             : defined $hour ? 3600
95             : defined $day ? 86400
96             : defined $month ? 86400 * $monthdays[$month+0]
97             + _leap_secs($year, $month)
98             : 86400 * (_is_leap($year) ? 366 : 365);
99              
100 10         67 return ($begin_secs, $begin_secs + $length - 1);
101             }
102              
103              
104             1;
105              
106             __END__