File Coverage

lib/Date/Manip/DM6.pm
Criterion Covered Total %
statement 291 467 62.3
branch 149 282 52.8
condition 43 63 68.2
subroutine 22 40 55.0
pod 34 34 100.0
total 539 886 60.8


line stmt bran cond sub pod time code
1             package Date::Manip::DM6;
2             # Copyright (c) 1995-2023 Sullivan Beck. All rights reserved.
3             # This program is free software; you can redistribute it and/or modify it
4             # under the same terms as Perl itself.
5              
6             ###########################################################################
7             ###########################################################################
8              
9             our (@ISA,@EXPORT);
10              
11             require 5.010000;
12             require Exporter;
13             @ISA = qw(Exporter);
14             @EXPORT = qw(
15             DateManipVersion
16             Date_Init
17             ParseDate
18             ParseDateString
19             ParseDateDelta
20             ParseDateFormat
21             ParseRecur
22             Date_IsHoliday
23             Date_IsWorkDay
24             Date_Cmp
25             DateCalc
26             UnixDate
27             Delta_Format
28             Date_GetPrev
29             Date_GetNext
30             Date_SetTime
31             Date_SetDateField
32             Events_List
33             Date_NextWorkDay
34             Date_PrevWorkDay
35             Date_NearestWorkDay
36              
37             Date_DayOfWeek
38             Date_SecsSince1970
39             Date_SecsSince1970GMT
40             Date_DaysSince1BC
41             Date_DayOfYear
42             Date_NthDayOfYear
43             Date_DaysInMonth
44             Date_DaysInYear
45             Date_WeekOfYear
46             Date_LeapYear
47             Date_DaySuffix
48             Date_ConvTZ
49             Date_TimeZone
50             );
51              
52 168     168   975 use strict;
  168         329  
  168         4293  
53 168     168   64786 use integer;
  168         2178  
  168         720  
54 168     168   4310 use warnings;
  168         394  
  168         10409  
55              
56             our $VERSION;
57             $VERSION='6.92';
58              
59             ###########################################################################
60              
61             our ($dmb,$dmt,$date,$delta,$recur,$date2,$dateUT);
62 168     168   126493 use Date::Manip::Date;
  168         518  
  168         6292  
63 168     168   892 use Carp;
  168         351  
  168         747115  
64              
65             $dateUT = new Date::Manip::Date;
66             $dateUT->config('setdate','now,Etc/GMT');
67              
68             $date = new Date::Manip::Date;
69             $date2 = $date->new_date();
70             $delta = $date->new_delta();
71             $recur = $date->new_recur();
72             $dmb = $date->base();
73             $dmt = $date->tz();
74              
75             ########################################################################
76             ########################################################################
77             # THESE ARE THE MAIN ROUTINES
78             ########################################################################
79             ########################################################################
80              
81             sub DateManipVersion {
82 168     168 1 33954 my($flag) = @_;
83 168         1513 return $date->version($flag);
84             }
85              
86             sub Date_Init {
87 23     23 1 1351 my(@args) = @_;
88 23         42 my(@args2);
89              
90 23         60 foreach my $arg (@args) {
91 24 50       225 if ($arg =~ /^(\S+)\s*=\s*(.*)$/) {
92 24         127 push(@args2,$1,$2);
93             } else {
94 0         0 carp "ERROR: invalid Date_Init argument: $arg";
95             }
96             }
97 23         119 $date->config(@args2);
98 23         223 return $date->err();
99             }
100              
101             sub ParseDateString {
102 247     247 1 99202 my($string,@opts) = @_;
103 247 50       504 $string = '' if (! defined($string));
104 247         773 my $err = $date->parse($string,@opts);
105 247 100       545 return '' if ($err);
106 203         598 my $ret = $date->value('local');
107 203         836 return $ret;
108             }
109              
110             sub ParseDateFormat {
111 3     3 1 1988 my($format,$string) = @_;
112 3 50       10 $string = '' if (! defined($string));
113 3         14 my $err = $date->parse_format($format,$string);
114 3 50       6 return '' if ($err);
115 3         15 my $ret = $date->value('local');
116 3         15 return $ret;
117             }
118              
119             sub ParseDate {
120 0     0 1 0 my($arg,@opts) = @_;
121              
122 0 0       0 $arg = '' if (! defined($arg));
123 0         0 my $ref = ref($arg);
124 0         0 my $list = 0;
125              
126 0         0 my @args;
127 0 0       0 if (! $ref) {
    0          
    0          
128 0         0 @args = ($arg);
129             } elsif ($ref eq 'ARRAY') {
130 0         0 @args = @$arg;
131 0         0 $list = 1;
132             } elsif ($ref eq 'SCALAR') {
133 0         0 @args = ($$arg);
134             } else {
135 0         0 print "ERROR: Invalid arguments to ParseDate.\n";
136 0         0 return '';
137             }
138              
139 0         0 while (@args) {
140 0         0 my $string = join(' ',@args);
141 0         0 my $err = $date->parse($string,@opts);
142 0 0       0 if (! $err) {
143 0 0       0 splice(@$arg,0,$#args+1) if ($list);
144 0         0 my $ret = $date->value('local');
145 0         0 return $ret;
146             }
147 0         0 pop(@args);
148             }
149              
150 0         0 return '';
151             }
152              
153             sub ParseDateDelta {
154 33     33 1 14253 my(@a) = @_;
155              
156 33 50 33     153 if (@a < 1 || @a > 2) {
157 0         0 print "ERROR: Invalid number of arguments to ParseDateDelta.\n";
158 0         0 return '';
159             }
160 33         53 my($args,$mode) = @_;
161 33 50       57 $args = '' if (! defined($args));
162 33 100       53 $mode = '' if (! $mode);
163 33         47 $mode = lc($mode);
164 33 50 33     51 if ($mode && ($mode ne 'exact' && $mode ne 'semi' && $mode ne 'approx')) {
      33        
      66        
165 0         0 print "ERROR: Invalid arguments to ParseDateDelta.\n";
166 0         0 return '';
167             }
168              
169 33         35 my @args;
170 33         41 my $ref = ref($args);
171 33         34 my $list = 0;
172              
173 33 50       59 if (! $ref) {
    0          
    0          
174 33         41 @args = ($args);
175             } elsif ($ref eq 'ARRAY') {
176 0         0 @args = @$args;
177 0         0 $list = 1;
178             } elsif ($ref eq 'SCALAR') {
179 0         0 @args = ($$args);
180             } else {
181 0         0 print "ERROR: Invalid arguments to ParseDateDelta.\n";
182 0         0 return '';
183             }
184              
185 33         60 while (@args) {
186 33         53 my $string = join(' ',@args);
187 33         111 my $err = $delta->parse($string);
188 33 100       68 if (! $err) {
189 24 100       47 $delta->convert($mode) if ($mode);
190 24 50       32 splice(@$args,0,$#args+1) if ($list);
191 24         55 my $ret = $delta->value('local');
192 24         90 return $ret;
193             }
194 9         21 pop(@args);
195             }
196              
197 9         29 return '';
198             }
199              
200             sub UnixDate {
201 2     2 1 899 my($string,@in) = @_;
202 2         3 my(@ret);
203              
204 2         10 my $err = $date->parse($string);
205 2 50       4 return () if ($err);
206              
207 2         5 foreach my $in (@in) {
208 2         7 push(@ret,$date->printf($in));
209             }
210              
211 2 50       6 if (! wantarray) {
212 0         0 return join(" ",@ret);
213             }
214 2         10 return @ret;
215             }
216              
217             sub Delta_Format {
218 19     19 1 12871 my($string,@args) = @_;
219              
220 19         51 my $err = $delta->parse($string);
221 19 50       55 return () if ($err);
222              
223 19         26 my($mode,$dec,@in);
224 19 50 100     86 if (! defined($args[0])) {
    100 100        
    50          
225 0         0 $mode = 'exact';
226 0         0 @in = @args;
227 0         0 shift(@in);
228              
229             } elsif (lc($args[0]) eq 'exact' ||
230             lc($args[0]) eq 'approx' ||
231             lc($args[0]) eq 'semi') {
232 18         37 ($mode,$dec,@in) = (@args);
233 18         24 $mode = lc($mode);
234              
235             } elsif ($args[0] =~ /^\d+$/) {
236 0         0 ($mode,$dec,@in) = ('exact',@args);
237              
238             } else {
239 1         3 $mode = 'exact';
240 1         3 @in = @args;
241             }
242              
243 19 100       28 $dec = 0 if (! $dec);
244 19         36 @in = _Delta_Format_old($mode,$dec,@in);
245              
246 19         33 my @ret = ();
247 19         30 foreach my $in (@in) {
248 19         48 push(@ret,$delta->printf($in));
249             }
250              
251 19 50       29 if (! wantarray) {
252 0         0 return join(" ",@ret);
253             }
254              
255 19         83 return @ret;
256             }
257              
258             sub _Delta_Format_old {
259 19     19   31 my($mode,$dec,@in) = @_;
260 19         22 my(@ret);
261 19         43 my $business = $delta->type('business');
262              
263 19         31 foreach my $in (@in) {
264 19         31 my $out = '';
265              
266             # This will look for old formats (%Xd, %Xh, %Xt) and turn them
267             # into the new format: %XYZ
268              
269 19         30 while ($in) {
270 248 100       753 if ($in =~ s/^([^%]+)//) {
    50          
    100          
271 115         218 $out .= $1;
272              
273             } elsif ($in =~ /^%[yMwdhms][yMwdhms][yMwdhms]/) {
274             # It's one of the new formats so don't modify it.
275 0         0 $in =~ s/^%//;
276 0         0 $out .= '%';
277              
278             } elsif ($in =~ s/^%([yMwdhms])([dht])//) {
279 126         234 my($field,$scope) = ($1,$2);
280 126         201 $out .= '%';
281              
282 126 100       204 if ($scope eq 'd') {
    100          
    50          
283 42 100 100     124 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
284 14         31 $out .= ".${dec}${field}${field}s";
285             } elsif ($field eq 'y' || $field eq 'M') {
286 8         18 $out .= ".${dec}${field}${field}M";
287             } elsif ($mode eq 'semi') {
288 10         21 $out .= ".${dec}${field}${field}s";
289             } elsif ($field eq 'w' && $business) {
290 1         4 $out .= ".${dec}www";
291             } elsif (($field eq 'w' || $field eq 'd') && ! $business) {
292 2         5 $out .= ".${dec}${field}${field}d";
293             } else {
294 7         16 $out .= ".${dec}${field}${field}s";
295             }
296              
297             } elsif ($scope eq 'h') {
298 42 100 100     109 if ($mode eq 'approx') {
    100 100        
    100          
    100          
    100          
    100          
299 14         30 $out .= ".${dec}${field}y${field}";
300             } elsif ($field eq 'y' || $field eq 'M') {
301 8         18 $out .= ".${dec}${field}y${field}";
302             } elsif ($mode eq 'semi') {
303 10         19 $out .= ".${dec}${field}w${field}";
304             } elsif ($field eq 'w') {
305 2         6 $out .= ".${dec}www";
306             } elsif ($field eq 'd' && ! $business) {
307 1         4 $out .= ".${dec}dwd";
308             } elsif ($business) {
309 4         9 $out .= ".${dec}${field}d${field}";
310             } else {
311 3         7 $out .= ".${dec}${field}h${field}";
312             }
313              
314             } elsif ($scope eq 't') {
315 42 100 100     130 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
    100          
316 14         26 $out .= ".${dec}${field}ys";
317             } elsif ($field eq 'y' || $field eq 'M') {
318 8         19 $out .= ".${dec}${field}yM";
319             } elsif ($mode eq 'semi') {
320 10         22 $out .= ".${dec}${field}ws";
321             } elsif ($field eq 'w' && $business) {
322 1         4 $out .= ".${dec}www";
323             } elsif (($field eq 'w' || $field eq 'd') && ! $business) {
324 2         6 $out .= ".${dec}${field}wd";
325             } elsif ($business) {
326 4         8 $out .= ".${dec}${field}ds";
327             } else {
328 3         7 $out .= ".${dec}${field}hs";
329             }
330             }
331              
332             } else {
333             # It's one of the new formats so don't modify it.
334 7         16 $in =~ s/^%//;
335 7         11 $out .= '%';
336             }
337             }
338              
339 19         38 push(@ret,$out);
340             }
341              
342 19         41 return @ret;
343             }
344              
345             sub DateCalc {
346 120     120 1 67520 my($d1,$d2,@args) = @_;
347              
348             # Handle \$err arg
349              
350 120         164 my($ref,$errref);
351              
352 120 50 66     523 if (@args && ref($args[0])) {
353 0         0 $errref = shift(@args);
354 0         0 $ref = 1;
355             } else {
356 120         169 $ref = 0;
357             }
358              
359             # Parse $d1 and $d2
360              
361 120         170 my ($obj1,$obj2,$err,$usemode);
362 120         158 $usemode = 1;
363              
364 120         328 $obj1 = $date->new_date();
365 120         332 $err = $obj1->parse($d1,'nodelta');
366 120 50       230 if ($err) {
367 0         0 $obj1 = $date->new_delta();
368 0         0 $err = $obj1->parse($d1);
369 0 0       0 if ($err) {
370 0 0       0 $$errref = 1 if ($ref);
371 0         0 return '';
372             }
373 0         0 $usemode = 0;
374             }
375              
376 120         314 $obj2 = $date->new_date();
377 120         372 $err = $obj2->parse($d2,'nodelta');
378 120 100       317 if ($err) {
379 49         163 $obj2 = $date->new_delta();
380 49         133 $err = $obj2->parse($d2);
381 49 50       85 if ($err) {
382 0 0       0 $$errref = 2 if ($ref);
383 0         0 return '';
384             }
385 49         58 $usemode = 0;
386             }
387              
388             # Handle $mode
389              
390 120         150 my($mode);
391 120 100       224 if (@args) {
392 60         85 $mode = shift(@args);
393             }
394 120 50       220 if (@args) {
395 0 0       0 $$errref = 3 if ($ref);
396 0         0 return '';
397             }
398              
399             # Apply the $mode to any deltas
400              
401 120 100       200 if (defined($mode)) {
402 60 50       179 if (ref($obj1) eq 'Date::Manip::Delta') {
403 0 0       0 if ($$obj1{'data'}{'gotmode'}) {
404 0 0 0     0 if ($mode == 2 || $mode == 3) {
405 0 0       0 if (! $obj1->type('business')) {
406 0 0       0 $$errref = 3 if ($ref);
407 0         0 return '';
408             }
409             } else {
410 0 0       0 if ($obj1->type('business')) {
411 0 0       0 $$errref = 3 if ($ref);
412 0         0 return '';
413             }
414             }
415             } else {
416 0 0 0     0 if ($mode == 2 || $mode == 3) {
417 0         0 $obj1->set('mode','business');
418             } else {
419 0         0 $obj1->set('mode','normal');
420             }
421             }
422             }
423              
424 60 50       155 if (ref($obj2) eq 'Date::Manip::Delta') {
425 0 0       0 if ($$obj2{'data'}{'gotmode'}) {
426 0 0 0     0 if ($mode == 2 || $mode == 3) {
427 0 0       0 if (! $obj2->type('business')) {
428 0 0       0 $$errref = 3 if ($ref);
429 0         0 return '';
430             }
431             } else {
432 0 0       0 if ($obj2->type('business')) {
433 0 0       0 $$errref = 3 if ($ref);
434 0         0 return '';
435             }
436             }
437             } else {
438 0 0 0     0 if ($mode ==2 || $mode == 3) {
439 0         0 $obj2->set('mode','business');
440             } else {
441 0         0 $obj2->set('mode','normal');
442             }
443             }
444             }
445             }
446              
447             # Do the calculation
448              
449 120         150 my $obj3;
450 120 100       199 if ($usemode) {
451 71 100       129 $mode = 'exact' if (! $mode);
452 71         450 my %tmp = ('0' => 'exact',
453             '1' => 'approx',
454             '2' => 'bapprox',
455             '3' => 'business',
456             'exact' => 'exact',
457             'semi' => 'semi',
458             'approx' => 'approx',
459             'business'=> 'business',
460             'bsemi' => 'bsemi',
461             'bapprox' => 'bapprox',
462             );
463              
464 71 50       138 if (exists $tmp{$mode}) {
465 71         150 $mode = $tmp{$mode};
466             } else {
467 0 0       0 $$errref = 3 if ($ref);
468 0         0 return '';
469             }
470              
471 71         177 $obj3 = $obj1->calc($obj2,$mode);
472             } else {
473 49         141 $obj3 = $obj1->calc($obj2);
474             }
475              
476 120         378 my $ret = $obj3->value();
477 120         1501 return $ret;
478             }
479              
480             sub Date_GetPrev {
481 34     34 1 32812 my($string,$dow,$curr,@time) = @_;
482 34         90 my $err = $date->parse($string);
483 34 50       64 return '' if ($err);
484              
485 34 100       55 if (defined($dow)) {
486 11         16 $dow = lc($dow);
487 11 50       37 if (exists $$dmb{'data'}{'wordmatch'}{'day_char'}{$dow}) {
    100          
    50          
488 0         0 $dow = $$dmb{'data'}{'wordmatch'}{'day_char'}{$dow};
489             } elsif (exists $$dmb{'data'}{'wordmatch'}{'day_abb'}{$dow}) {
490 10         15 $dow = $$dmb{'data'}{'wordmatch'}{'day_abb'}{$dow};
491             } elsif (exists $$dmb{'data'}{'wordmatch'}{'day_name'}{$dow}) {
492 0         0 $dow = $$dmb{'data'}{'wordmatch'}{'day_name'}{$dow};
493             }
494             }
495              
496 34 100       55 if ($#time == 0) {
497 7         9 @time = @{ $dmb->split('hms',$time[0]) };
  7         22  
498             }
499              
500 34 100       54 if (@time) {
501 29         54 while ($#time < 2) {
502 7         13 push(@time,0);
503             }
504 29         77 $date->prev($dow,$curr,\@time);
505             } else {
506 5         15 $date->prev($dow,$curr);
507             }
508 34         78 my $ret = $date->value();
509 34         158 return $ret;
510             }
511              
512             sub Date_GetNext {
513 34     34 1 33417 my($string,$dow,$curr,@time) = @_;
514 34         81 my $err = $date->parse($string);
515 34 50       55 return '' if ($err);
516              
517 34 100       52 if (defined($dow)) {
518 11         16 $dow = lc($dow);
519 11 50       40 if (exists $$dmb{'data'}{'wordmatch'}{'day_char'}{$dow}) {
    100          
    50          
520 0         0 $dow = $$dmb{'data'}{'wordmatch'}{'day_char'}{$dow};
521             } elsif (exists $$dmb{'data'}{'wordmatch'}{'day_abb'}{$dow}) {
522 10         17 $dow = $$dmb{'data'}{'wordmatch'}{'day_abb'}{$dow};
523             } elsif (exists $$dmb{'data'}{'wordmatch'}{'day_name'}{$dow}) {
524 0         0 $dow = $$dmb{'data'}{'wordmatch'}{'day_name'}{$dow};
525             }
526             }
527              
528 34 100       54 if ($#time == 0) {
529 7         10 @time = @{ $dmb->split('hms',$time[0]) };
  7         21  
530             }
531              
532 34 100       60 if (@time) {
533 29         55 while ($#time < 2) {
534 7         12 push(@time,0);
535             }
536 29         67 $date->next($dow,$curr,\@time);
537             } else {
538 5         13 $date->next($dow,$curr);
539             }
540 34         78 my $ret = $date->value();
541 34         121 return $ret;
542             }
543              
544             sub Date_SetTime {
545 5     5 1 3843 my($string,@time) = @_;
546              
547 5         18 my $err = $date->parse($string);
548 5 50       11 return '' if ($err);
549              
550 5 100       9 if ($#time == 0) {
551 3         5 @time = @{ $dmb->split('hms',$time[0]) };
  3         12  
552             }
553              
554 5         11 while ($#time < 2) {
555 1         3 push(@time,0);
556             }
557              
558 5         16 $date->set('time',\@time);
559 5         12 my $val = $date->value();
560 5         19 return $val;
561             }
562              
563             sub Date_SetDateField {
564 0     0 1 0 my($string,$field,$val) = @_;
565              
566 0         0 my $err = $date->parse($string);
567 0 0       0 return '' if ($err);
568              
569 0         0 $date->set($field,$val);
570 0         0 my $ret = $date->value();
571 0         0 return $ret;
572             }
573              
574             sub Date_NextWorkDay {
575 0     0 1 0 my($string,$n,$checktime) = @_;
576 0         0 my $err = $date->parse($string);
577 0 0       0 return '' if ($err);
578 0         0 $date->next_business_day($n,$checktime);
579 0         0 my $val = $date->value();
580 0         0 return $val;
581             }
582              
583             sub Date_PrevWorkDay {
584 0     0 1 0 my($string,$n,$checktime) = @_;
585 0         0 my $err = $date->parse($string);
586 0 0       0 return '' if ($err);
587 0         0 $date->prev_business_day($n,$checktime);
588 0         0 my $val = $date->value();
589 0         0 return $val;
590             }
591              
592             sub Date_NearestWorkDay {
593 0     0 1 0 my($string,$tomorrowfirst) = @_;
594 0         0 my $err = $date->parse($string);
595 0 0       0 return '' if ($err);
596 0         0 $date->nearest_business_day($tomorrowfirst);
597 0         0 my $val = $date->value();
598 0         0 return $val;
599             }
600              
601             sub ParseRecur {
602 93     93 1 110367 my($string,@args) = @_;
603              
604 93 50       302 if ($#args == 3) {
605 0         0 my($base,$d0,$d1,$flags) = @args;
606 0         0 @args = ();
607 0 0       0 push(@args,$flags) if ($flags);
608 0         0 push(@args,$base,$d0,$d1);
609             }
610              
611 93         400 my $err = $recur->parse($string,@args);
612 93 50       190 return '' if ($err);
613              
614 93 50       197 if (wantarray) {
615 93         306 my @dates = $recur->dates();
616 93         163 my @ret;
617 93         210 foreach my $d (@dates) {
618 363         723 my $val = $d->value();
619 363         773 push(@ret,$val);
620             }
621 93         686 return @ret;
622             }
623              
624 0         0 my @int = @{ $$recur{'data'}{'interval'} };
  0         0  
625 0         0 my @rtime = @{ $$recur{'data'}{'rtime'} };
  0         0  
626 0         0 my @flags = @{ $$recur{'data'}{'flags'} };
  0         0  
627 0         0 my $start = $$recur{'data'}{'start'};
628 0         0 my $end = $$recur{'data'}{'end'};
629 0         0 my $base = $$recur{'data'}{'base'};
630              
631 0         0 my $r;
632 0 0       0 if (@int) {
633 0         0 $r = join(':',@int);
634             }
635 0 0       0 if (@rtime) {
636 0         0 my @rt;
637 0         0 foreach my $rt (@rtime) {
638 0         0 push(@rt,join(",",@$rt));
639             }
640 0         0 $r .= '*' . join(':',@rt);
641             }
642              
643 0         0 $r .= '*' . join(",",@flags);
644              
645 0 0       0 my $val = (defined($base) ? $base->value() : '');
646 0         0 $r .= "*$val";
647              
648 0 0       0 $val = (defined($start) ? $start->value() : '');
649 0         0 $r .= "*$val";
650              
651 0 0       0 $val = (defined($end) ? $end->value() : '');
652 0         0 $r .= "*$val";
653              
654 0         0 return $r;
655             }
656              
657             sub Events_List {
658 8     8 1 10578 my($datestr,@args) = @_;
659              
660             # First argument is always a date
661              
662 8         36 my $err = $date->parse($datestr);
663 8 50       18 return [] if ($err);
664              
665             # Second argument is absent, a date, or 0.
666              
667 8         13 my @list;
668 8         11 my $flag = 0;
669 8         11 my ($date0,$date1);
670              
671 8 100       19 if (! @args) {
672             # absent
673 4         14 @list = $date->list_events('dates');
674              
675             } else {
676             # a date or 0
677 4         10 my $arg = shift(@args);
678 4 100       9 $flag = shift(@args) if (@args);
679 4 50       10 if (@args) {
680 0         0 carp "ERROR: unknown argument list";
681 0         0 return [];
682             }
683              
684 4 100       11 if (! $arg) {
685 1         4 my($y,$m,$d) = $date->value();
686 1         6 $date2->set('date',[$y,$m,$d,23,59,59]);
687 1         5 @list = $date->list_events(0, 'dates');
688              
689             } else {
690 3         13 $err = $date2->parse($arg);
691 3 50       8 if ($err) {
692 0         0 carp "ERROR: invalid argument: $arg";
693 0         0 return [];
694             }
695 3         12 @list = $date->list_events($date2, 'dates');
696             }
697             }
698              
699             # Handle the flag
700              
701 8 100       26 if (! $flag) {
702 6         11 my @ret = ();
703 6         15 foreach my $e (@list) {
704 11         21 my($d,@n) = @$e;
705 11         27 my $v = $d->value();
706 11         30 push(@ret,$v,[@n]);
707             }
708 6         43 return \@ret;
709             }
710              
711 2         8 push(@list,[$date2]);
712 2         4 my %ret;
713              
714 2 100       19 if ($flag==1) {
    50          
715 1         6 while ($#list > 0) {
716 4         6 my($d0,@n) = @{ shift(@list) };
  4         8  
717 4         9 my $d1 = $list[0]->[0];
718 4         11 my $delta = $d0->calc($d1);
719              
720 4         8 foreach $flag (@n) {
721 5 50       9 $flag = '' if (! defined($flag));
722 5 100       11 if (exists $ret{$flag}) {
723 2         7 $ret{$flag} = $ret{$flag}->calc($delta);
724             } else {
725 3         9 $ret{$flag} = $delta;
726             }
727             }
728             }
729              
730             } elsif ($flag==2) {
731 1         5 while ($#list > 0) {
732 4         7 my($d0,@n) = @{ shift(@list) };
  4         10  
733 4         8 my $d1 = $list[0]->[0];
734 4         10 my $delta = $d0->calc($d1);
735 4         14 $flag = join("+",sort(@n));
736              
737 4 100       10 if (exists $ret{$flag}) {
738 1         6 $ret{$flag} = $ret{$flag}->calc($delta);
739             } else {
740 3         9 $ret{$flag} = $delta;
741             }
742             }
743              
744             } else {
745 0         0 carp "ERROR: Invalid flag $flag";
746 0         0 return [];
747             }
748              
749 2         8 foreach my $flag (keys %ret) {
750 6         17 $ret{$flag} = $ret{$flag}->value();
751             }
752              
753 2         10 return \%ret;
754             }
755              
756             ########################################################################
757             # ADDITIONAL ROUTINES
758             ########################################################################
759              
760             sub Date_DayOfWeek {
761 0     0 1 0 my($m,$d,$y) = @_;
762 0         0 return $dmb->day_of_week([$y,$m,$d]);
763             }
764              
765             sub Date_SecsSince1970 {
766 0     0 1 0 my($m,$d,$y,$h,$mn,$s) = @_;
767 0         0 return $dmb->secs_since_1970([$y,$m,$d,$h,$mn,$s]);
768             }
769              
770             sub Date_SecsSince1970GMT {
771 0     0 1 0 my($m,$d,$y,$h,$mn,$s) = @_;
772 0         0 $date->set('date',[$y,$m,$d,$h,$mn,$s]);
773 0         0 return $date->secs_since_1970_GMT();
774             }
775              
776             sub Date_DaysSince1BC {
777 0     0 1 0 my($m,$d,$y) = @_;
778 0         0 return $dmb->days_since_1BC([$y,$m,$d]);
779             }
780              
781             sub Date_DayOfYear {
782 0     0 1 0 my($m,$d,$y) = @_;
783 0         0 return $dmb->day_of_year([$y,$m,$d]);
784             }
785              
786             sub Date_NthDayOfYear {
787 7     7 1 4689 my($y,$n) = @_;
788 7         9 my @ret = @{ $dmb->day_of_year($y,$n) };
  7         15  
789 7 100       21 push(@ret,0,0,0) if ($#ret == 2);
790 7         20 return @ret;
791             }
792              
793             sub Date_DaysInMonth {
794 0     0 1 0 my($m,$y) = @_;
795 0         0 return $dmb->days_in_month($y,$m);
796             }
797              
798             sub Date_DaysInYear {
799 0     0 1 0 my($y) = @_;
800 0         0 return $dmb->days_in_year($y);
801             }
802              
803             sub Date_WeekOfYear {
804 0     0 1 0 my($m,$d,$y,$first) = @_;
805 0         0 my($yy,$ww) = $dmb->_week_of_year($first,[$y,$m,$d]);
806 0 0       0 return 0 if ($yy<$y);
807 0 0       0 return 53 if ($yy>$y);
808 0         0 return $ww;
809             }
810              
811             sub Date_LeapYear {
812 0     0 1 0 my($y) = @_;
813 0         0 return $dmb->leapyear($y);
814             }
815              
816             sub Date_DaySuffix {
817 0     0 1 0 my($d) = @_;
818 0         0 return $$dmb{'data'}{'wordlist'}{'nth_dom'}[$d-1];
819             }
820              
821             sub Date_TimeZone {
822 0     0 1 0 my($ret) = $dmb->_now('tz');
823 0         0 return $ret;
824             }
825              
826             sub Date_ConvTZ {
827 14     14 1 11596 my($str,$from,$to) = @_;
828 14 50       35 $from = $dmb->_now('tz') if (! $from);
829 14 50       30 $to = $dmb->_now('tz') if (! $to);
830              
831             # Parse the date (ignoring timezone information):
832              
833 14         70 my $err = $dateUT->parse($str);
834 14 50       28 return '' if ($err);
835 14         48 my $d = [ $dateUT->value() ];
836 14 50       36 return '' if (! $d);
837              
838             # Get the timezone for $from. First, we'll assume that
839             # the date matches exactly (so if the timezone is passed
840             # in as an abbreviation, we'll try to get the timezone
841             # that fits the date/abbrev combination). If we can't,
842             # we'll just assume that the timezone is more generic
843             # and try it without the date.
844              
845 14         20 my $tmp;
846 14         42 $tmp = $dmt->zone($from,$d);
847 14 50       38 if (! $tmp) {
848 0         0 $tmp = $dmt->zone($from);
849 0 0       0 return '' if (! $tmp);
850             }
851 14         26 $from = $tmp;
852              
853 14         35 $tmp = $dmt->zone($to,$d);
854 14 100       41 if (! $tmp) {
855 2         8 $tmp = $dmt->zone($to);
856 2 50       13 return '' if (! $tmp);
857             }
858 14         31 $to = $tmp;
859              
860 14         49 ($err,$d) = $dmt->convert($d,$from,$to);
861 14 50       33 return '' if ($err);
862 14         51 return $dmb->join('date',$d);
863             }
864              
865             sub Date_IsWorkDay {
866 0     0 1 0 my($str,$checktime) = @_;
867 0         0 my $err = $date->parse($str);
868 0 0       0 return '' if ($err);
869 0         0 return $date->is_business_day($checktime);
870             }
871              
872             sub Date_IsHoliday {
873 2     2 1 1420 my($str) = @_;
874 2         10 my $err = $date->parse($str);
875 2 50       5 return undef if ($err);
876 2 100       4 if (wantarray) {
877 1         6 my @ret = $date->holiday();
878 1         4 return @ret;
879             } else {
880 1         6 my $ret = $date->holiday();
881 1         5 return $ret;
882             }
883             }
884              
885             sub Date_Cmp {
886 0     0 1   my($str1,$str2) = @_;
887 0           my $err = $date->parse($str1);
888 0 0         return undef if ($err);
889 0           $err = $date2->parse($str2);
890 0 0         return undef if ($err);
891 0           return $date->cmp($date2);
892             }
893              
894             1;
895             # Local Variables:
896             # mode: cperl
897             # indent-tabs-mode: nil
898             # cperl-indent-level: 3
899             # cperl-continued-statement-offset: 2
900             # cperl-continued-brace-offset: 0
901             # cperl-brace-offset: 0
902             # cperl-brace-imaginary-offset: 0
903             # cperl-label-offset: 0
904             # End: