File Coverage

blib/lib/Date/Handler/Delta.pm
Criterion Covered Total %
statement 70 123 56.9
branch 15 54 27.7
condition 16 32 50.0
subroutine 17 24 70.8
pod 0 16 0.0
total 118 249 47.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             package Date::Handler::Delta;
3              
4 8     8   1041 use strict;
  8         14  
  8         335  
5 8     8   42 use Carp;
  8         13  
  8         557  
6 8     8   45 use Data::Dumper;
  8         14  
  8         369  
7 8     8   43 use vars qw(@ISA $VERSION);
  8         19  
  8         539  
8             $VERSION = '1.0';
9              
10 8     8   44 use POSIX qw(floor strftime mktime);
  8         163  
  8         100  
11              
12             use overload (
13             '""' => 'AsScalar',
14             '0+' => 'AsNumber',
15             'neg' => 'Neg',
16             '+' => 'Add',
17             '-' => 'Sub',
18             '*' => 'Mul',
19             '/' => 'Div',
20             '<=>' => 'Cmp',
21             '++' => 'Incr',
22 0     0   0 '%' => sub { croak "Impossible to modulo a Date::Handler::Delta"; },
23 0     0   0 '**' => sub { croak "Trying to obtain square virtual minutes out of a virtual delta boy ?"; },
24 8         100 fallback => 1,
25 8     8   1219 );
  8         13  
26              
27              
28             sub new
29             {
30 377     377 0 576 my ($classname, $delta) = @_;
31              
32 377         837 my $self = {};
33 377         5307 bless $self, $classname;
34              
35 377 50       796 croak "No args to new()" if not defined $delta;
36              
37 377 100       1166 if(ref($delta) =~ /ARRAY/)
    100          
    50          
38             {
39 360         1014 my $delta_array = $self->DeltaFromArray($delta);
40 360         1131 $self->{months} = $delta_array->[0];
41 360         1296 $self->{seconds} = $delta_array->[1];
42             }
43             elsif(ref($delta) =~ /HASH/)
44             {
45 4         20 my $delta_array = $self->DeltaFromArray([
46             $delta->{years},
47             $delta->{months},
48             $delta->{days},
49             $delta->{hours},
50             $delta->{minutes},
51             $delta->{seconds},
52             ]);
53 4         14 $self->{months} = $delta_array->[0];
54 4         10 $self->{seconds} = $delta_array->[1];
55            
56             }
57             elsif(!ref($delta))
58             {
59 13         29 $self->{months} = 0;
60 13         20 $self->{seconds} = $delta;
61             }
62             else
63             {
64 0         0 croak "Arguments to new in unknown format.";
65             }
66            
67 377 0 33     816 croak "Could not parse delta" if !defined $self->{months} && !defined $self->{seconds};
68              
69 377         1722 return $self;
70             }
71              
72              
73              
74             #Accessors (Might want to optimised some of those)
75 631     631 0 2368 sub Months { return shift->{months}; }
76 580     580 0 2810 sub Seconds { return shift->{seconds}; }
77              
78              
79             #Oveload methods.
80 268     268 0 2254 sub AsScalar { return sprintf("%d:%d", @{shift()->AsArray()}); }
  268         560  
81 0     0 0 0 sub AsNumber { return sprintf("%d.%d",@{shift()->AsArray()}); }
  0         0  
82              
83             sub AsArray
84             {
85 323     323 0 481 my $self = shift;
86 323   100     614 return [$self->Months()||0,$self->Seconds()||0];
      100        
87             }
88              
89             sub AsHash
90             {
91 0     0 0 0 my $self = shift;
92              
93             return {
94 0         0 month => $self->Months(),
95             seconds => $self->Seconds(),
96             };
97             }
98              
99              
100             sub Add
101             {
102 55     55 0 76 my ($self, $delta) = @_;
103              
104              
105 55         107 my $self_array = $self->AsArray();
106              
107 55 100       309 if(!ref($delta))
    100          
    50          
108             {
109 2         4 $self_array->[1] += $delta;
110             }
111             elsif($delta->isa('Date::Handler::Delta'))
112             {
113 39         87 $self_array->[0] += $delta->Months();
114 39         261 $self_array->[1] += $delta->Seconds();
115             }
116             elsif($delta->isa('Date::Handler'))
117             {
118 14         45 return $delta->Add($self);
119             }
120             else
121             {
122 0         0 $self_array->[1] += $delta;
123             }
124              
125 41         155 return ref($self)->new([0, $self_array->[0], 0,0,0,$self_array->[1]]);
126             }
127              
128             sub Sub
129             {
130 19     19 0 25 my ($self, $delta) = @_;
131              
132 19 50 33     377 if(ref($delta) && $delta->isa('Date::Handler'))
133             {
134 0         0 croak "Cannot substract a date from a Delta.";
135             }
136              
137 19         39 return $self->Add(-$delta);
138             }
139             sub Cmp
140             {
141 0     0 0 0 my ($self, $delta) = @_;
142              
143 0 0       0 croak "Cannot compare a Delta with something else than another Delta" if(!ref($delta));
144              
145 0 0       0 if($delta->isa('Date::Handler::Delta'))
146             {
147 0         0 my $self_time = 24*60*60*(30*$self->Months())+$self->Seconds();
148 0         0 my $delta_time = 24*60*60*(30*$delta->Months())+$delta->Seconds();
149              
150 0         0 return $self_time <=> $delta_time;
151             }
152             else
153             {
154 0         0 croak "Cannot compare a Delta with something else than another Delta";
155             }
156            
157             }
158              
159             sub Mul
160             {
161 14     14 0 24 my ($self, $delta) = @_;
162              
163 14 50       38 if(!ref($delta))
    0          
    0          
164             {
165 14         31 my $months = $self->Months() * $delta;
166 14         35 my $seconds = $self->Seconds() * $delta;
167              
168 14         63 return ref($self)->new([0, $months,0,0,0,$seconds]);
169             }
170             elsif($delta->isa('Date::Handler::Delta'))
171             {
172 0         0 croak "Cannot obtain square minutes from Delta multiplication";
173             }
174             elsif($delta->isa('Date::Handler'))
175             {
176 0         0 croak "Cannot Multiply a date with a delta.";
177             }
178             else
179             {
180 0         0 my $months = $self->Months() * $delta;
181 0         0 my $seconds = $self->Seconds() * $delta;
182              
183 0         0 return ref($self)->new([0, $months,0,0,0,$seconds]);
184             }
185              
186             }
187             sub Div
188             {
189 9     9 0 14 my ($self, $delta) = @_;
190              
191 9 50       24 if(!ref($delta))
    0          
    0          
192             {
193 9         20 my $months = floor($self->Months() / $delta);
194 9         19 my $seconds = floor($self->Seconds() / $delta);
195              
196 9         36 return ref($self)->new([0, $months,0,0,0,$seconds]);
197             }
198             elsif($delta->isa('Date::Handler::Delta'))
199             {
200 0 0 0     0 croak "Cannot divide a delta expressed in months and seconds." if($self->Months() && $self->Seconds());
201 0 0 0     0 croak "Cannot divide a delta expressed in months and seconds." if($delta->Months() && $delta->Seconds());
202              
203 0 0 0     0 croak "You can only divide by a delta expressed in the same unit." if($self->Months() && $delta->Seconds());
204 0 0 0     0 croak "You can only divide by a delta expressed in the same unit." if($self->Seconds() && $delta->Months());
205              
206 0 0       0 if($self->Months())
207             {
208 0         0 my $recurrence = $self->Months() / $delta->Months();
209 0         0 return $recurrence;
210             }
211             else
212             {
213 0 0       0 if($delta->Seconds())
214             {
215 0         0 my $recurrence = $self->Seconds() / $delta->Seconds();
216 0         0 return $recurrence;
217             }
218             else
219             {
220 0         0 return (0 / $delta->Months());
221             }
222             }
223             }
224             elsif($delta->isa('Date::Handler'))
225             {
226 0         0 croak "Cannot divide a date and a delta.";
227             }
228             else
229             {
230 0         0 my $months = floor($self->Months() / $delta);
231 0         0 my $seconds = floor($self->Seconds() / $delta);
232              
233 0         0 return ref($self)->new([0, $months,0,0,0,$seconds]);
234             }
235             }
236              
237             sub ApproximateInSeconds
238             {
239 0     0 0 0 my $self = shift;
240 0         0 my $direction = shift;
241              
242 0 0       0 if($direction eq 'over')
    0          
243             {
244 0         0 my $years = floor($self->Months() / 12);
245 0         0 return $self->Seconds() + (24 * 60 * 60 * (($years * 366) + ($self->Months() % 12) * 31));
246             }
247             elsif($direction eq 'under')
248             {
249 0         0 my $years = floor($self->Months() / 12);
250 0         0 my $months = $self->Months() % 12;
251 0         0 my $months_as_days = 0;
252              
253 0 0       0 if($months)
254             {
255 0         0 $months--;
256 0         0 $months_as_days += 28;
257 0         0 $months_as_days += $months * 30;
258             }
259              
260 0         0 return $self->Seconds() + (24 * 60 * 60 * ( ($years * 365) + ($months_as_days) ) );
261             }
262             else
263             {
264 0         0 croak "Allowed argument for ApproximateInSeconds is 'over','under','average'";
265             }
266             }
267              
268             sub Incr
269             {
270 0     0 0 0 my $self = shift;
271              
272 0         0 my $secs = $self->Seconds();
273              
274 0         0 return ref($self)->new([0, $self->Months(),0,0,0,$secs++]);
275             }
276              
277             sub Neg
278             {
279 53     53 0 86 my $self = shift;
280              
281 53         128 return ref($self)->new([0, -$self->Months(),0,0,0,-$self->Seconds()]);
282             }
283              
284              
285             #Useful methods.
286              
287             #Taken from Class::Date
288             sub DeltaFromArray
289             {
290 364     364 0 3159 my $self = shift;
291 364         388 my $input = shift;
292 364         458 my ($y,$m,$d,$hh,$mm,$ss) = @{$input}[0,1,2,3,4,5];
  364         700  
293              
294 364 50       712 $y = 0 unless (defined $y);
295 364         1046 $y = floor($y * 12);
296 364         494 $m += $y;
297 364   100     4514 return [$m||0,($ss||0)+60*(($mm||0)+60*(($hh||0)+24*($d||0)))];
      100        
      100        
      100        
      100        
298             }
299              
300              
301             666;
302             __END__