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   1103 use strict;
  168         338  
  168         4781  
53 168     168   77228 use integer;
  168         2467  
  168         876  
54 168     168   5102 use warnings;
  168         332  
  168         12145  
55              
56             our $VERSION;
57             $VERSION='6.91';
58              
59             ###########################################################################
60              
61             our ($dmb,$dmt,$date,$delta,$recur,$date2,$dateUT);
62 168     168   152496 use Date::Manip::Date;
  168         693  
  168         7759  
63 168     168   1101 use Carp;
  168         381  
  168         899529  
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 41488 my($flag) = @_;
83 168         1843 return $date->version($flag);
84             }
85              
86             sub Date_Init {
87 23     23 1 1627 my(@args) = @_;
88 23         54 my(@args2);
89              
90 23         67 foreach my $arg (@args) {
91 24 50       245 if ($arg =~ /^(\S+)\s*=\s*(.*)$/) {
92 24         142 push(@args2,$1,$2);
93             } else {
94 0         0 carp "ERROR: invalid Date_Init argument: $arg";
95             }
96             }
97 23         118 $date->config(@args2);
98 23         219 return $date->err();
99             }
100              
101             sub ParseDateString {
102 247     247 1 121712 my($string,@opts) = @_;
103 247 50       584 $string = '' if (! defined($string));
104 247         819 my $err = $date->parse($string,@opts);
105 247 100       678 return '' if ($err);
106 203         672 my $ret = $date->value('local');
107 203         881 return $ret;
108             }
109              
110             sub ParseDateFormat {
111 3     3 1 2570 my($format,$string) = @_;
112 3 50       9 $string = '' if (! defined($string));
113 3         15 my $err = $date->parse_format($format,$string);
114 3 50       8 return '' if ($err);
115 3         15 my $ret = $date->value('local');
116 3         16 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 17263 my(@a) = @_;
155              
156 33 50 33     136 if (@a < 1 || @a > 2) {
157 0         0 print "ERROR: Invalid number of arguments to ParseDateDelta.\n";
158 0         0 return '';
159             }
160 33         64 my($args,$mode) = @_;
161 33 50       64 $args = '' if (! defined($args));
162 33 100       68 $mode = '' if (! $mode);
163 33         51 $mode = lc($mode);
164 33 50 33     70 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         60 my @args;
170 33         51 my $ref = ref($args);
171 33         38 my $list = 0;
172              
173 33 50       63 if (! $ref) {
    0          
    0          
174 33         59 @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         64 while (@args) {
186 33         82 my $string = join(' ',@args);
187 33         94 my $err = $delta->parse($string);
188 33 100       68 if (! $err) {
189 24 100       49 $delta->convert($mode) if ($mode);
190 24 50       48 splice(@$args,0,$#args+1) if ($list);
191 24         60 my $ret = $delta->value('local');
192 24         101 return $ret;
193             }
194 9         23 pop(@args);
195             }
196              
197 9         34 return '';
198             }
199              
200             sub UnixDate {
201 2     2 1 1129 my($string,@in) = @_;
202 2         4 my(@ret);
203              
204 2         13 my $err = $date->parse($string);
205 2 50       5 return () if ($err);
206              
207 2         7 foreach my $in (@in) {
208 2         9 push(@ret,$date->printf($in));
209             }
210              
211 2 50       13 if (! wantarray) {
212 0         0 return join(" ",@ret);
213             }
214 2         11 return @ret;
215             }
216              
217             sub Delta_Format {
218 19     19 1 16150 my($string,@args) = @_;
219              
220 19         55 my $err = $delta->parse($string);
221 19 50       56 return () if ($err);
222              
223 19         27 my($mode,$dec,@in);
224 19 50 100     92 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         41 ($mode,$dec,@in) = (@args);
233 18         29 $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       37 $dec = 0 if (! $dec);
244 19         40 @in = _Delta_Format_old($mode,$dec,@in);
245              
246 19         28 my @ret = ();
247 19         26 foreach my $in (@in) {
248 19         59 push(@ret,$delta->printf($in));
249             }
250              
251 19 50       38 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   36 my($mode,$dec,@in) = @_;
260 19         26 my(@ret);
261 19         48 my $business = $delta->type('business');
262              
263 19         34 foreach my $in (@in) {
264 19         28 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         33 while ($in) {
270 248 100       907 if ($in =~ s/^([^%]+)//) {
    50          
    100          
271 115         254 $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         281 my($field,$scope) = ($1,$2);
280 126         172 $out .= '%';
281              
282 126 100       243 if ($scope eq 'd') {
    100          
    50          
283 42 100 100     150 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
284 14         35 $out .= ".${dec}${field}${field}s";
285             } elsif ($field eq 'y' || $field eq 'M') {
286 8         22 $out .= ".${dec}${field}${field}M";
287             } elsif ($mode eq 'semi') {
288 10         23 $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         8 $out .= ".${dec}${field}${field}d";
293             } else {
294 7         18 $out .= ".${dec}${field}${field}s";
295             }
296              
297             } elsif ($scope eq 'h') {
298 42 100 100     126 if ($mode eq 'approx') {
    100 100        
    100          
    100          
    100          
    100          
299 14         38 $out .= ".${dec}${field}y${field}";
300             } elsif ($field eq 'y' || $field eq 'M') {
301 8         22 $out .= ".${dec}${field}y${field}";
302             } elsif ($mode eq 'semi') {
303 10         23 $out .= ".${dec}${field}w${field}";
304             } elsif ($field eq 'w') {
305 2         7 $out .= ".${dec}www";
306             } elsif ($field eq 'd' && ! $business) {
307 1         4 $out .= ".${dec}dwd";
308             } elsif ($business) {
309 4         11 $out .= ".${dec}${field}d${field}";
310             } else {
311 3         8 $out .= ".${dec}${field}h${field}";
312             }
313              
314             } elsif ($scope eq 't') {
315 42 100 100     143 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
    100          
316 14         31 $out .= ".${dec}${field}ys";
317             } elsif ($field eq 'y' || $field eq 'M') {
318 8         20 $out .= ".${dec}${field}yM";
319             } elsif ($mode eq 'semi') {
320 10         23 $out .= ".${dec}${field}ws";
321             } elsif ($field eq 'w' && $business) {
322 1         3 $out .= ".${dec}www";
323             } elsif (($field eq 'w' || $field eq 'd') && ! $business) {
324 2         6 $out .= ".${dec}${field}wd";
325             } elsif ($business) {
326 4         10 $out .= ".${dec}${field}ds";
327             } else {
328 3         9 $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         15 $out .= '%';
336             }
337             }
338              
339 19         40 push(@ret,$out);
340             }
341              
342 19         46 return @ret;
343             }
344              
345             sub DateCalc {
346 120     120 1 78640 my($d1,$d2,@args) = @_;
347              
348             # Handle \$err arg
349              
350 120         201 my($ref,$errref);
351              
352 120 50 66     479 if (@args && ref($args[0])) {
353 0         0 $errref = shift(@args);
354 0         0 $ref = 1;
355             } else {
356 120         190 $ref = 0;
357             }
358              
359             # Parse $d1 and $d2
360              
361 120         205 my ($obj1,$obj2,$err,$usemode);
362 120         172 $usemode = 1;
363              
364 120         411 $obj1 = $date->new_date();
365 120         368 $err = $obj1->parse($d1,'nodelta');
366 120 50       278 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         356 $obj2 = $date->new_date();
377 120         321 $err = $obj2->parse($d2,'nodelta');
378 120 100       301 if ($err) {
379 49         159 $obj2 = $date->new_delta();
380 49         167 $err = $obj2->parse($d2);
381 49 50       105 if ($err) {
382 0 0       0 $$errref = 2 if ($ref);
383 0         0 return '';
384             }
385 49         75 $usemode = 0;
386             }
387              
388             # Handle $mode
389              
390 120         163 my($mode);
391 120 100       244 if (@args) {
392 60         105 $mode = shift(@args);
393             }
394 120 50       242 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       256 if (defined($mode)) {
402 60 50       154 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       125 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         165 my $obj3;
450 120 100       214 if ($usemode) {
451 71 100       143 $mode = 'exact' if (! $mode);
452 71         508 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       152 if (exists $tmp{$mode}) {
465 71         125 $mode = $tmp{$mode};
466             } else {
467 0 0       0 $$errref = 3 if ($ref);
468 0         0 return '';
469             }
470              
471 71         222 $obj3 = $obj1->calc($obj2,$mode);
472             } else {
473 49         208 $obj3 = $obj1->calc($obj2);
474             }
475              
476 120         362 my $ret = $obj3->value();
477 120         1616 return $ret;
478             }
479              
480             sub Date_GetPrev {
481 34     34 1 40533 my($string,$dow,$curr,@time) = @_;
482 34         108 my $err = $date->parse($string);
483 34 50       72 return '' if ($err);
484              
485 34 100       54 if (defined($dow)) {
486 11         22 $dow = lc($dow);
487 11 50       49 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         21 $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       70 if ($#time == 0) {
497 7         9 @time = @{ $dmb->split('hms',$time[0]) };
  7         25  
498             }
499              
500 34 100       72 if (@time) {
501 29         64 while ($#time < 2) {
502 7         21 push(@time,0);
503             }
504 29         87 $date->prev($dow,$curr,\@time);
505             } else {
506 5         17 $date->prev($dow,$curr);
507             }
508 34         95 my $ret = $date->value();
509 34         211 return $ret;
510             }
511              
512             sub Date_GetNext {
513 34     34 1 40329 my($string,$dow,$curr,@time) = @_;
514 34         103 my $err = $date->parse($string);
515 34 50       64 return '' if ($err);
516              
517 34 100       66 if (defined($dow)) {
518 11         21 $dow = lc($dow);
519 11 50       53 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         23 $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       75 if ($#time == 0) {
529 7         12 @time = @{ $dmb->split('hms',$time[0]) };
  7         23  
530             }
531              
532 34 100       68 if (@time) {
533 29         64 while ($#time < 2) {
534 7         16 push(@time,0);
535             }
536 29         86 $date->next($dow,$curr,\@time);
537             } else {
538 5         19 $date->next($dow,$curr);
539             }
540 34         97 my $ret = $date->value();
541 34         147 return $ret;
542             }
543              
544             sub Date_SetTime {
545 5     5 1 4738 my($string,@time) = @_;
546              
547 5         19 my $err = $date->parse($string);
548 5 50       14 return '' if ($err);
549              
550 5 100       10 if ($#time == 0) {
551 3         5 @time = @{ $dmb->split('hms',$time[0]) };
  3         10  
552             }
553              
554 5         16 while ($#time < 2) {
555 1         14 push(@time,0);
556             }
557              
558 5         18 $date->set('time',\@time);
559 5         19 my $val = $date->value();
560 5         22 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 128286 my($string,@args) = @_;
603              
604 93 50       249 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         320 my $err = $recur->parse($string,@args);
612 93 50       173 return '' if ($err);
613              
614 93 50       207 if (wantarray) {
615 93         270 my @dates = $recur->dates();
616 93         144 my @ret;
617 93         187 foreach my $d (@dates) {
618 363         746 my $val = $d->value();
619 363         793 push(@ret,$val);
620             }
621 93         500 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 12750 my($datestr,@args) = @_;
659              
660             # First argument is always a date
661              
662 8         37 my $err = $date->parse($datestr);
663 8 50       19 return [] if ($err);
664              
665             # Second argument is absent, a date, or 0.
666              
667 8         12 my @list;
668 8         11 my $flag = 0;
669 8         13 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         11 my $arg = shift(@args);
678 4 100       12 $flag = shift(@args) if (@args);
679 4 50       12 if (@args) {
680 0         0 carp "ERROR: unknown argument list";
681 0         0 return [];
682             }
683              
684 4 100       10 if (! $arg) {
685 1         4 my($y,$m,$d) = $date->value();
686 1         8 $date2->set('date',[$y,$m,$d,23,59,59]);
687 1         7 @list = $date->list_events(0, 'dates');
688              
689             } else {
690 3         13 $err = $date2->parse($arg);
691 3 50       11 if ($err) {
692 0         0 carp "ERROR: invalid argument: $arg";
693 0         0 return [];
694             }
695 3         14 @list = $date->list_events($date2, 'dates');
696             }
697             }
698              
699             # Handle the flag
700              
701 8 100       36 if (! $flag) {
702 6         13 my @ret = ();
703 6         14 foreach my $e (@list) {
704 11         24 my($d,@n) = @$e;
705 11         24 my $v = $d->value();
706 11         52 push(@ret,$v,[@n]);
707             }
708 6         32 return \@ret;
709             }
710              
711 2         7 push(@list,[$date2]);
712 2         3 my %ret;
713              
714 2 100       11 if ($flag==1) {
    50          
715 1         4 while ($#list > 0) {
716 4         8 my($d0,@n) = @{ shift(@list) };
  4         10  
717 4         9 my $d1 = $list[0]->[0];
718 4         14 my $delta = $d0->calc($d1);
719              
720 4         11 foreach $flag (@n) {
721 5 50       12 $flag = '' if (! defined($flag));
722 5 100       14 if (exists $ret{$flag}) {
723 2         11 $ret{$flag} = $ret{$flag}->calc($delta);
724             } else {
725 3         12 $ret{$flag} = $delta;
726             }
727             }
728             }
729              
730             } elsif ($flag==2) {
731 1         5 while ($#list > 0) {
732 4         8 my($d0,@n) = @{ shift(@list) };
  4         12  
733 4         13 my $d1 = $list[0]->[0];
734 4         11 my $delta = $d0->calc($d1);
735 4         17 $flag = join("+",sort(@n));
736              
737 4 100       13 if (exists $ret{$flag}) {
738 1         11 $ret{$flag} = $ret{$flag}->calc($delta);
739             } else {
740 3         12 $ret{$flag} = $delta;
741             }
742             }
743              
744             } else {
745 0         0 carp "ERROR: Invalid flag $flag";
746 0         0 return [];
747             }
748              
749 2         10 foreach my $flag (keys %ret) {
750 6         31 $ret{$flag} = $ret{$flag}->value();
751             }
752              
753 2         12 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 5893 my($y,$n) = @_;
788 7         10 my @ret = @{ $dmb->day_of_year($y,$n) };
  7         20  
789 7 100       21 push(@ret,0,0,0) if ($#ret == 2);
790 7         22 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 14348 my($str,$from,$to) = @_;
828 14 50       50 $from = $dmb->_now('tz') if (! $from);
829 14 50       35 $to = $dmb->_now('tz') if (! $to);
830              
831             # Parse the date (ignoring timezone information):
832              
833 14         79 my $err = $dateUT->parse($str);
834 14 50       35 return '' if ($err);
835 14         54 my $d = [ $dateUT->value() ];
836 14 50       37 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         18 my $tmp;
846 14         64 $tmp = $dmt->zone($from,$d);
847 14 50       40 if (! $tmp) {
848 0         0 $tmp = $dmt->zone($from);
849 0 0       0 return '' if (! $tmp);
850             }
851 14         27 $from = $tmp;
852              
853 14         41 $tmp = $dmt->zone($to,$d);
854 14 100       52 if (! $tmp) {
855 2         9 $tmp = $dmt->zone($to);
856 2 50       14 return '' if (! $tmp);
857             }
858 14         24 $to = $tmp;
859              
860 14         59 ($err,$d) = $dmt->convert($d,$from,$to);
861 14 50       39 return '' if ($err);
862 14         59 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 1796 my($str) = @_;
874 2         11 my $err = $date->parse($str);
875 2 50       7 return undef if ($err);
876 2 100       6 if (wantarray) {
877 1         8 my @ret = $date->holiday();
878 1         4 return @ret;
879             } else {
880 1         5 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: