File Coverage

blib/lib/Date/Calc/Object.pm
Criterion Covered Total %
statement 635 883 71.9
branch 356 526 67.6
condition 167 342 48.8
subroutine 56 66 84.8
pod 0 40 0.0
total 1214 1857 65.3


line stmt bran cond sub pod time code
1              
2             ###############################################################################
3             ## ##
4             ## Copyright (c) 2000 - 2015 by Steffen Beyer. ##
5             ## All rights reserved. ##
6             ## ##
7             ## This package is free software; you can redistribute it ##
8             ## and/or modify it under the same terms as Perl itself. ##
9             ## ##
10             ###############################################################################
11              
12             ###############################################################################
13             ## ##
14             ## Mottos of this module: ##
15             ## ##
16             ## 1) Small is beautiful. ##
17             ## ##
18             ## 2) Make frequent things easy and infrequent or hard things possible. ##
19             ## ##
20             ###############################################################################
21              
22             package Date::Calc::Object;
23              
24 15     15   15449 BEGIN { eval { require bytes; }; }
  15         401  
25 15     15   50 use strict;
  15         19  
  15         475  
26 15     15   60 use vars qw(@ISA @AUXILIARY @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
  15         15  
  15         1283  
27              
28 15     15   5279 use Carp::Clan qw(^Date::);
  15         35674  
  15         88  
29              
30             BEGIN # Re-export imports from Date::Calc:
31             {
32 15     15   3371 require Exporter;
33 15         5160 require Date::Calc;
34 15         1055 @ISA = qw(Exporter Date::Calc);
35 15         48 @AUXILIARY = qw(shift_year shift_date shift_time shift_datetime);
36 15         29 @EXPORT = @Date::Calc::EXPORT;
37 15         1472 @EXPORT_OK = (@Date::Calc::EXPORT_OK,@AUXILIARY);
38 15         2402 %EXPORT_TAGS = (all => [@Date::Calc::EXPORT_OK],
39             aux => [@AUXILIARY],
40             ALL => [@EXPORT_OK]);
41 15         37 $VERSION = '6.4';
42 15         14605 Date::Calc->import(@Date::Calc::EXPORT,@Date::Calc::EXPORT_OK);
43             }
44              
45             sub shift_year
46             {
47 1239 100   1239 0 2522 croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
48              
49 1238 100       1811 if (ref($_[0][0]))
50             {
51 195 100       1367 if (ref($_[0][0]) eq 'ARRAY')
    100          
52             {
53 6 100       4 if (@{$_[0][0]} == 3) # otherwise anonymous array is pointless
  6         10  
54             {
55 1         2 return ${shift(@{$_[0]})}[0];
  1         1  
  1         3  
56             }
57             else
58             {
59 5         10 croak("wrong number of elements in date constant");
60             }
61             }
62             elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
63             {
64 188         207 return shift(@{$_[0]})->year();
  188         679  
65             }
66             else
67             {
68 1         2 croak("input parameter is neither ARRAY ref nor object");
69             }
70             }
71             else
72             {
73 1043 100       674 if (@{$_[0]} >= 1)
  1043         1498  
74             {
75 1042         665 return shift(@{$_[0]});
  1042         1902  
76             }
77             else
78             {
79 1         5 croak("not enough input parameters for a year");
80             }
81             }
82             }
83              
84             sub shift_date
85             {
86 23848 100   23848 0 40853 croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
87              
88 23847 100       36716 if (ref($_[0][0]))
89             {
90 48 100       184 if (ref($_[0][0]) eq 'ARRAY')
    100          
91             {
92 34 100       27 if (@{$_[0][0]} == 3)
  34         115  
93             {
94 28         56 return( @{shift(@{$_[0]})} );
  28         28  
  28         87  
95             }
96             else
97             {
98 6         9 croak("wrong number of elements in date constant");
99             }
100             }
101             elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
102             {
103 13         19 return( shift(@{$_[0]})->date() );
  13         57  
104             }
105             else
106             {
107 1         3 croak("input parameter is neither ARRAY ref nor object");
108             }
109             }
110             else
111             {
112 23799 100       15789 if (@{$_[0]} >= 3)
  23799         35915  
113             {
114 23796         16978 return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
  23796         23641  
  23796         21455  
  23796         55671  
115             }
116             else
117             {
118 3         6 croak("not enough input parameters for a date");
119             }
120             }
121             }
122              
123             sub shift_time
124             {
125 20 100   20 0 595 croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
126              
127 19 100       29 if (ref($_[0][0]))
128             {
129 12 100       36 if (ref($_[0][0]) eq 'ARRAY')
    100          
130             {
131 7 100       4 if (@{$_[0][0]} == 3)
  7         12  
132             {
133 1         1 return( @{shift(@{$_[0]})} );
  1         1  
  1         3  
134             }
135             else
136             {
137 6         10 croak("wrong number of elements in time constant");
138             }
139             }
140             elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
141             {
142 4         5 return( (shift(@{$_[0]})->datetime())[3,4,5] );
  4         11  
143             }
144             else
145             {
146 1         3 croak("input parameter is neither ARRAY ref nor object");
147             }
148             }
149             else
150             {
151 7 100       7 if (@{$_[0]} >= 3)
  7         9  
152             {
153 4         2 return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
  4         5  
  4         4  
  4         8  
154             }
155             else
156             {
157 3         7 croak("not enough input parameters for time values");
158             }
159             }
160             }
161              
162             sub shift_datetime
163             {
164 26 100   26 0 906 croak("internal error - parameter is not an ARRAY ref") if (ref($_[0]) ne 'ARRAY');
165              
166 25 100       44 if (ref($_[0][0]))
167             {
168 15 100       38 if (ref($_[0][0]) eq 'ARRAY')
    100          
169             {
170 10 100       5 if (@{$_[0][0]} == 6)
  10         22  
171             {
172 1         2 return( @{shift(@{$_[0]})} );
  1         1  
  1         3  
173             }
174             else
175             {
176 9         13 croak("wrong number of elements in date-time constant");
177             }
178             }
179             elsif (ref($_[0][0]) =~ /[^:]::[^:]/)
180             {
181 4         5 return( shift(@{$_[0]})->datetime() );
  4         11  
182             }
183             else
184             {
185 1         4 croak("input parameter is neither ARRAY ref nor object");
186             }
187             }
188             else
189             {
190 10 100       7 if (@{$_[0]} >= 6)
  10         15  
191             {
192 4         5 return( shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}),
  4         4  
  4         3  
  4         5  
193 4         2 shift(@{$_[0]}), shift(@{$_[0]}), shift(@{$_[0]}) );
  4         3  
  4         15  
194             }
195             else
196             {
197 6         11 croak("not enough input parameters for a date and time");
198             }
199             }
200             }
201              
202             package Date::Calc;
203              
204 15     15   93 use strict;
  15         16  
  15         576  
205              
206 15     15   55 use Carp::Clan qw(^Date::);
  15         20  
  15         237  
207              
208             use overload
209 15         138 '0+' => 'number',
210             '""' => 'string',
211             'bool' => 'is_valid',
212             'neg' => '_unary_minus_',
213             'abs' => 'number',
214             '<=>' => '_compare_date_',
215             'cmp' => '_compare_date_time_',
216             '==' => '_equal_date_',
217             '!=' => '_not_equal_date_',
218             'eq' => '_equal_date_time_',
219             'ne' => '_not_equal_date_time_',
220             '+' => '_plus_',
221             '-' => '_minus_',
222             '+=' => '_plus_equal_',
223             '-=' => '_minus_equal_',
224             '++' => '_increment_',
225             '--' => '_decrement_',
226             'x' => '_times_',
227             'x=' => '_times_equal_',
228             '=' => 'clone',
229             'nomethod' => 'OVERLOAD', # equivalent of AUTOLOAD ;-)
230 15     15   3094 'fallback' => undef;
  15         22  
231              
232             # Report unimplemented overloaded operators:
233              
234             sub OVERLOAD
235             {
236 8     8 0 119 croak("operator '$_[3]' is unimplemented");
237             }
238              
239             # Prevent nearly infinite loops:
240              
241             sub _times_
242             {
243 1     1   77 $_[3] = 'x';
244 1         4 goto &OVERLOAD;
245             }
246              
247             sub _times_equal_
248             {
249 1     1   77 $_[3] = 'x=';
250 1         3 goto &OVERLOAD;
251             }
252              
253             my $ACCURATE_MODE = 1;
254             my $NORMALIZED_MODE = 0; # disabled by default for backward compatibility
255             my $NUMBER_FORMAT = 0;
256             my $DELTA_FORMAT = 0;
257             my $DATE_FORMAT = 0;
258              
259             sub accurate_mode
260             {
261 22     22 0 169 my($flag) = $ACCURATE_MODE;
262              
263 22 50       43 if (@_ > 1)
264             {
265 22   100     57 $ACCURATE_MODE = $_[1] || 0;
266             }
267 22         26 return $flag;
268             }
269              
270             sub normalized_mode
271             {
272 2     2 0 42 my($flag) = $NORMALIZED_MODE;
273              
274 2 50       8 if (@_ > 1)
275             {
276 2   50     6 $NORMALIZED_MODE = $_[1] || 0;
277             }
278 2         4 return $flag;
279             }
280              
281             sub number_format
282             {
283 0     0 0 0 my($flag) = $NUMBER_FORMAT;
284              
285 0 0       0 if (@_ > 1)
286             {
287 0   0     0 $NUMBER_FORMAT = $_[1] || 0;
288             }
289 0         0 return $flag;
290             }
291              
292             sub delta_format
293             {
294 8     8 0 57 my($self) = shift;
295 8         13 my($flag);
296              
297 8 100       18 if (ref $self) # object method
298             {
299 4 50       68 $flag = defined($self->[0][1]) ? $self->[0][1] : undef;
300 4 50       11 if (@_ > 0)
301             {
302 4 50       11 $self->[0][1] = defined($_[0]) ? $_[0] : undef;
303             }
304             }
305             else # class method
306             {
307 4         7 $flag = $DELTA_FORMAT;
308 4 50       11 if (@_ > 0)
309             {
310 4   50     12 $DELTA_FORMAT = $_[0] || 0;
311             }
312             }
313 8         13 return $flag;
314             }
315              
316             sub date_format
317             {
318 13     13 0 588 my($self) = shift;
319 13         16 my($flag);
320              
321 13 100       31 if (ref $self) # object method
322             {
323 6 50       15 $flag = defined($self->[0][2]) ? $self->[0][2] : undef;
324 6 50       37 if (@_ > 0)
325             {
326 6 50       21 $self->[0][2] = defined($_[0]) ? $_[0] : undef;
327             }
328             }
329             else # class method
330             {
331 7         11 $flag = $DATE_FORMAT;
332 7 50       20 if (@_ > 0)
333             {
334 7   50     63 $DATE_FORMAT = $_[0] || 0;
335             }
336             }
337 13         23 return $flag;
338             }
339              
340             sub language
341             {
342 14     14 0 103 my($self) = shift;
343 14         10 my($lang,$temp);
344              
345             eval
346 14         14 {
347 14 100       29 if (ref $self) # object method
348             {
349 9 100       86 $lang = defined($self->[0][3]) ? Language_to_Text($self->[0][3]) : undef;
350 8 100       16 if (@_ > 0)
351             {
352 5 50       33 if (defined $_[0])
353             {
354 5         7 $temp = $_[0];
355 5 100       50 if ($temp !~ /^\d+$/)
356 4         15 { $temp = Decode_Language($temp); }
357 5 50 33     21 if ($temp >= 1 and $temp <= Languages())
358 5         15 { $self->[0][3] = $temp; }
359             else
360 0         0 { croak "no such language '$_[0]'"; }
361             }
362 0         0 else { $self->[0][3] = undef; }
363             }
364             }
365             else # class method
366             {
367 5         16 $lang = Language_to_Text(Language());
368 5 100       20 if (@_ > 0)
369             {
370 3         4 $temp = $_[0];
371 3 100       22 if ($temp !~ /^\d+$/)
372 1         4 { $temp = Decode_Language($temp); }
373 3 50 33     23 if ($temp >= 1 and $temp <= Languages())
374 3         6 { Language($temp); }
375             else
376 0         0 { croak "no such language '$_[0]'"; }
377             }
378             }
379             };
380 14 100       148 if ($@)
381             {
382 1         29 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
383 1         8 $@ =~ s!\s+at\s+\S.*\s*$!!;
384 1         5 croak($@);
385             }
386 13         22 return $lang;
387             }
388              
389             sub is_delta
390             {
391 61     61 0 246 my($self) = @_;
392 61         72 my($bool) = undef;
393              
394             eval
395 61         56 {
396 61 100 33     431 if (defined($self->[0]) and
      66        
397             ref($self->[0]) eq 'ARRAY' and
398             defined($self->[0][0]))
399 60 100       125 { $bool = ($self->[0][0] ? 1 : 0); }
400             };
401 61 50       101 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
402 61         92 return $bool;
403             }
404              
405             sub is_date
406             {
407 927     927 0 943 my($self) = @_;
408 927         738 my($bool) = undef;
409              
410             eval
411 927         689 {
412 927 100 33     4572 if (defined($self->[0]) and
      66        
413             ref($self->[0]) eq 'ARRAY' and
414             defined($self->[0][0]))
415 926 100       1376 { $bool = ($self->[0][0] ? 0 : 1); }
416             };
417 927 50       1261 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
418 927         875 return $bool;
419             }
420              
421             sub is_short
422             {
423 0     0 0 0 my($self) = @_;
424 0         0 my($bool) = undef;
425              
426             eval
427 0         0 {
428 0 0       0 if (@{$self} == 4) { $bool = 1; }
  0 0       0  
  0         0  
  0         0  
429 0         0 elsif (@{$self} == 7) { $bool = 0; }
430             };
431 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
432 0         0 return $bool;
433             }
434              
435             sub is_long
436             {
437 518     518 0 654 my($self) = @_;
438 518         398 my($bool) = undef;
439              
440             eval
441 518         362 {
442 518 100       347 if (@{$self} == 7) { $bool = 1; }
  518 50       733  
  205         176  
  313         432  
443 313         253 elsif (@{$self} == 4) { $bool = 0; }
444             };
445 518 50       685 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
446 518         505 return $bool;
447             }
448              
449             sub is_valid
450             {
451 1275     1275 0 1299 my($self) = @_;
452 1275         861 my($bool);
453              
454             $bool = eval
455 1275         1178 {
456 1275 100 33     5488 if (defined($self->[0]) and
  1275   66     10409  
      66        
      66        
      66        
      33        
      100        
      33        
457             ref($self->[0]) eq 'ARRAY' and
458             @{$self->[0]} > 0 and
459             defined($self->[0][0]) and
460             not ref($self->[0][0]) and
461             ($self->[0][0] == 0 or $self->[0][0] == 1) and
462             (@{$self} == 4 or @{$self} == 7))
463             {
464 1272 100       1697 if ($self->[0][0]) # is_delta
465             {
466 421 50 33     3879 return 0 unless
      33        
      33        
      33        
      33        
467             (
468             defined($self->[1]) and not ref($self->[1]) and
469             defined($self->[2]) and not ref($self->[2]) and
470             defined($self->[3]) and not ref($self->[3])
471             );
472 421 100       324 if (@{$self} > 4) # is_long
  421         680  
473             {
474 210 50 33     2079 return 0 unless
      33        
      33        
      33        
      33        
475             (
476             defined($self->[4]) and not ref($self->[4]) and
477             defined($self->[5]) and not ref($self->[5]) and
478             defined($self->[6]) and not ref($self->[6])
479             );
480             }
481 421         481 return 1;
482             }
483             else # is_date
484             {
485 851         1926 return 0 unless
486             (
487             defined($self->[1]) and not ref($self->[1]) and
488             defined($self->[2]) and not ref($self->[2]) and
489             defined($self->[3]) and not ref($self->[3]) and
490 851 100 33     8753 check_date(@{$self}[1..3])
      33        
      33        
      33        
      33        
      66        
491             );
492 848 100       971 if (@{$self} > 4) # is_long
  848         1673  
493             {
494 314         645 return 0 unless
495             (
496             defined($self->[4]) and not ref($self->[4]) and
497             defined($self->[5]) and not ref($self->[5]) and
498             defined($self->[6]) and not ref($self->[6]) and
499 314 50 33     3307 check_time(@{$self}[4..6])
      33        
      33        
      33        
      33        
      33        
500             );
501             }
502 848         1030 return 1;
503             }
504             }
505 3         5 return undef;
506             };
507 1275 50       1916 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
508 1275         2332 return $bool;
509             }
510              
511             sub normalize
512             {
513 13     13 0 75 my($self) = shift;
514 13         10 my($quot);
515              
516 13 50       15 if ($self->is_valid())
517             {
518 13 100       21 if ($self->is_delta())
519             {
520 12 50       20 if ($self->is_long())
521             {
522 12         13 splice( @{$self}, 3, 4, Normalize_DHMS(@{$self}[3..6]) );
  12         15  
  12         30  
523             }
524 12 100       22 unless ($ACCURATE_MODE) # YMD_MODE or N_YMD_MODE
525             {
526 6 100 66     26 if ($self->[2] and ($quot = int($self->[2] / 12)))
527             {
528 4         5 $self->[1] += $quot;
529 4         3 $self->[2] -= $quot * 12;
530             }
531 6 100 33     45 if
    100 66        
      33        
      66        
532             (
533             $self->[2] < 0 and
534             ( $self->[3] > 0 or
535             $self->[4] > 0 or
536             $self->[5] > 0 or
537             $self->[6] > 0 )
538             )
539             {
540 1         2 $self->[1]--;
541 1         2 $self->[2] += 12;
542             }
543             elsif
544             (
545             $self->[2] > 0 and
546             ( $self->[3] < 0 or
547             $self->[4] < 0 or
548             $self->[5] < 0 or
549             $self->[6] < 0 )
550             )
551             {
552 3         4 $self->[1]++;
553 3         3 $self->[2] -= 12;
554             }
555             }
556             }
557             else
558             {
559 1 50       10 carp("normalizing a date is a no-op") if ($^W);
560             }
561             }
562 13         101 return $self;
563             }
564              
565             sub new
566             {
567 538     538 0 2667 my($class,$list,$type,$self);
568              
569 538 50       841 if (@_)
570             {
571 538         494 $class = shift;
572 538 100 100     1080 if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
  29         29  
  509         637  
573             }
574 538 100 100     4422 croak("wrong number of arguments")
      33        
575             unless (defined($list) and
576             (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
577 532 100 100     2360 if (@$list == 1 or @$list == 4 or @$list == 7)
    100 100        
      100        
578             {
579 416 100       562 $type = (shift(@$list) ? 1 : 0);
580 416         818 $self = [ [$type], @$list ];
581             }
582             elsif (@$list == 3 or @$list == 6)
583             {
584 72         168 $self = [ [0], @$list ];
585             }
586             else
587             {
588 44         62 $self = [ [] ];
589             }
590 532   50     1800 bless($self, ref($class) || $class || 'Date::Calc');
591 532         1107 return $self;
592             }
593              
594             sub clone
595             {
596 18     18 0 290 my($self) = @_;
597 18         12 my($this);
598              
599 18 50       35 croak("invalid date/time") unless ($self->is_valid());
600 18         29 $this = $self->new();
601 18         12 @{$this} = @{$self};
  18         51  
  18         21  
602 18         28 $this->[0] = [];
603 18         18 @{$this->[0]} = @{$self->[0]};
  18         28  
  18         23  
604 18         30 return $this;
605             }
606              
607             sub copy
608             {
609 2     2 0 11 my($self) = shift;
610 2         1 my($this);
611              
612             eval
613 2         3 {
614 2 50 33     8 if (@_ == 1 and ref($_[0])) { $this = $_[0]; } else { $this = \@_; }
  2         2  
  0         0  
615 2         2 @{$self} = @{$this};
  2         6  
  2         3  
616 2         3 $self->[0] = [];
617 2 50       5 if (defined $this->[0])
618             {
619 2 50       4 if (ref($this->[0]) eq 'ARRAY') { @{$self->[0]} = @{$this->[0]}; }
  2         2  
  2         3  
  2         3  
620 0         0 else { $self->[0][0] = $this->[0]; }
621             }
622             };
623 2 50       6 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
624 2 50       3 croak("invalid date/time") unless ($self->is_valid());
625 2         3 return $self;
626             }
627              
628             sub date
629             {
630 42     42 0 87 my($self,$list);
631              
632 42 50       95 if (@_)
633             {
634 42         44 $self = shift;
635 42 50 33     122 if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
  0         0  
  42         67  
636             }
637 42 50 33     271 croak("wrong number of arguments")
      33        
638             unless (defined($list) and
639             (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
640             eval
641 42         55 {
642 42 100 33     277 if (@$list == 1 or @$list == 4 or @$list == 7)
      66        
643             {
644 5 50       23 $self->[0][0] = (shift(@$list) ? 1 : 0);
645             }
646 42 100 66     167 if (@$list == 3 or @$list == 6)
647             {
648 5         7 splice( @{$self}, 1, scalar(@$list), @$list );
  5         33  
649             }
650             };
651 42 50       80 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
652 42 50       111 croak("invalid date/time") unless ($self->is_valid());
653 42         62 return (@{$self}[1..3]);
  42         180  
654             }
655              
656             sub time
657             {
658 15     15 0 17 my($self,$list);
659              
660 15 50       24 if (@_)
661             {
662 15         18 $self = shift;
663 15 50 33     30 if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
  0         0  
  15         17  
664             }
665 15 50 33     59 croak("wrong number of arguments")
      33        
666             unless (defined($list) and
667             (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4));
668             eval
669 15         14 {
670 15 50 33     52 if (@$list == 1 or @$list == 4)
671             {
672 0 0       0 $self->[0][0] = (shift(@$list) ? 1 : 0);
673             }
674 15 100       29 if (@$list == 3)
675             {
676 1         2 splice( @{$self}, 4, 3, @$list );
  1         3  
677             }
678             };
679 15 50       19 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
680 15 50       23 croak("invalid date/time") unless ($self->is_valid());
681 15 100       12 if (@{$self} == 7) { return (@{$self}[4..6]); }
  15         37  
  14         11  
  14         98  
682 1         34 else { return (); }
683             }
684              
685             sub datetime
686             {
687 13     13 0 16 my($self,$list);
688              
689 13 50       27 if (@_)
690             {
691 13         19 $self = shift;
692 13 50 33     39 if (@_ == 1 and ref($_[0]) eq 'ARRAY') { $list = $_[0]; } else { $list = \@_; }
  0         0  
  13         24  
693             }
694 13 0 0     57 croak("wrong number of arguments")
      33        
695             unless (defined($list) and
696             (@$list == 0 or @$list == 1 or @$list == 3 or @$list == 4 or @$list == 6 or @$list == 7));
697             eval
698 13         14 {
699 13 50 33     94 if (@$list == 1 or @$list == 4 or @$list == 7)
      33        
700             {
701 0 0       0 $self->[0][0] = (shift(@$list) ? 1 : 0);
702             }
703 13 50       49 if (@$list == 3)
    50          
704             {
705 0         0 splice( @{$self}, 1, 6, @$list, 0,0,0 );
  0         0  
706             }
707             elsif (@$list == 6)
708             {
709 0         0 splice( @{$self}, 1, 6, @$list );
  0         0  
710             }
711             };
712 13 50       24 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
713 13 50       22 croak("invalid date/time") unless ($self->is_valid());
714 13 100       14 if (@{$self} == 7) { return (@{$self}[1..6]); }
  13         31  
  8         9  
  8         40  
715 5         6 else { return (@{$self}[1..3],0,0,0); }
  5         21  
716             }
717              
718             sub today
719             {
720 0     0 0 0 my($self) = shift;
721 0   0     0 my($gmt) = shift || 0;
722              
723 0 0       0 if (ref $self) # object method
724             {
725 0         0 $self->date( 0, Today($gmt) );
726 0         0 return $self;
727             }
728             else # class method
729             {
730 0   0     0 $self ||= 'Date::Calc';
731 0         0 return $self->new( 0, Today($gmt) );
732             }
733             }
734              
735             sub now
736             {
737 0     0 0 0 my($self) = shift;
738 0   0     0 my($gmt) = shift || 0;
739              
740 0 0       0 if (ref $self) # object method
741             {
742 0         0 $self->time( 0, Now($gmt) );
743 0         0 return $self;
744             }
745             else # class method
746             {
747 0   0     0 $self ||= 'Date::Calc';
748 0         0 return $self->new( 0, Today_and_Now($gmt) );
749             }
750             }
751              
752             sub today_and_now
753             {
754 0     0 0 0 my($self) = shift;
755 0   0     0 my($gmt) = shift || 0;
756              
757 0 0       0 if (ref $self) # object method
758             {
759 0         0 $self->date( 0, Today_and_Now($gmt) );
760 0         0 return $self;
761             }
762             else # class method
763             {
764 0   0     0 $self ||= 'Date::Calc';
765 0         0 return $self->new( 0, Today_and_Now($gmt) );
766             }
767             }
768              
769             sub gmtime
770             {
771 1     1 0 13 my($self) = shift;
772 1         2 my(@date);
773              
774             eval
775 1         2 {
776 1         6 @date = (Gmtime(@_))[0..5];
777             };
778 1 50       4 if ($@)
779             {
780 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
781 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
782 0         0 croak($@);
783             }
784 1 50       10 if (ref $self) # object method
785             {
786 1         5 $self->date( 0, @date );
787 1         4 return $self;
788             }
789             else # class method
790             {
791 0   0     0 $self ||= 'Date::Calc';
792 0         0 return $self->new( 0, @date );
793             }
794             }
795              
796             sub localtime
797             {
798 1     1 0 14 my($self) = shift;
799 1         2 my(@date);
800              
801             eval
802 1         2 {
803 1         6 @date = (Localtime(@_))[0..5];
804             };
805 1 50       9 if ($@)
806             {
807 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
808 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
809 0         0 croak($@);
810             }
811 1 50       4 if (ref $self) # object method
812             {
813 1         6 $self->date( 0, @date );
814 1         4 return $self;
815             }
816             else # class method
817             {
818 0   0     0 $self ||= 'Date::Calc';
819 0         0 return $self->new( 0, @date );
820             }
821             }
822              
823             sub mktime
824             {
825 1     1 0 15 my($self) = @_;
826 1         2 my($time);
827              
828 1 50       4 if (ref $self) # object method
829             {
830 1 50       4 croak("invalid date/time") unless ($self->is_valid());
831 1 50       4 croak("can't mktime from a delta vector") if ($self->is_delta()); # add [1970,1,1,0,0,0] first!
832             eval
833 1         2 {
834 1         4 $time = Mktime( $self->datetime() );
835             };
836 1 50       4 if ($@)
837             {
838 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
839 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
840 0         0 croak($@);
841             }
842 1         3 return $time;
843             }
844             else # class method
845             {
846 0         0 return CORE::time();
847             }
848             }
849              
850             sub tzoffset
851             {
852 0     0 0 0 my($self) = shift;
853 0         0 my(@diff);
854              
855             eval
856 0         0 {
857 0         0 @diff = (Timezone(@_))[0..5];
858             };
859 0 0       0 if ($@)
860             {
861 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
862 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
863 0         0 croak($@);
864             }
865 0 0       0 if (ref $self) # object method
866             {
867 0         0 $self->date( 1, @diff );
868 0         0 return $self;
869             }
870             else # class method
871             {
872 0   0     0 $self ||= 'Date::Calc';
873 0         0 return $self->new( 1, @diff );
874             }
875             }
876              
877             sub date2time
878             {
879 3     3 0 34 my($self) = @_;
880 3         4 my($time);
881              
882 3 50       9 if (ref $self) # object method
883             {
884 3 50       9 croak("invalid date/time") unless ($self->is_valid());
885 3 50       10 croak("can't make time from a delta vector") if ($self->is_delta()); # add [1970,1,1,0,0,0] first!
886             eval
887 3         6 {
888 3         10 $time = Date_to_Time( $self->datetime() );
889             };
890 3 50       10 if ($@)
891             {
892 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
893 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
894 0         0 croak($@);
895             }
896 3         14 return $time;
897             }
898             else # class method
899             {
900 0         0 return CORE::time();
901             }
902             }
903              
904             sub time2date
905             {
906 4     4 0 179 my($self) = shift;
907 4         7 my(@date);
908              
909             eval
910 4         6 {
911 4         18 @date = Time_to_Date(@_);
912             };
913 4 50       14 if ($@)
914             {
915 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
916 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
917 0         0 croak($@);
918             }
919 4 100       22 if (ref $self) # object method
920             {
921 3         14 $self->date( 0, @date );
922 3         9 return $self;
923             }
924             else # class method
925             {
926 1   50     9 $self ||= 'Date::Calc';
927 1         6 return $self->new( 0, @date );
928             }
929             }
930              
931             sub year
932             {
933 24     24 0 110 my($self) = shift;
934              
935 24 50       56 if (@_ > 0)
936             {
937 0   0     0 eval { $self->[1] = $_[0] || 0; };
  0         0  
938 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
939             }
940 24 50       59 croak("invalid date/time") unless ($self->is_valid());
941 24         53 return $self->[1];
942             }
943              
944             sub month
945             {
946 9     9 0 59 my($self) = shift;
947              
948 9 50       21 if (@_ > 0)
949             {
950 0   0     0 eval { $self->[2] = $_[0] || 0; };
  0         0  
951 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
952             }
953 9 50       12 croak("invalid date/time") unless ($self->is_valid());
954 9         19 return $self->[2];
955             }
956              
957             sub day
958             {
959 10     10 0 120 my($self) = shift;
960              
961 10 100       21 if (@_ > 0)
962             {
963 1   50     2 eval { $self->[3] = $_[0] || 0; };
  1         6  
964 1 50       3 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
965             }
966 10 50       18 croak("invalid date/time") unless ($self->is_valid());
967 10         20 return $self->[3];
968             }
969              
970             sub hours
971             {
972 9     9 0 61 my($self) = shift;
973              
974 9 50       18 if (@_ > 0)
975             {
976             eval
977 0         0 {
978 0 0       0 if (@{$self} == 4)
  0         0  
979             {
980 0         0 $self->[4] = 0;
981 0         0 $self->[5] = 0;
982 0         0 $self->[6] = 0;
983             }
984 0 0       0 if (@{$self} == 7)
  0         0  
985             {
986 0   0     0 $self->[4] = $_[0] || 0;
987             }
988             };
989 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
990             }
991 9 50       10 croak("invalid date/time") unless ($self->is_valid());
992 9 100       4 if (@{$self} == 7) { return $self->[4]; }
  9         16  
  4         8  
993 5         7 else { return undef; }
994             }
995              
996             sub minutes
997             {
998 9     9 0 53 my($self) = shift;
999              
1000 9 50       16 if (@_ > 0)
1001             {
1002             eval
1003 0         0 {
1004 0 0       0 if (@{$self} == 4)
  0         0  
1005             {
1006 0         0 $self->[4] = 0;
1007 0         0 $self->[5] = 0;
1008 0         0 $self->[6] = 0;
1009             }
1010 0 0       0 if (@{$self} == 7)
  0         0  
1011             {
1012 0   0     0 $self->[5] = $_[0] || 0;
1013             }
1014             };
1015 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
1016             }
1017 9 50       12 croak("invalid date/time") unless ($self->is_valid());
1018 9 100       5 if (@{$self} == 7) { return $self->[5]; }
  9         17  
  4         33  
1019 5         6 else { return undef; }
1020             }
1021              
1022             sub seconds
1023             {
1024 9     9 0 54 my($self) = shift;
1025              
1026 9 50       24 if (@_ > 0)
1027             {
1028             eval
1029 0         0 {
1030 0 0       0 if (@{$self} == 4)
  0         0  
1031             {
1032 0         0 $self->[4] = 0;
1033 0         0 $self->[5] = 0;
1034 0         0 $self->[6] = 0;
1035             }
1036 0 0       0 if (@{$self} == 7)
  0         0  
1037             {
1038 0   0     0 $self->[6] = $_[0] || 0;
1039             }
1040             };
1041 0 0       0 if ($@) { $@ =~ s!\s+at\s+\S.*\s*$!!; croak($@); }
  0         0  
  0         0  
1042             }
1043 9 50       13 croak("invalid date/time") unless ($self->is_valid());
1044 9 100       9 if (@{$self} == 7) { return $self->[6]; }
  9         26  
  4         7  
1045 5         8 else { return undef; }
1046             }
1047              
1048             ###############################
1049             ## ##
1050             ## Selector constants ##
1051             ## for formatting ##
1052             ## callback functions: ##
1053             ## ##
1054             ###############################
1055             ## ##
1056             ## IS_SHORT = 0x00; ##
1057             ## IS_LONG = 0x01; ##
1058             ## IS_DATE = 0x00; ##
1059             ## IS_DELTA = 0x02; ##
1060             ## TO_NUMBER = 0x00; ##
1061             ## TO_STRING = 0x04; ##
1062             ## ##
1063             ###############################
1064              
1065             sub number
1066             {
1067 40     40 0 227 my($self,$format) = @_;
1068 40         30 my($number,$sign,@temp);
1069              
1070 40 50       55 if ($self->is_valid())
1071             {
1072             eval
1073 40         34 {
1074 40 100       68 $format = $NUMBER_FORMAT unless (defined $format); # because of overloading!
1075 40 100       71 if ($self->[0][0]) # is_delta
1076             {
1077             # carp("returning a fictitious number of days for delta vector")
1078             # if ((($self->[1] != 0) or ($self->[2] != 0)) and $^W);
1079 26 100       16 if (@{$self} == 4) # is_short
  26         37  
1080             {
1081 24 50       32 if (ref($format) eq 'CODE')
1082             {
1083 0         0 $number = &{$format}( $self, 0x02 ); # = TO_NUMBER | IS_DELTA | IS_SHORT
  0         0  
1084             }
1085             else
1086             {
1087 24         51 $number = ($self->[1]*12+$self->[2])*31+$self->[3];
1088             }
1089             }
1090             else # is_long
1091             {
1092 2 50       6 if (ref($format) eq 'CODE')
    50          
1093             {
1094 0         0 $number = &{$format}( $self, 0x03 ); # = TO_NUMBER | IS_DELTA | IS_LONG
  0         0  
1095             }
1096             elsif ($format == 2)
1097             {
1098 0         0 $number = ($self->[1]*12+$self->[2])*31+$self->[3] +
1099             ((($self->[4]*60+$self->[5])*60+$self->[6])/86400);
1100             }
1101             else
1102             {
1103 2         2 local($_);
1104 2         2 $sign = 0;
1105 2         6 @temp = @{$self}[3..6];
  2         4  
1106 2         4 $temp[0] += ($self->[1] * 12 + $self->[2]) * 31;
1107 2 100       6 @temp = map( $_ < 0 ? $sign = -$_ : $_, Normalize_DHMS(@temp) );
1108 2 100       12 $number = sprintf( "%s%d.%02d%02d%02d", $sign ? '-' : '', @temp );
1109             }
1110             }
1111             }
1112             else # is_date
1113             {
1114 14 100       15 if (@{$self} == 4) # is_short
  14         30  
1115             {
1116 8 50 33     35 if (ref($format) eq 'CODE')
    50          
1117             {
1118 0         0 $number = &{$format}( $self, 0x00 ); # = TO_NUMBER | IS_DATE | IS_SHORT
  0         0  
1119             }
1120             elsif ($format == 2 or $format == 1)
1121             {
1122 0         0 $number = Date_to_Days( @{$self}[1..3] );
  0         0  
1123             }
1124             else
1125             {
1126 8         21 $number = sprintf( "%04d%02d%02d",
1127 8         8 @{$self}[1..3] );
1128             }
1129             }
1130             else # is_long
1131             {
1132 6 50       24 if (ref($format) eq 'CODE')
    50          
    50          
1133             {
1134 0         0 $number = &{$format}( $self, 0x01 ); # = TO_NUMBER | IS_DATE | IS_LONG
  0         0  
1135             }
1136             elsif ($format == 2)
1137             {
1138 0         0 $number = Date_to_Days( @{$self}[1..3] ) +
  0         0  
1139             ((($self->[4]*60+$self->[5])*60+$self->[6])/86400);
1140             }
1141             elsif ($format == 1)
1142             {
1143 0         0 $number = Date_to_Days( @{$self}[1..3] ) .
  0         0  
1144 0         0 sprintf( ".%02d%02d%02d", @{$self}[4..6] );
1145             }
1146             else
1147             {
1148 6         36 $number = sprintf( "%04d%02d%02d.%02d%02d%02d",
1149 6         12 @{$self}[1..6] );
1150             }
1151             }
1152             }
1153             };
1154 40 50       65 if ($@)
1155             {
1156 0         0 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
1157 0         0 $@ =~ s!\s+at\s+\S.*\s*$!!;
1158 0         0 croak($@);
1159             }
1160 40         91 return $number;
1161             }
1162 0         0 return undef;
1163             }
1164              
1165             sub string
1166             {
1167 142     142 0 865 my($self,$format,$lang) = @_;
1168 142         104 my($restore,$string);
1169              
1170 142 50       230 if ($self->is_valid())
1171             {
1172 142 100 66     422 if (defined($lang) and $lang ne '') # because of overloading!
1173             {
1174 4 50       24 $lang = Decode_Language($lang) unless ($lang =~ /^\d+$/);
1175             }
1176             else
1177             {
1178 138 100       215 if (defined $self->[0][3]) { $lang = $self->[0][3]; }
  10         16  
1179 128         248 else { $lang = Language(); }
1180             }
1181 142 100 66     539 croak "no such language '$lang'" unless ($lang >= 1 and $lang <= Languages());
1182             eval
1183 141         129 {
1184 141 100       216 if ($self->[0][0]) # is_delta
1185             {
1186 40 100       90 $format = defined($self->[0][1]) ? $self->[0][1] : $DELTA_FORMAT
    50          
1187             unless (defined $format); # because of overloading!
1188 40 100       34 if (@{$self} == 4) # is_short
  40         65  
1189             {
1190 20 50       71 if (ref($format) eq 'CODE')
    50          
    50          
    50          
    50          
1191             {
1192 0         0 $string = &{$format}( $self, 0x06, $lang ); # = TO_STRING | IS_DELTA | IS_SHORT
  0         0  
1193             }
1194             elsif ($format == 4)
1195             {
1196 0         0 $string = '(' . join(',', @{$self}[1..3]) . ')';
  0         0  
1197             }
1198             elsif ($format == 3)
1199             {
1200 0         0 $string = sprintf( "%+d Y %+d M %+d D",
1201 0         0 @{$self}[1..3] );
1202             }
1203             elsif ($format == 2)
1204             {
1205 0         0 $string = sprintf( "%+dY %+dM %+dD",
1206 0         0 @{$self}[1..3] );
1207             }
1208             elsif ($format == 1)
1209             {
1210 20         72 $string = sprintf( "%+d %+d %+d",
1211 20         21 @{$self}[1..3] );
1212             }
1213             else
1214             {
1215 0         0 $string = sprintf( "%+d%+d%+d",
1216 0         0 @{$self}[1..3] );
1217             }
1218             }
1219             else # is_long
1220             {
1221 20 100       58 if (ref($format) eq 'CODE')
    50          
    50          
    50          
    100          
1222             {
1223 3         8 $string = &{$format}( $self, 0x07, $lang ); # = TO_STRING | IS_DELTA | IS_LONG
  3         8  
1224             }
1225             elsif ($format == 4)
1226             {
1227 0         0 $string = '(' . join(',', @{$self}[1..6]) . ')';
  0         0  
1228             }
1229             elsif ($format == 3)
1230             {
1231 0         0 $string = sprintf( "%+d Y %+d M %+d D %+d h %+d m %+d s",
1232 0         0 @{$self}[1..6] );
1233             }
1234             elsif ($format == 2)
1235             {
1236 0         0 $string = sprintf( "%+dY %+dM %+dD %+dh %+dm %+ds",
1237 0         0 @{$self}[1..6] );
1238             }
1239             elsif ($format == 1)
1240             {
1241 16         52 $string = sprintf( "%+d %+d %+d %+d %+d %+d",
1242 16         16 @{$self}[1..6] );
1243             }
1244             else
1245             {
1246 1         6 $string = sprintf( "%+d%+d%+d%+d%+d%+d",
1247 1         2 @{$self}[1..6] );
1248             }
1249             }
1250             }
1251             else # is_date
1252             {
1253 101 100       243 $format = defined($self->[0][2]) ? $self->[0][2] : $DATE_FORMAT
    100          
1254             unless (defined $format); # because of overloading!
1255 101 100       77 if (@{$self} == 4) # is_short
  101         159  
1256             {
1257 88 100       255 if (ref($format) eq 'CODE')
    50          
    100          
    100          
    50          
1258             {
1259 5         8 $string = &{$format}( $self, 0x04, $lang ); # = TO_STRING | IS_DATE | IS_SHORT
  5         9  
1260             }
1261             elsif ($format == 4)
1262             {
1263 0         0 $string = '[' . join(',', @{$self}[1..3]) . ']';
  0         0  
1264             }
1265             elsif ($format == 3)
1266             {
1267 15         15 $string = Date_to_Text_Long( @{$self}[1..3], $lang );
  15         37  
1268             }
1269             elsif ($format == 2)
1270             {
1271 1         3 $string = Date_to_Text( @{$self}[1..3], $lang );
  1         4  
1272             }
1273             elsif ($format == 1)
1274             {
1275 67         140 $string = sprintf( "%02d-%.3s-%04d",
1276             $self->[3],
1277             Month_to_Text($self->[2],$lang),
1278             $self->[1] );
1279             }
1280             else
1281             {
1282 0         0 $string = sprintf( "%04d%02d%02d",
1283 0         0 @{$self}[1..3] );
1284             }
1285             }
1286             else # is_long
1287             {
1288 13 100       55 if (ref($format) eq 'CODE')
    50          
    100          
    50          
    50          
1289             {
1290 6         6 $string = &{$format}( $self, 0x05, $lang ); # = TO_STRING | IS_DATE | IS_LONG
  6         12  
1291             }
1292             elsif ($format == 4)
1293             {
1294 0         0 $string = '[' . join(',', @{$self}[1..6]) . ']';
  0         0  
1295             }
1296             elsif ($format == 3)
1297             {
1298 3         13 $string = Date_to_Text_Long( @{$self}[1..3], $lang ) .
  3         18  
1299 3         6 sprintf( " %02d:%02d:%02d", @{$self}[4..6] );
1300             }
1301             elsif ($format == 2)
1302             {
1303 0         0 $string = Date_to_Text( @{$self}[1..3], $lang ) .
  0         0  
1304 0         0 sprintf( " %02d:%02d:%02d", @{$self}[4..6] );
1305             }
1306             elsif ($format == 1)
1307             {
1308 4         16 $string = sprintf( "%02d-%.3s-%04d %02d:%02d:%02d",
1309             $self->[3],
1310             Month_to_Text($self->[2],$lang),
1311             $self->[1],
1312 4         11 @{$self}[4..6] );
1313             }
1314             else
1315             {
1316 0         0 $string = sprintf( "%04d%02d%02d%02d%02d%02d",
1317 0         0 @{$self}[1..6] );
1318             }
1319             }
1320             }
1321             };
1322 141 100       300 if ($@)
1323             {
1324 1         3 $@ =~ s!^.*[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s*!!;
1325 1         6 $@ =~ s!\s+at\s+\S.*\s*$!!;
1326 1         3 croak($@);
1327             }
1328 140         433 return $string;
1329             }
1330 0         0 return undef;
1331             }
1332              
1333             sub _process_
1334             {
1335 451     451   476 my($self,$this,$flag,$code) = @_;
1336 451         339 my($result,$val1,$val2,$len1,$len2,$last,$item);
1337              
1338 451 50       609 croak("invalid date/time") unless ($self->is_valid());
1339 451 50       733 if ($code == 0)
1340             {
1341 0 0       0 croak("can't apply unary minus to a date")
1342             unless ($self->is_delta());
1343 0         0 $result = $self->new();
1344 0         0 $result->[0][0] = $self->[0][0];
1345 0         0 for ( $item = 1; $item < @{$self}; $item++ )
  0         0  
1346             {
1347 0         0 $result->[$item] = -$self->[$item];
1348             }
1349 0         0 return $result;
1350             }
1351 451 100 66     2732 if (defined $this and ref($this) =~ /[^:]::[^:]/)
    100 66        
    50 33        
1352             {
1353 368 50       550 croak("invalid date/time") unless ($this->is_valid());
1354             }
1355             elsif (defined $this and ref($this) eq 'ARRAY')
1356             {
1357 55 100 100     50 if (@{$this} == 3 or @{$this} == 6)
  55         353  
  12         33  
1358             {
1359 49 100       102 if ($code == 6)
    100          
1360             {
1361 2         3 $this = $self->new(0,@{$this});
  2         6  
1362             }
1363             elsif ($code == 5)
1364             {
1365 16         30 $this = $self->new($self->is_date(),@{$this});
  16         39  
1366             }
1367             else
1368             {
1369 31         72 $this = $self->new($self->is_delta(),@{$this});
  31         79  
1370             }
1371             }
1372             else
1373             {
1374 6         5 $this = $self->new(@{$this});
  6         19  
1375             }
1376 55 100       110 croak("invalid date/time") unless ($this->is_valid());
1377             }
1378             elsif (defined $this and not ref($this))
1379             {
1380 28   50     69 $this = $self->new(1,0,0,$this || 0);
1381 28 50       37 croak("invalid date/time") unless ($this->is_valid());
1382             }
1383 0         0 else { croak("illegal operand type"); }
1384 449         846 $val1 = $self->is_date();
1385 449         592 $val2 = $this->is_date();
1386 449 100 100     1648 if ($code == 6 or $code == 5)
    50 33        
1387             {
1388 242 100       277 if ($code == 6)
1389             {
1390 123 50 66     682 croak("can't subtract a date from a delta vector")
      33        
      100        
      66        
      33        
1391             if ((not $val1 and $val2 and not $flag) or
1392             ($val1 and not $val2 and $flag));
1393             }
1394             else
1395             {
1396 119 100 100     380 croak("can't add two dates")
1397             if ($val1 and $val2);
1398             }
1399 240         396 $len1 = $self->is_long();
1400 240         301 $len2 = $this->is_long();
1401 240 100 100     591 if ($len1 or $len2) { $last = 7; }
  94         74  
1402 146         117 else { $last = 4; }
1403 240 100       284 if (defined $flag) { $result = $self->new((0) x $last); }
  188         425  
1404 52         40 else { $result = $self; }
1405 240 100 66     369 if (not $val1 and not $val2)
1406             {
1407 2         3 $result->[0][0] = 1;
1408 2         9 for ( $item = 1; $item < $last; $item++ )
1409             {
1410 12 100       14 if ($code == 6)
1411             {
1412 6 50       7 if ($flag)
1413             {
1414 0   0     0 $result->[$item] =
      0        
1415             ($this->[$item] || 0) -
1416             ($self->[$item] || 0);
1417             }
1418             else
1419             {
1420 6   50     23 $result->[$item] =
      100        
1421             ($self->[$item] || 0) -
1422             ($this->[$item] || 0);
1423             }
1424             }
1425             else
1426             {
1427 6   50     21 $result->[$item] =
      100        
1428             ($self->[$item] || 0) +
1429             ($this->[$item] || 0);
1430             }
1431             }
1432             }
1433 240         733 return ($result,$this,$val1,$val2,$len1,$len2);
1434             }
1435             elsif ($code <= 4 and $code >= 1)
1436             {
1437 207 50 50     696 croak("can't compare a date and a delta vector")
1438             if ($val1 xor $val2);
1439 207 100       274 if ($code >= 3)
1440             {
1441 204 100       235 if ($code == 4) { $last = 7; }
  165         164  
1442 39         38 else { $last = 4; }
1443 204         143 $result = 1;
1444             ITEM:
1445 204         325 for ( $item = 1; $item < $last; $item++ )
1446             {
1447 1107 50 100     4442 if (($self->[$item] || 0) !=
      100        
1448             ($this->[$item] || 0))
1449 0         0 { $result = 0; last ITEM; }
  0         0  
1450             }
1451 204         492 return $result;
1452             }
1453             else # ($code <= 2)
1454             {
1455             # croak("can't compare two delta vectors")
1456             # if (not $val1 and not $val2);
1457 3 50       8 if ($code == 2)
1458             {
1459 3         10 $len1 = $self->number();
1460 3         8 $len2 = $this->number();
1461             }
1462             else
1463             {
1464 0         0 $len1 = int($self->number());
1465 0         0 $len2 = int($this->number());
1466             }
1467 3 50       9 if ($flag) { return $len2 <=> $len1; }
  0         0  
1468 3         27 else { return $len1 <=> $len2; }
1469             }
1470             }
1471 0         0 else { croak("unexpected internal error; please contact author"); }
1472             }
1473              
1474             sub _unary_minus_
1475             {
1476 0     0   0 my($self,$this,$flag) = @_;
1477              
1478 0         0 return $self->_process_($this,$flag,0);
1479             }
1480              
1481             sub _compare_date_
1482             {
1483 0     0   0 my($self,$this,$flag) = @_;
1484              
1485 0         0 return $self->_process_($this,$flag,1);
1486             }
1487              
1488             sub _compare_date_time_
1489             {
1490 3     3   35 my($self,$this,$flag) = @_;
1491              
1492 3         13 return $self->_process_($this,$flag,2);
1493             }
1494              
1495             sub _equal_date_
1496             {
1497 39     39   542 my($self,$this,$flag) = @_;
1498              
1499 39         81 return $self->_process_($this,$flag,3);
1500             }
1501              
1502             sub _not_equal_date_
1503             {
1504 0     0   0 my($self,$this,$flag) = @_;
1505              
1506 0         0 return $self->_process_($this,$flag,3) ^ 1;
1507             }
1508              
1509             sub _equal_date_time_
1510             {
1511 165     165   936 my($self,$this,$flag) = @_;
1512              
1513 165         238 return $self->_process_($this,$flag,4);
1514             }
1515              
1516             sub _not_equal_date_time_
1517             {
1518 0     0   0 my($self,$this,$flag) = @_;
1519              
1520 0         0 return $self->_process_($this,$flag,4) ^ 1;
1521             }
1522              
1523             sub _date_time_
1524             {
1525 184     184   145 my($self) = @_;
1526              
1527 184 100       114 if (@{$self} == 7) { return (@{$self}[1..6]); }
  184         225  
  175         141  
  175         479  
1528 9         10 else { return (@{$self}[1..3],0,0,0); }
  9         29  
1529             }
1530              
1531             sub _add_
1532             {
1533 138     138   168 my($result,$self,$this,$flag,$val1,$val2,$len1,$len2) = @_;
1534              
1535 138 100       175 if ($val1) # date + delta => date
1536             {
1537 120 100 66     308 if ($len1 or $len2)
1538             {
1539 40 50 33     112 if (not $ACCURATE_MODE and $NORMALIZED_MODE)
1540             {
1541 40         28 splice( @{$result}, 1, 6,
  40         69  
1542             Add_N_Delta_YMDHMS( $self->_date_time_(),
1543             $this->_date_time_() ) );
1544             }
1545             else # ACCURATE_MODE or YMD_MODE
1546             {
1547 0         0 splice( @{$result}, 1, 6,
  0         0  
1548             Add_Delta_YMDHMS( $self->_date_time_(),
1549             $this->_date_time_() ) );
1550             }
1551             }
1552             else # short
1553             {
1554 80 100 100     251 if (not $ACCURATE_MODE and $NORMALIZED_MODE)
1555             {
1556 56         87 splice( @{$result}, 1, 3,
  56         63  
1557 56         37 Add_N_Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
  56         123  
1558             }
1559             else # ACCURATE_MODE or YMD_MODE
1560             {
1561 24         32 splice( @{$result}, 1, 3,
  24         29  
1562 24         22 Add_Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
  24         64  
1563             }
1564             }
1565             }
1566             else # delta + date => date
1567             {
1568 18 100 66     46 if ($len1 or $len2)
1569             {
1570 6 50 66     17 if (not $ACCURATE_MODE and $NORMALIZED_MODE)
1571             {
1572 0         0 splice( @{$result}, 1, 6,
  0         0  
1573             Add_N_Delta_YMDHMS( $this->_date_time_(),
1574             $self->_date_time_() ) );
1575             }
1576             else # ACCURATE_MODE or YMD_MODE
1577             {
1578 6         9 splice( @{$result}, 1, 6,
  6         16  
1579             Add_Delta_YMDHMS( $this->_date_time_(),
1580             $self->_date_time_() ) );
1581             }
1582             }
1583             else # short
1584             {
1585 12 100 66     32 if (not $ACCURATE_MODE and $NORMALIZED_MODE)
1586             {
1587 6         8 splice( @{$result}, 1, 3,
  6         7  
1588 6         6 Add_N_Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
  6         14  
1589             }
1590             else # ACCURATE_MODE or YMD_MODE
1591             {
1592 6         11 splice( @{$result}, 1, 3,
  6         8  
1593 6         5 Add_Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
  6         15  
1594             }
1595             }
1596 18 100 66     63 carp("implicitly changed object type from delta vector to date")
1597             if (not defined $flag and $^W);
1598             }
1599 138         570 $result->[0][0] = 0;
1600             }
1601              
1602             sub _plus_
1603             {
1604 119     119   365 my($self,$this,$flag) = @_;
1605 119         87 my($result,$val1,$val2,$len1,$len2);
1606              
1607 119         200 ($result,$this,$val1,$val2,$len1,$len2) = $self->_process_($this,$flag,5);
1608 117 100 100     286 if ($val1 or $val2)
1609             {
1610 116         206 $result->_add_($self,$this,$flag,$val1,$val2,$len1,$len2);
1611             }
1612 117         286 return $result;
1613             }
1614              
1615             sub _minus_
1616             {
1617 125     125   669 my($self,$this,$flag) = @_;
1618 125         101 my($result,$val1,$val2,$len1,$len2,$temp,$item);
1619              
1620 125         179 ($result,$this,$val1,$val2,$len1,$len2) = $self->_process_($this,$flag,6);
1621 123 100 66     255 if ($val1 or $val2)
1622             {
1623 122 100 66     360 if ($val1 and $val2) # date - date => delta
1624             {
1625 100 100 100     227 if ($len1 or $len2)
1626             {
1627 46 100       59 if ($ACCURATE_MODE)
1628             {
1629 3 50       5 if ($flag)
1630             {
1631 0         0 splice( @{$result}, 1, 6, 0, 0,
  0         0  
1632             Delta_DHMS( $self->_date_time_(),
1633             $this->_date_time_() ) );
1634             }
1635             else
1636             {
1637 3         2 splice( @{$result}, 1, 6, 0, 0,
  3         11  
1638             Delta_DHMS( $this->_date_time_(),
1639             $self->_date_time_() ) );
1640             }
1641             }
1642             else # YMD_MODE or N_YMD_MODE
1643             {
1644 43 100       79 if ($NORMALIZED_MODE) # N_YMD_MODE
1645             {
1646 40 50       47 if ($flag)
1647             {
1648 0         0 splice( @{$result}, 1, 6,
  0         0  
1649             N_Delta_YMDHMS( $self->_date_time_(),
1650             $this->_date_time_() ) );
1651             }
1652             else
1653             {
1654 40         32 splice( @{$result}, 1, 6,
  40         91  
1655             N_Delta_YMDHMS( $this->_date_time_(),
1656             $self->_date_time_() ) );
1657             }
1658             }
1659             else # YMD_MODE
1660             {
1661 3 50       6 if ($flag)
1662             {
1663 0         0 splice( @{$result}, 1, 6,
  0         0  
1664             Delta_YMDHMS( $self->_date_time_(),
1665             $this->_date_time_() ) );
1666             }
1667             else
1668             {
1669 3         4 splice( @{$result}, 1, 6,
  3         9  
1670             Delta_YMDHMS( $this->_date_time_(),
1671             $self->_date_time_() ) );
1672             }
1673             }
1674             }
1675             }
1676             else # short
1677             {
1678 54 100       87 if ($ACCURATE_MODE)
1679             {
1680 10 50       14 if ($flag)
1681             {
1682 0         0 splice( @{$result}, 1, 3, 0, 0,
  0         0  
1683 0         0 Delta_Days( @{$self}[1..3], @{$this}[1..3] ) );
  0         0  
1684             }
1685             else
1686             {
1687 10         19 splice( @{$result}, 1, 3, 0, 0,
  10         10  
1688 10         9 Delta_Days( @{$this}[1..3], @{$self}[1..3] ) );
  10         24  
1689             }
1690             }
1691             else # YMD_MODE or N_YMD_MODE
1692             {
1693 44 100       51 if ($NORMALIZED_MODE) # N_YMD_MODE
1694             {
1695 39 50       50 if ($flag)
1696             {
1697 0         0 splice( @{$result}, 1, 3,
  0         0  
1698 0         0 N_Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
  0         0  
1699             }
1700             else
1701             {
1702 39         61 splice( @{$result}, 1, 3,
  39         42  
1703 39         25 N_Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
  39         95  
1704             }
1705             }
1706             else # YMD_MODE
1707             {
1708 5 50       8 if ($flag)
1709             {
1710 0         0 splice( @{$result}, 1, 3,
  0         0  
1711 0         0 Delta_YMD( @{$self}[1..3], @{$this}[1..3] ) );
  0         0  
1712             }
1713             else
1714             {
1715 5         11 splice( @{$result}, 1, 3,
  5         6  
1716 5         2 Delta_YMD( @{$this}[1..3], @{$self}[1..3] ) );
  5         12  
1717             }
1718             }
1719             }
1720             }
1721 100 100 66     270 carp("implicitly changed object type from date to delta vector")
1722             if (not defined $flag and $^W);
1723 100         308 $result->[0][0] = 1;
1724             }
1725             else # date - delta => date
1726             {
1727 22 50       25 if ($val1)
1728             {
1729 22         29 $temp = $this->new();
1730 22         37 $temp->[0][0] = $this->[0][0];
1731 22         29 for ( $item = 1; $item < @{$this}; $item++ )
  88         140  
1732             {
1733 66         92 $temp->[$item] = -$this->[$item];
1734             }
1735 22         36 $result->_add_($self,$temp,$flag,$val1,$val2,$len1,$len2);
1736             }
1737             else
1738             {
1739 0         0 $temp = $self->new();
1740 0         0 $temp->[0][0] = $self->[0][0];
1741 0         0 for ( $item = 1; $item < @{$self}; $item++ )
  0         0  
1742             {
1743 0         0 $temp->[$item] = -$self->[$item];
1744             }
1745 0         0 $result->_add_($temp,$this,$flag,$val1,$val2,$len1,$len2);
1746             }
1747             }
1748             }
1749 123         298 return $result;
1750             }
1751              
1752             sub _plus_equal_
1753             {
1754 21     21   189 my($self,$this) = @_;
1755              
1756 21         34 return $self->_plus_($this,undef);
1757             }
1758              
1759             sub _minus_equal_
1760             {
1761 18     18   375 my($self,$this) = @_;
1762              
1763 18         93 return $self->_minus_($this,undef);
1764             }
1765              
1766             sub _increment_
1767             {
1768 8     8   44 my($self) = @_;
1769              
1770 8         16 return $self->_plus_(1,undef);
1771             }
1772              
1773             sub _decrement_
1774             {
1775 8     8   47 my($self) = @_;
1776              
1777 8         17 return $self->_minus_(1,undef);
1778             }
1779              
1780             1;
1781              
1782             __END__