File Coverage

lib/Date/Manip/DM6.pm
Criterion Covered Total %
statement 291 470 61.9
branch 149 282 52.8
condition 43 63 68.2
subroutine 22 40 55.0
pod 34 34 100.0
total 539 889 60.6


line stmt bran cond sub pod time code
1             package Date::Manip::DM6;
2             # Copyright (c) 1995-2026 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 170     170   1023 use strict;
  170         345  
  170         5142  
53 170     170   61706 use integer;
  170         2400  
  170         856  
54 170     170   4895 use warnings;
  170         250  
  170         13056  
55              
56             our $VERSION;
57             $VERSION='6.99';
58              
59             ###########################################################################
60              
61             our ($dmb,$dmt,$date,$delta,$recur,$date2,$dateUT);
62 170     170   140192 use Date::Manip::Date;
  170         575  
  170         7704  
63 170     170   795 use Carp;
  170         218  
  170         736429  
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 170     170 1 42556 my($flag) = @_;
83 170         1680 return $date->version($flag);
84             }
85              
86             sub Date_Init {
87 23     23 1 1856 my(@args) = @_;
88 23         42 my(@args2);
89              
90 23         79 foreach my $arg (@args) {
91 24 50       322 if ($arg =~ /^(\S+)\s*=\s*(.*)$/) {
92 24         152 push(@args2,$1,$2);
93             } else {
94 0         0 carp "ERROR: invalid Date_Init argument: $arg";
95             }
96             }
97 23         112 $date->config(@args2);
98 23         213 return $date->err();
99             }
100              
101             sub ParseDateString {
102 247     247 1 123038 my($string,@opts) = @_;
103 247 50       387 $string = '' if (! defined($string));
104 247         618 my $err = $date->parse($string,@opts);
105 247 100       506 return '' if ($err);
106 203         489 my $ret = $date->value('local');
107 203         847 return $ret;
108             }
109              
110             sub ParseDateFormat {
111 3     3 1 2594 my($format,$string) = @_;
112 3 50       6 $string = '' if (! defined($string));
113 3         15 my $err = $date->parse_format($format,$string);
114 3 50       6 return '' if ($err);
115 3         11 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 23502 my(@a) = @_;
155              
156 33 50 33     97 if (@a < 1 || @a > 2) {
157 0         0 print "ERROR: Invalid number of arguments to ParseDateDelta.\n";
158 0         0 return '';
159             }
160 33         48 my($args,$mode) = @_;
161 33 50       51 $args = '' if (! defined($args));
162 33 100       59 $mode = '' if (! $mode);
163 33         53 $mode = lc($mode);
164 33 50 33     56 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         34 my @args;
170 33         44 my $ref = ref($args);
171 33         34 my $list = 0;
172              
173 33 50       51 if (! $ref) {
    0          
    0          
174 33         40 @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         46 while (@args) {
186 33         52 my $string = join(' ',@args);
187 33         72 my $err = $delta->parse($string);
188 33 100       44 if (! $err) {
189 24 100       41 $delta->convert($mode) if ($mode);
190 24 50       37 splice(@$args,0,$#args+1) if ($list);
191 24         44 my $ret = $delta->value('local');
192 24         108 return $ret;
193             }
194 9         17 pop(@args);
195             }
196              
197 9         29 return '';
198             }
199              
200             sub UnixDate {
201 2     2 1 918 my($string,@in) = @_;
202 2         3 my(@ret);
203              
204 2         15 my $err = $date->parse($string);
205 2 50       4 return () if ($err);
206              
207 2         4 foreach my $in (@in) {
208 2         16 push(@ret,$date->printf($in));
209             }
210              
211 2 50       5 if (! wantarray) {
212 0         0 return join(" ",@ret);
213             }
214 2         11 return @ret;
215             }
216              
217             sub Delta_Format {
218 19     19 1 17614 my($string,@args) = @_;
219              
220 19         45 my $err = $delta->parse($string);
221 19 50       30 return () if ($err);
222              
223 19         21 my($mode,$dec,@in);
224 19 50 100     81 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         27 ($mode,$dec,@in) = (@args);
233 18         22 $mode = lc($mode);
234              
235             } elsif ($args[0] =~ /^\d+$/) {
236 0         0 ($mode,$dec,@in) = ('exact',@args);
237              
238             } else {
239 1         2 $mode = 'exact';
240 1         2 @in = @args;
241             }
242              
243 19 100       30 $dec = 0 if (! $dec);
244 19         27 @in = _Delta_Format_old($mode,$dec,@in);
245              
246 19         22 my @ret = ();
247 19         20 foreach my $in (@in) {
248 19         41 push(@ret,$delta->printf($in));
249             }
250              
251 19 50       25 if (! wantarray) {
252 0         0 return join(" ",@ret);
253             }
254              
255 19         72 return @ret;
256             }
257              
258             sub _Delta_Format_old {
259 19     19   123 my($mode,$dec,@in) = @_;
260 19         18 my(@ret);
261 19         40 my $business = $delta->type('business');
262              
263 19         27 foreach my $in (@in) {
264 19         20 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         29 while ($in) {
270 248 100       627 if ($in =~ s/^([^%]+)//) {
    50          
    100          
271 115         187 $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         183 my($field,$scope) = ($1,$2);
280 126         143 $out .= '%';
281              
282 126 100       204 if ($scope eq 'd') {
    100          
    50          
283 42 100 100     112 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
284 14         22 $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         16 $out .= ".${dec}${field}${field}s";
289             } elsif ($field eq 'w' && $business) {
290 1         2 $out .= ".${dec}www";
291             } elsif (($field eq 'w' || $field eq 'd') && ! $business) {
292 2         4 $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     98 if ($mode eq 'approx') {
    100 100        
    100          
    100          
    100          
    100          
299 14         26 $out .= ".${dec}${field}y${field}";
300             } elsif ($field eq 'y' || $field eq 'M') {
301 8         16 $out .= ".${dec}${field}y${field}";
302             } elsif ($mode eq 'semi') {
303 10         16 $out .= ".${dec}${field}w${field}";
304             } elsif ($field eq 'w') {
305 2         4 $out .= ".${dec}www";
306             } elsif ($field eq 'd' && ! $business) {
307 1         3 $out .= ".${dec}dwd";
308             } elsif ($business) {
309 4         7 $out .= ".${dec}${field}d${field}";
310             } else {
311 3         4 $out .= ".${dec}${field}h${field}";
312             }
313              
314             } elsif ($scope eq 't') {
315 42 100 100     132 if ($mode eq 'approx') {
    100 100        
    100 100        
    100 100        
    100          
    100          
316 14         25 $out .= ".${dec}${field}ys";
317             } elsif ($field eq 'y' || $field eq 'M') {
318 8         13 $out .= ".${dec}${field}yM";
319             } elsif ($mode eq 'semi') {
320 10         15 $out .= ".${dec}${field}ws";
321             } elsif ($field eq 'w' && $business) {
322 1         2 $out .= ".${dec}www";
323             } elsif (($field eq 'w' || $field eq 'd') && ! $business) {
324 2         5 $out .= ".${dec}${field}wd";
325             } elsif ($business) {
326 4         8 $out .= ".${dec}${field}ds";
327             } else {
328 3         6 $out .= ".${dec}${field}hs";
329             }
330             }
331              
332             } else {
333             # It's one of the new formats so don't modify it.
334 7         14 $in =~ s/^%//;
335 7         9 $out .= '%';
336             }
337             }
338              
339 19         32 push(@ret,$out);
340             }
341              
342 19         39 return @ret;
343             }
344              
345             sub DateCalc {
346 120     120 1 84432 my($d1,$d2,@args) = @_;
347              
348             # Handle \$err arg
349              
350 120         143 my($ref,$errref);
351              
352 120 50 66     334 if (@args && ref($args[0])) {
353 0         0 $errref = shift(@args);
354 0         0 $ref = 1;
355             } else {
356 120         134 $ref = 0;
357             }
358              
359             # Parse $d1 and $d2
360              
361 120         135 my ($obj1,$obj2,$err,$usemode);
362 120         141 $usemode = 1;
363              
364 120         385 $obj1 = $date->new_date();
365 120         320 $err = $obj1->parse($d1,'nodelta');
366 120 50       221 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         297 $obj2 = $date->new_date();
377 120         278 $err = $obj2->parse($d2,'nodelta');
378 120 100       228 if ($err) {
379 49         160 $obj2 = $date->new_delta();
380 49         113 $err = $obj2->parse($d2);
381 49 50       67 if ($err) {
382 0 0       0 $$errref = 2 if ($ref);
383 0         0 return '';
384             }
385 49         60 $usemode = 0;
386             }
387              
388             # Handle $mode
389              
390 120         113 my($mode);
391 120 100       172 if (@args) {
392 60         93 $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       222 if (defined($mode)) {
402 60 50       105 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       100 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         134 my $obj3;
450 120 100       142 if ($usemode) {
451 71 100       117 $mode = 'exact' if (! $mode);
452 71         475 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       121 if (exists $tmp{$mode}) {
465 71         96 $mode = $tmp{$mode};
466             } else {
467 0 0       0 $$errref = 3 if ($ref);
468 0         0 return '';
469             }
470              
471 71         172 $obj3 = $obj1->calc($obj2,$mode);
472             } else {
473 49         133 $obj3 = $obj1->calc($obj2);
474             }
475              
476 120         299 my $ret = $obj3->value();
477 120         1696 return $ret;
478             }
479              
480             sub Date_GetPrev {
481 34     34 1 50771 my($string,$dow,$curr,@time) = @_;
482 34         116 my $err = $date->parse($string);
483 34 50       57 return '' if ($err);
484              
485 34 100       56 if (defined($dow)) {
486 11         20 $dow = lc($dow);
487 11 50       68 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         23 $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       81 if ($#time == 0) {
497 7         8 @time = @{ $dmb->split('hms',$time[0]) };
  7         27  
498             }
499              
500 34 100       56 if (@time) {
501 29         53 while ($#time < 2) {
502 7         12 push(@time,0);
503             }
504 29         78 $date->prev($dow,$curr,\@time);
505             } else {
506 5         14 $date->prev($dow,$curr);
507             }
508 34         93 my $ret = $date->value();
509 34         165 return $ret;
510             }
511              
512             sub Date_GetNext {
513 34     34 1 47106 my($string,$dow,$curr,@time) = @_;
514 34         92 my $err = $date->parse($string);
515 34 50       47 return '' if ($err);
516              
517 34 100       57 if (defined($dow)) {
518 11         12 $dow = lc($dow);
519 11 50       38 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         15 $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       48 if ($#time == 0) {
529 7         6 @time = @{ $dmb->split('hms',$time[0]) };
  7         22  
530             }
531              
532 34 100       45 if (@time) {
533 29         48 while ($#time < 2) {
534 7         16 push(@time,0);
535             }
536 29         66 $date->next($dow,$curr,\@time);
537             } else {
538 5         12 $date->next($dow,$curr);
539             }
540 34         86 my $ret = $date->value();
541 34         154 return $ret;
542             }
543              
544             sub Date_SetTime {
545 5     5 1 5433 my($string,@time) = @_;
546              
547 5         23 my $err = $date->parse($string);
548 5 50       9 return '' if ($err);
549              
550 5 100       8 if ($#time == 0) {
551 3         4 @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         14 $date->set('time',\@time);
559 5         13 my $val = $date->value();
560 5         24 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 148960 my($string,@args) = @_;
603              
604 93 50       222 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         372 my $err = $recur->parse($string,@args);
612 93 50       147 return '' if ($err);
613              
614 93 50       169 if (wantarray) {
615 93         264 my @dates = $recur->dates();
616 93         109 my @ret;
617 93         150 foreach my $d (@dates) {
618 363         567 my $val = $d->value();
619 363         538 push(@ret,$val);
620             }
621 93         557 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 14240 my($datestr,@args) = @_;
659              
660             # First argument is always a date
661              
662 8         50 my $err = $date->parse($datestr);
663 8 50       20 return [] if ($err);
664              
665             # Second argument is absent, a date, or 0.
666              
667 8         9 my @list;
668 8         11 my $flag = 0;
669 8         11 my ($date0,$date1);
670              
671 8 100       17 if (! @args) {
672             # absent
673 4         25 @list = $date->list_events('dates');
674              
675             } else {
676             # a date or 0
677 4         7 my $arg = shift(@args);
678 4 100       15 $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       9 if (! $arg) {
685 1         4 my($y,$m,$d) = $date->value();
686 1         4 $date2->set('date',[$y,$m,$d,23,59,59]);
687 1         5 @list = $date->list_events(0, 'dates');
688              
689             } else {
690 3         9 $err = $date2->parse($arg);
691 3 50       29 if ($err) {
692 0         0 carp "ERROR: invalid argument: $arg";
693 0         0 return [];
694             }
695 3         13 @list = $date->list_events($date2, 'dates');
696             }
697             }
698              
699             # Handle the flag
700              
701 8 100       23 if (! $flag) {
702 6         11 my @ret = ();
703 6         12 foreach my $e (@list) {
704 11         20 my($d,@n) = @$e;
705 11         22 my $v = $d->value();
706 11         26 push(@ret,$v,[@n]);
707             }
708 6         45 return \@ret;
709             }
710              
711 2         6 push(@list,[$date2]);
712 2         4 my %ret;
713              
714 2 100       8 if ($flag==1) {
    50          
715 1         4 while ($#list > 0) {
716 4         9 my($d0,@n) = @{ shift(@list) };
  4         11  
717 4         6 my $d1 = $list[0]->[0];
718 4         12 my $delta = $d0->calc($d1);
719              
720 4         6 foreach $flag (@n) {
721 5 50       10 $flag = '' if (! defined($flag));
722 5 100       59 if (exists $ret{$flag}) {
723 2         8 $ret{$flag} = $ret{$flag}->calc($delta);
724             } else {
725 3         8 $ret{$flag} = $delta;
726             }
727             }
728             }
729              
730             } elsif ($flag==2) {
731 1         4 while ($#list > 0) {
732 4         5 my($d0,@n) = @{ shift(@list) };
  4         8  
733 4         6 my $d1 = $list[0]->[0];
734 4         10 my $delta = $d0->calc($d1);
735 4         12 $flag = join("+",sort(@n));
736              
737 4 100       10 if (exists $ret{$flag}) {
738 1         5 $ret{$flag} = $ret{$flag}->calc($delta);
739             } else {
740 3         8 $ret{$flag} = $delta;
741             }
742             }
743              
744             } else {
745 0         0 carp "ERROR: Invalid flag $flag";
746 0         0 return [];
747             }
748              
749 2         6 foreach my $flag (keys %ret) {
750 6         14 $ret{$flag} = $ret{$flag}->value();
751             }
752              
753 2         13 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 7143 my($y,$n) = @_;
788 7         8 my @ret = @{ $dmb->day_of_year($y,$n) };
  7         20  
789 7 100       16 push(@ret,0,0,0) if ($#ret == 2);
790 7         18 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 $currfirst = $dmb->_config('firstday');
806 0         0 $dmb->config('firstday',$first);
807 0         0 my($yy,$ww) = $dmb->week_of_year([$y,$m,$d]);
808 0         0 $dmb->config('firstday',$currfirst);
809 0 0       0 return 0 if ($yy<$y);
810 0 0       0 return 53 if ($yy>$y);
811 0         0 return $ww;
812             }
813              
814             sub Date_LeapYear {
815 0     0 1 0 my($y) = @_;
816 0         0 return $dmb->leapyear($y);
817             }
818              
819             sub Date_DaySuffix {
820 0     0 1 0 my($d) = @_;
821 0         0 return $$dmb{'data'}{'wordlist'}{'nth_dom'}[$d-1];
822             }
823              
824             sub Date_TimeZone {
825 0     0 1 0 my($ret) = $dmb->_now('tz');
826 0         0 return $ret;
827             }
828              
829             sub Date_ConvTZ {
830 14     14 1 16820 my($str,$from,$to) = @_;
831 14 50       36 $from = $dmb->_now('tz') if (! $from);
832 14 50       38 $to = $dmb->_now('tz') if (! $to);
833              
834             # Parse the date (ignoring timezone information):
835              
836 14         80 my $err = $dateUT->parse($str);
837 14 50       25 return '' if ($err);
838 14         52 my $d = [ $dateUT->value() ];
839 14 50       23 return '' if (! $d);
840              
841             # Get the timezone for $from. First, we'll assume that
842             # the date matches exactly (so if the timezone is passed
843             # in as an abbreviation, we'll try to get the timezone
844             # that fits the date/abbrev combination). If we can't,
845             # we'll just assume that the timezone is more generic
846             # and try it without the date.
847              
848 14         17 my $tmp;
849 14         37 $tmp = $dmt->zone($from,$d);
850 14 50       29 if (! $tmp) {
851 0         0 $tmp = $dmt->zone($from);
852 0 0       0 return '' if (! $tmp);
853             }
854 14         25 $from = $tmp;
855              
856 14         39 $tmp = $dmt->zone($to,$d);
857 14 100       43 if (! $tmp) {
858 2         7 $tmp = $dmt->zone($to);
859 2 50       9 return '' if (! $tmp);
860             }
861 14         22 $to = $tmp;
862              
863 14         70 ($err,$d) = $dmt->convert($d,$from,$to);
864 14 50       31 return '' if ($err);
865 14         57 return $dmb->join('date',$d);
866             }
867              
868             sub Date_IsWorkDay {
869 0     0 1 0 my($str,$checktime) = @_;
870 0         0 my $err = $date->parse($str);
871 0 0       0 return '' if ($err);
872 0         0 return $date->is_business_day($checktime);
873             }
874              
875             sub Date_IsHoliday {
876 2     2 1 1908 my($str) = @_;
877 2         11 my $err = $date->parse($str);
878 2 50       4 return undef if ($err);
879 2 100       4 if (wantarray) {
880 1         4 my @ret = $date->holiday();
881 1         11 return @ret;
882             } else {
883 1         15 my $ret = $date->holiday();
884 1         9 return $ret;
885             }
886             }
887              
888             sub Date_Cmp {
889 0     0 1   my($str1,$str2) = @_;
890 0           my $err = $date->parse($str1);
891 0 0         return undef if ($err);
892 0           $err = $date2->parse($str2);
893 0 0         return undef if ($err);
894 0           return $date->cmp($date2);
895             }
896              
897             1;
898             # Local Variables:
899             # mode: cperl
900             # indent-tabs-mode: nil
901             # cperl-indent-level: 3
902             # cperl-continued-statement-offset: 2
903             # cperl-continued-brace-offset: 0
904             # cperl-brace-offset: 0
905             # cperl-brace-imaginary-offset: 0
906             # cperl-label-offset: 0
907             # End: