File Coverage

blib/lib/Date/Simple/Range.pm
Criterion Covered Total %
statement 66 69 95.6
branch 20 34 58.8
condition 6 15 40.0
subroutine 17 17 100.0
pod 1 12 8.3
total 110 147 74.8


line stmt bran cond sub pod time code
1             package Date::Simple::Range;
2              
3 1     1   71144 use Date::Simple;
  1         28896  
  1         50  
4 1     1   2875 use Time::Seconds ();
  1         19723  
  1         40  
5 1     1   16 use Carp;
  1         9  
  1         137  
6              
7 1     1   7 use base qw/ Class::Accessor /;
  1         2  
  1         5817  
8              
9             __PACKAGE__->mk_accessors(qw/ start end index /);
10              
11             our $VERSION = '1.1';
12              
13             use overload
14 1         14 'fallback' => 1,
15             'bool' => 'bool',
16             '<>' => 'iterator',
17             '@{}' => 'array',
18             '>>' => 'shiftr',
19             '<<' => 'shiftl',
20             '=' => 'clone',
21 1     1   7609 '""' => 'stringify';
  1         2  
22              
23             sub new
24             {
25 2     2 1 36 my $proto = shift;
26 2   33     13 my $class = ref($proto) || $proto;
27              
28 2         20 my $self = bless $proto->SUPER::new(), $class;
29              
30 2         25 my ($start, $end) = @_;
31              
32 2         7 $self->start($start);
33 2         32 $self->end($end);
34              
35 2         182 return $self;
36             }
37              
38             sub to_date_simple
39             {
40 8     8 0 11 my ($self, $arg) = @_;
41              
42             return undef
43 8 50       14 unless defined $arg;
44              
45 8 100       30 if (ref($arg)) {
46 7 50       52 return $arg
47             if $arg->isa('Date::Simple');
48              
49 0 0 0     0 $arg = $arg->ymd
50             if $arg->isa('DateTime')
51             or $arg->isa('Time::Piece');
52              
53 0 0       0 $arg = Date::Simple->new($arg->date(0))
54             if $arg->isa('Date::Calc::Object');
55             }
56              
57 1         8 return Date::Simple->new($arg);
58             }
59              
60             sub start
61             {
62 66     66 0 2018 my ($self, $arg) = @_;
63            
64 66 100       217 return $self->_start_accessor
65             unless defined $arg;
66              
67 4 50       13 $arg = $self->to_date_simple($arg)
68             or croak('invalid start date: ', $arg);
69              
70 4 50 66     136 croak('start date (', $arg, ') is past end date (', $self->end, ')')
71             if defined $self->end
72             and $arg > $self->end;
73              
74 4         113 return $self->_start_accessor($arg);
75             }
76              
77             sub end
78             {
79 85     85 0 9943 my ($self, $arg) = @_;
80            
81 85 100       491 return $self->_end_accessor
82             unless defined $arg;
83              
84 4 50       9 $arg = $self->to_date_simple($arg)
85             or croak('invalid end date: ', $arg);
86              
87 4 50 33     22 croak('end date (', $arg, ') is before start date (', $self->start, ')')
88             if defined $self->start
89             and $arg < $self->start;
90              
91 4         60 return $self->_end_accessor($arg);
92             }
93              
94             sub duration
95             {
96 3     3 0 1721 my $self = shift;
97              
98 3 50       8 return undef unless $self;
99              
100 3         32 return Time::Seconds->new(($self->end - $self->start + 1) * (60 * 60 * 24));
101             }
102              
103             sub array
104             {
105 2     2 0 2449 my $self = shift;
106              
107 2 50       5 return [] unless $self;
108              
109 2         20 my @a;
110              
111 2         5 for ($i = $self->start; $i <= $self->end; $i++) {
112 10         113 push(@a, Date::Simple->new($i));
113             }
114              
115 2         28 return \@a;
116             }
117              
118             sub iterator
119             {
120 12     12 0 1051 my $self = shift;
121              
122 12 50       26 return undef unless $self;
123              
124 12 100       159 $self->index($self->start->prev)
125             unless defined $self->index;
126              
127 12 100       187 return $self->index(undef)
128             if $self->index == $self->end;
129              
130 10         108 return $self->index($self->index->next);
131             }
132              
133             sub bool
134             {
135 39     39 0 28212 my $self = shift;
136 39   66     86 return defined $self->start && defined $self->end;
137             }
138              
139             sub stringify
140             {
141 1     1 0 16 my $self = shift;
142              
143 1 50       3 if ($self) {
144 1         16 $self->start . ' - ' . $self->end;
145             } else {
146 0         0 return 'incomplete range';
147             }
148             }
149              
150             sub shiftr
151             {
152 1     1 0 523 my ($self, $amount) = @_;
153              
154 1         4 $self->start($self->start + $amount);
155 1         12 $self->end($self->end + $amount);
156              
157 1         9 return $self;
158             }
159              
160             sub shiftl
161             {
162 1     1 0 4 my ($self, $amount) = @_;
163              
164 1         5 $self->start($self->start - $amount);
165 1         11 $self->end($self->end - $amount);
166              
167 1         9 return $self;
168             }
169              
170             sub clone
171             {
172 1     1 0 691 my $self = shift;
173              
174 1         4 return new Date::Simple::Range(
175             new Date::Simple($self->start),
176             new Date::Simple($self->end));
177             }
178              
179             1;
180              
181             =head1 NAME
182              
183             Date::Simple::Range - A range of Date::Simple objects
184              
185             =head1 SYNOPSIS
186              
187             use Date::Simple::Range;
188              
189             # the new, start and end methods accept Date::Simple, DateTime, Time::Piece,
190             # Date::Calc::Object objects, ISO 8601 strings and undef values.
191              
192             my $range = new Date::Simple::Range('2008-01-01', '2008-01-05');
193              
194             my $incomplete = new Date::Simple::Range(undef, '2008-01-05');
195             my $start = new Date::Simple('2008-01-01');
196             $incomplete->start($start); # now complete
197              
198              
199             if ($range) { ... # start and end dates are both valid
200              
201             print $range; # stringifies as '2008-01-01 - 2008-01-05'
202             # or 'incomplete range'
203              
204             $range->start # start date
205             $range->end # end date
206              
207             $range->start('2008-01-02') # change start date
208             $range->end($anotherobj) # change end date
209              
210             $range >>= 2 # shift range two days in the future...
211             $range <<= 4 # ...and 4 days in the past
212              
213             $range->duration # duration as a Time::Seconds object
214             $range->duration->days # duration in days
215             scalar @$range # duration in days (ugly!)
216              
217             foreach (@$range) { ... # iterate thru the range
218             while (<$range>) { ... # another way, less memory hungry
219              
220             $range->clone # a new, independent, cloned range object
221              
222             =head1 DESCRIPTION
223              
224             A range of Date::Simple objects.
225              
226             =head1 SEE ALSO
227              
228             Date::Simple, Time::Seconds
229              
230             =head1 AUTHOR
231              
232             Alessandro Zummo, Ea.zummo@towertech.itE
233              
234             =head1 COPYRIGHT
235              
236             Copyright (C) 2008 by Alessandro Zummo
237              
238             This program is free software; you can redistribute it and/or
239             modify it under the terms of the GNU General Public License version 2 as
240             published by the Free Software Foundation.
241              
242             =cut