1Pcalc(3)              User Contributed Perl Documentation             Pcalc(3)
2
3
4

NAME

6       Date::Pcalc - Gregorian calendar date calculations
7

MOTTO

9       Keep it small, fast and simple
10

PREFACE

12       This package consists of a library written in pure Perl providing all
13       sorts of date calculations based on the Gregorian calendar (the one
14       used in all western countries today), thereby complying with all
15       relevant norms and standards: ISO/R 2015-1971, DIN 1355 and, to some
16       extent, ISO 8601 (where applicable).
17
18       (See also http://www.engelschall.com/u/sb/download/Date-Calc/DIN1355/
19       for a scan of part of the "DIN 1355" document (in German)).
20
21       This package is meant as a drop-in replacement for Date::Calc(3), the
22       latter of which is written in C and XS and therefore needs a C compiler
23       in order to build and install (which this one doesn't).
24
25       The module of course handles year numbers of 2000 and above correctly
26       ("Year 2000" or "Y2K" compliance) -- actually all year numbers from 1
27       to the largest positive integer representable on your system (which is
28       at least 32767) can be dealt with.
29
30       This is not true, however, for the import/export functions in this
31       package which are an interface to the internal POSIX date and time
32       functions of your system, which can only cover dates in the following
33       ranges:
34
35        01-Jan-1970 00:00:00 GMT .. 19-Jan-2038 03:14:07 GMT [Unix etc.]
36        01-Jan-1904 00:00:00 LT  .. 06-Feb-2040 06:28:15 LT  [MacOS Classic]
37        (LT = local time)
38
39       Note that this package projects the Gregorian calendar back until the
40       year 1 A.D. -- even though the Gregorian calendar was only adopted in
41       1582, mostly by the Catholic European countries, in obedience to the
42       corresponding decree of Pope Gregory XIII in that year.
43
44       Some (mainly protestant) countries continued to use the Julian calendar
45       (used until then) until as late as the beginning of the 20th century.
46
47       Finally, note that this package is not intended to do everything you
48       could ever imagine automagically for you; it is rather intended to
49       serve as a toolbox (in the best of UNIX spirit and traditions) which
50       should, however, always get you where you want to go.
51
52       See the section "RECIPES" at the bottom of this document for solutions
53       to common problems!
54
55       If nevertheless you can't figure out how to solve a particular problem,
56       please let me know! (See e-mail address at the end of this document.)
57

SYNOPSIS

59         use Date::Pcalc qw(
60             Days_in_Year
61             Days_in_Month
62             Weeks_in_Year
63             leap_year
64             check_date
65             check_time
66             check_business_date
67             Day_of_Year
68             Date_to_Days
69             Day_of_Week
70             Week_Number
71             Week_of_Year
72             Monday_of_Week
73             Nth_Weekday_of_Month_Year
74             Standard_to_Business
75             Business_to_Standard
76             Delta_Days
77             Delta_DHMS
78             Delta_YMD
79             Delta_YMDHMS
80             N_Delta_YMD
81             N_Delta_YMDHMS
82             Normalize_DHMS
83             Add_Delta_Days
84             Add_Delta_DHMS
85             Add_Delta_YM
86             Add_Delta_YMD
87             Add_Delta_YMDHMS
88             Add_N_Delta_YMD
89             Add_N_Delta_YMDHMS
90             System_Clock
91             Today
92             Now
93             Today_and_Now
94             This_Year
95             Gmtime
96             Localtime
97             Mktime
98             Timezone
99             Date_to_Time
100             Time_to_Date
101             Easter_Sunday
102             Decode_Month
103             Decode_Day_of_Week
104             Decode_Language
105             Decode_Date_EU
106             Decode_Date_US
107             Fixed_Window
108             Moving_Window
109             Compress
110             Uncompress
111             check_compressed
112             Compressed_to_Text
113             Date_to_Text
114             Date_to_Text_Long
115             English_Ordinal
116             Calendar
117             Month_to_Text
118             Day_of_Week_to_Text
119             Day_of_Week_Abbreviation
120             Language_to_Text
121             Language
122             Languages
123             Decode_Date_EU2
124             Decode_Date_US2
125             Parse_Date
126             ISO_LC
127             ISO_UC
128         );
129
130         use Date::Pcalc qw(:all);
131
132         Days_in_Year
133             $days = Days_in_Year($year,$month);
134
135         Days_in_Month
136             $days = Days_in_Month($year,$month);
137
138         Weeks_in_Year
139             $weeks = Weeks_in_Year($year);
140
141         leap_year
142             if (leap_year($year))
143
144         check_date
145             if (check_date($year,$month,$day))
146
147         check_time
148             if (check_time($hour,$min,$sec))
149
150         check_business_date
151             if (check_business_date($year,$week,$dow))
152
153         Day_of_Year
154             $doy = Day_of_Year($year,$month,$day);
155
156         Date_to_Days
157             $days = Date_to_Days($year,$month,$day);
158
159         Day_of_Week
160             $dow = Day_of_Week($year,$month,$day);
161
162         Week_Number
163             $week = Week_Number($year,$month,$day);          # DEPRECATED
164
165         Week_of_Year
166             ($week,$year) = Week_of_Year($year,$month,$day); # RECOMMENDED
167             $week = Week_of_Year($year,$month,$day);         # DANGEROUS
168
169         Monday_of_Week
170             ($year,$month,$day) = Monday_of_Week($week,$year);
171
172         Nth_Weekday_of_Month_Year
173             if (($year,$month,$day) =
174             Nth_Weekday_of_Month_Year($year,$month,$dow,$n))
175
176         Standard_to_Business
177             ($year,$week,$dow) =
178             Standard_to_Business($year,$month,$day);
179
180         Business_to_Standard
181             ($year,$month,$day) =
182             Business_to_Standard($year,$week,$dow);
183
184         Delta_Days
185             $Dd = Delta_Days($year1,$month1,$day1,
186                              $year2,$month2,$day2);
187
188         Delta_DHMS
189             ($Dd,$Dh,$Dm,$Ds) =
190             Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
191                        $year2,$month2,$day2, $hour2,$min2,$sec2);
192
193         Delta_YMD
194             ($Dy,$Dm,$Dd) =
195             Delta_YMD($year1,$month1,$day1,
196                       $year2,$month2,$day2);
197
198         Delta_YMDHMS
199             ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) =
200             Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
201                          $year2,$month2,$day2, $hour2,$min2,$sec2);
202
203         N_Delta_YMD
204             ($Dy,$Dm,$Dd) =
205             N_Delta_YMD($year1,$month1,$day1,
206                         $year2,$month2,$day2);
207
208         N_Delta_YMDHMS
209             ($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
210             N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
211                            $year2,$month2,$day2, $hour2,$min2,$sec2);
212
213         Normalize_DHMS
214             ($Dd,$Dh,$Dm,$Ds) =
215             Normalize_DHMS($Dd,$Dh,$Dm,$Ds);
216
217         Add_Delta_Days
218             ($year,$month,$day) =
219             Add_Delta_Days($year,$month,$day,
220                            $Dd);
221
222         Add_Delta_DHMS
223             ($year,$month,$day, $hour,$min,$sec) =
224             Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec,
225                            $Dd,$Dh,$Dm,$Ds);
226
227         Add_Delta_YM
228             ($year,$month,$day) =
229             Add_Delta_YM($year,$month,$day,
230                          $Dy,$Dm);
231
232         Add_Delta_YMD
233             ($year,$month,$day) =
234             Add_Delta_YMD($year,$month,$day,
235                           $Dy,$Dm,$Dd);
236
237         Add_Delta_YMDHMS
238             ($year,$month,$day, $hour,$min,$sec) =
239             Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
240                              $D_y,$D_m,$D_d, $Dh,$Dm,$Ds);
241
242         Add_N_Delta_YMD
243             ($year,$month,$day) =
244             Add_N_Delta_YMD($year,$month,$day,
245                             $Dy,$Dm,$Dd);
246
247         Add_N_Delta_YMDHMS
248             ($year,$month,$day, $hour,$min,$sec) =
249             Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
250                                $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);
251
252         System_Clock
253             ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
254             System_Clock([$gmt]);
255
256         Today
257             ($year,$month,$day) = Today([$gmt]);
258
259         Now
260             ($hour,$min,$sec) = Now([$gmt]);
261
262         Today_and_Now
263             ($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);
264
265         This_Year
266             $year = This_Year([$gmt]);
267
268         Gmtime
269             ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
270             Gmtime([time]);
271
272         Localtime
273             ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
274             Localtime([time]);
275
276         Mktime
277             $time = Mktime($year,$month,$day, $hour,$min,$sec);
278
279         Timezone
280             ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);
281
282         Date_to_Time
283             $time = Date_to_Time($year,$month,$day, $hour,$min,$sec);
284
285         Time_to_Date
286             ($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
287
288         Easter_Sunday
289             ($year,$month,$day) = Easter_Sunday($year);
290
291         Decode_Month
292             if ($month = Decode_Month($string[,$lang]))
293
294         Decode_Day_of_Week
295             if ($dow = Decode_Day_of_Week($string[,$lang]))
296
297         Decode_Language
298             if ($lang = Decode_Language($string))
299
300         Decode_Date_EU
301             if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))
302
303         Decode_Date_US
304             if (($year,$month,$day) = Decode_Date_US($string[,$lang]))
305
306         Fixed_Window
307             $year = Fixed_Window($yy);
308
309         Moving_Window
310             $year = Moving_Window($yy);
311
312         Compress
313             $date = Compress($year,$month,$day);
314
315         Uncompress
316             if (($century,$year,$month,$day) = Uncompress($date))
317
318         check_compressed
319             if (check_compressed($date))
320
321         Compressed_to_Text
322             $string = Compressed_to_Text($date[,$lang]);
323
324         Date_to_Text
325             $string = Date_to_Text($year,$month,$day[,$lang]);
326
327         Date_to_Text_Long
328             $string = Date_to_Text_Long($year,$month,$day[,$lang]);
329
330         English_Ordinal
331             $string = English_Ordinal($number);
332
333         Calendar
334             $string = Calendar($year,$month[,$orthodox[,$lang]]);
335
336         Month_to_Text
337             $string = Month_to_Text($month[,$lang]);
338
339         Day_of_Week_to_Text
340             $string = Day_of_Week_to_Text($dow[,$lang]);
341
342         Day_of_Week_Abbreviation
343             $string = Day_of_Week_Abbreviation($dow[,$lang]);
344
345         Language_to_Text
346             $string = Language_to_Text($lang);
347
348         Language
349             $lang = Language();
350             Language($lang);               # DEPRECATED
351             $oldlang = Language($newlang); # DEPRECATED
352
353         Languages
354             $max_lang = Languages();
355
356         Decode_Date_EU2
357             if (($year,$month,$day) = Decode_Date_EU2($string[,$lang]))
358
359         Decode_Date_US2
360             if (($year,$month,$day) = Decode_Date_US2($string[,$lang]))
361
362         Parse_Date
363             if (($year,$month,$day) = Parse_Date($string[,$lang]))
364
365         ISO_LC
366             $lower = ISO_LC($string);
367
368         ISO_UC
369             $upper = ISO_UC($string);
370
371         Version
372             $string = Date::Pcalc::Version();
373

IMPORTANT NOTES

375       (See the section "RECIPES" at the bottom of this document for solutions
376       to common problems!)
377
378       • "Year 2000" ("Y2K") compliance
379
380         The upper limit for any year number in this module is only given by
381         the size of the largest positive integer that can be represented in a
382         scalar variable on your system, which is at least 32767, according to
383         the ANSI C standard, on which Perl is based (exceptions see below).
384
385         In order to simplify calculations, this module projects the gregorian
386         calendar back until the year 1 A.D. -- i.e., back BEYOND the year
387         1582 when this calendar was first decreed by the Catholic Pope
388         Gregory XIII!
389
390         Therefore, BE SURE TO ALWAYS SPECIFY "1998" WHEN YOU MEAN "1998", for
391         instance, and DO NOT WRITE "98" INSTEAD, because this will in fact
392         perform a calculation based on the year "98" A.D. and NOT "1998"!
393
394         An exception from this rule are the functions which contain the word
395         "compress" in their names (which can only handle years between 1970
396         and 2069 and also accept the abbreviations "00" to "99"), and the
397         functions whose names begin with "Decode_Date_" (which translate year
398         numbers below 100 using a technique known as "moving window").
399
400         If you want to convert a two-digit year number into a full-fledged,
401         four-digit (at least for some years to come ";-)") year number, use
402         the two functions "Fixed_Window()" and "Moving_Window()" (see their
403         description further below).
404
405         Note also that the following import/export functions (which are
406         interfaces to the POSIX functions "time()", "gmtime()", "localtime()"
407         and "mktime()" or (the last two) substitutes for the BSD function
408         "timegm()" and the POSIX function "gmtime()") have a very limited
409         range of representable dates (in contrast to all other functions in
410         this package, which cover virtually any date including and after
411         January 1st 1 A.D.):
412
413                       System_Clock()
414                       Today()
415                       Now()
416                       Today_and_Now()
417                       This_Year()
418                       Gmtime()
419                       Localtime()
420                       Mktime()
421                       Timezone()
422                       Date_to_Time()
423                       Time_to_Date()
424
425         These functions can only deal with dates in the range from
426         01-Jan-1970 00:00:00 GMT to 19-Jan-2038 03:14:07 GMT (the latter
427         limit is only authoritative on 32 bit systems, however, and can (in
428         principle, through a few code changes) be extended somewhat ":-)" on
429         64 bit systems).
430
431         On MacOS Classic, the valid range of dates is between (both included)
432         01-Jan-1904 00:00:00 (local time) to 06-Feb-2040 06:28:15 (local
433         time).
434
435         Note further that the function "Easter_Sunday()" can only be used for
436         years in the range 1583 to 2299.
437
438       • POSIX functions
439
440         Note that the following functions
441
442                       Gmtime()
443                       Localtime()
444                       Mktime()
445                       Timezone()
446
447         are actually wrappers around or based upon the corresponding POSIX
448         functions "time()", "gmtime()", "localtime()" and "mktime()".
449
450         As such, they depend on local settings of the underlying machine such
451         as e.g. the system clock, the time zone and the locale.
452
453         Their results can therefore sometimes be unexpected or counter-
454         intuitive.
455
456         Therefore, no support can be provided for these functions.
457
458         They are supplied "as is", purely for the sake of interoperability.
459
460         Use at your own risk. (You have been warned!)
461
462       • First index
463
464         ALL ranges in this module start with "1", NOT "0"!
465
466         I.e., the day of month, day of week, day of year, month of year, week
467         of year, first valid year number and language ALL start counting at
468         one, NOT zero!
469
470         The only exception is the function "Week_Number()", which may in fact
471         return "0" when the given date actually lies in the last week of the
472         PREVIOUS year, and of course the numbers for hours (0..23), minutes
473         (0..59) and seconds (0..59).
474
475       • Function naming conventions
476
477         Function names completely in lower case indicate a boolean return
478         value.
479
480       • Boolean values
481
482         Boolean values returned from functions in this module are always a
483         numeric zero ("0") for "false" and a numeric one ("1") for "true".
484
485       • Exception handling
486
487         The functions in this module will usually die with a corresponding
488         error message if their input parameters, intermediate results or
489         output values are out of range.
490
491         The following functions handle errors differently:
492
493           -  check_date()
494           -  check_time()
495           -  check_business_date()
496           -  check_compressed()
497
498         (which return a "false" return value when the given input does not
499         represent a valid date or time),
500
501           -  Nth_Weekday_of_Month_Year()
502
503         (which returns an empty list if the requested 5th day of week does
504         not exist),
505
506           -  Decode_Month()
507           -  Decode_Day_of_Week()
508           -  Decode_Language()
509           -  Fixed_Window()
510           -  Moving_Window()
511           -  Compress()
512
513         (which return "0" upon failure or invalid input), and
514
515           -  Decode_Date_EU()
516           -  Decode_Date_US()
517           -  Decode_Date_EU2()
518           -  Decode_Date_US2()
519           -  Parse_Date()
520           -  Uncompress()
521
522         (which return an empty list upon failure or invalid input).
523
524         Note that you can always catch an exception thrown by any of the
525         functions in this module and handle it yourself by enclosing the
526         function call in an ""eval"" with curly brackets and checking the
527         special variable "$@" (see "eval" in perlfunc(1) for details).
528

DESCRIPTION

530       • "use Date::Pcalc qw( Days_in_Year Days_in_Month ... );"
531
532       • "use Date::Pcalc qw(:all);"
533
534         You can either specify the functions you want to import explicitly by
535         enumerating them between the parentheses of the "qw()" operator, or
536         you can use the "":all"" tag instead to import ALL available
537         functions.
538
539       • "$days = Days_in_Year($year,$month);"
540
541         This function returns the sum of the number of days in the months
542         starting with January up to and including "$month" in the given year
543         "$year".
544
545         I.e., ""Days_in_Year(1998,1)"" returns "31", ""Days_in_Year(1998,2)""
546         returns "59", ""Days_in_Year(1998,3)"" returns "90", and so on.
547
548         Note that ""Days_in_Year($year,12)"" returns the number of days in
549         the given year "$year", i.e., either "365" or "366".
550
551       • "$days = Days_in_Month($year,$month);"
552
553         This function returns the number of days in the given month "$month"
554         of the given year "$year".
555
556         The year must always be supplied, even though it is only needed when
557         the month is February, in order to determine whether it is a leap
558         year or not.
559
560         I.e., ""Days_in_Month(1998,1)"" returns "31",
561         ""Days_in_Month(1998,2)"" returns "28", ""Days_in_Month(2000,2)""
562         returns "29", ""Days_in_Month(1998,3)"" returns "31", and so on.
563
564       • "$weeks = Weeks_in_Year($year);"
565
566         This function returns the number of weeks in the given year "$year",
567         i.e., either "52" or "53".
568
569       • "if (leap_year($year))"
570
571         This function returns "true" ("1") if the given year "$year" is a
572         leap year and "false" ("0") otherwise.
573
574       • "if (check_date($year,$month,$day))"
575
576         This function returns "true" ("1") if the given three numerical
577         values "$year", "$month" and "$day" constitute a valid date, and
578         "false" ("0") otherwise.
579
580       • "if (check_time($hour,$min,$sec))"
581
582         This function returns "true" ("1") if the given three numerical
583         values "$hour", "$min" and "$sec" constitute a valid time ("0 <=
584         $hour < 24", "0 <= $min < 60" and "0 <= $sec < 60"), and "false"
585         ("0") otherwise.
586
587       • "if (check_business_date($year,$week,$dow))"
588
589         This function returns "true" ("1") if the given three numerical
590         values "$year", "$week" and "$dow" constitute a valid date in
591         business format, and "false" ("0") otherwise.
592
593         Beware that this function does NOT compute whether a given date is a
594         business day (i.e., Monday to Friday)!
595
596         To do so, use ""(Day_of_Week($year,$month,$day) < 6)"" instead.
597
598       • "$doy = Day_of_Year($year,$month,$day);"
599
600         This function returns the (relative) number of the day of the given
601         date in the given year.
602
603         E.g., ""Day_of_Year($year,1,1)"" returns "1",
604         ""Day_of_Year($year,2,1)"" returns "32", and
605         ""Day_of_Year($year,12,31)"" returns either "365" or "366".
606
607         The day of year is sometimes also referred to as the Julian day (or
608         date), although it has nothing to do with the Julian calendar, the
609         calendar which was used before the Gregorian calendar.
610
611         In order to convert the number returned by this function back into a
612         date, use the function "Add_Delta_Days()" (described further below),
613         as follows:
614
615           $doy = Day_of_Year($year,$month,$day);
616           ($year,$month,$day) = Add_Delta_Days($year,1,1, $doy - 1);
617
618       • "$days = Date_to_Days($year,$month,$day);"
619
620         This function returns the (absolute) number of the day of the given
621         date, where counting starts at the 1st of January of the year 1 A.D.
622
623         I.e., ""Date_to_Days(1,1,1)"" returns "1", ""Date_to_Days(1,12,31)""
624         returns "365", ""Date_to_Days(2,1,1)"" returns "366",
625         ""Date_to_Days(1998,5,1)"" returns "729510", and so on.
626
627         This is sometimes also referred to (not quite correctly) as the
628         Julian date (or day). This may cause confusion, because also the
629         number of the day in a year (from 1 to 365 or 366) is frequently
630         called the "Julian day".
631
632         More confusing still, this has nothing to do with the Julian
633         calendar, which was used BEFORE the Gregorian calendar.
634
635         The Julian calendar was named after famous Julius Caesar, who had
636         instituted it in Roman times. The Julian calendar is less precise
637         than the Gregorian calendar because it has too many leap years
638         compared to the true mean length of a year (but the Gregorian
639         calendar also still has one day too much every 5000 years). Anyway,
640         the Julian calendar was better than what existed before, because
641         rulers had often changed the calendar used until then in arbitrary
642         ways, in order to lengthen their own reign, for instance.
643
644         In order to convert the number returned by this function back into a
645         date, use the function "Add_Delta_Days()" (described further below),
646         as follows:
647
648           $days = Date_to_Days($year,$month,$day);
649           ($year,$month,$day) = Add_Delta_Days(1,1,1, $days - 1);
650
651       • "$dow = Day_of_Week($year,$month,$day);"
652
653         This function returns the number of the day of week of the given
654         date.
655
656         The function returns "1" for Monday, "2" for Tuesday and so on until
657         "7" for Sunday.
658
659         Note that in the Hebrew calendar (on which the Christian calendar is
660         based), the week starts with Sunday and ends with the Sabbath or
661         Saturday (where according to the Genesis (as described in the Bible)
662         the Lord rested from creating the world).
663
664         In medieval times, Catholic Popes have decreed the Sunday to be the
665         official day of rest, in order to dissociate the Christian from the
666         Hebrew belief.
667
668         It appears that this actually happened with the Emperor Constantin,
669         who converted to Christianity but still worshipped the Sun god and
670         therefore moved the Christian sabbath to the day of the Sun.
671
672         Nowadays, the Sunday AND the Saturday are commonly considered (and
673         used as) days of rest, usually referred to as the "week-end".
674
675         Consistent with this practice, current norms and standards (such as
676         ISO/R 2015-1971, DIN 1355 and ISO 8601) define the Monday as the
677         first day of the week.
678
679       • "$week = Week_Number($year,$month,$day);"
680
681         This function returns the number of the week the given date lies in.
682
683         If the given date lies in the LAST week of the PREVIOUS year, "0" is
684         returned.
685
686         If the given date lies in the FIRST week of the NEXT year,
687         ""Weeks_in_Year($year) + 1"" is returned.
688
689       • "($week,$year) = Week_of_Year($year,$month,$day);"
690
691         This function returns the number of the week the given date lies in,
692         as well as the year that week belongs to.
693
694         I.e., if the given date lies in the LAST week of the PREVIOUS year,
695         ""(Weeks_in_Year($year-1), $year-1)"" is returned.
696
697         If the given date lies in the FIRST week of the NEXT year, ""(1,
698         $year+1)"" is returned.
699
700         Otherwise, ""(Week_Number($year,$month,$day), $year)"" is returned.
701
702       • "$week = Week_of_Year($year,$month,$day);"
703
704         In scalar context, this function returns just the week number. This
705         allows you to write ""$week = Week_of_Year($year,$month,$day);""
706         instead of ""($week) = Week_of_Year($year,$month,$day);"" (note the
707         parentheses around "$week").
708
709         If the given date lies in the LAST week of the PREVIOUS year,
710         "Weeks_in_Year($year-1)" is returned.
711
712         If the given date lies in the FIRST week of the NEXT year, "1" is
713         returned.
714
715         Otherwise the return value is identical with that of
716         ""Week_Number($year,$month,$day)"".
717
718         BEWARE that using this function in scalar context is a DANGEROUS
719         feature, because without knowing which year the week belongs to, you
720         might inadvertently assume the wrong one!
721
722         If for instance you are iterating through an interval of dates, you
723         might assume that the week always belongs to the same year as the
724         given date, which unfortunately is WRONG in some cases!
725
726         In many years, the 31st of December for instance belongs to week
727         number one of the FOLLOWING year. Assuming that the year is the same
728         as your date (31st of December, in this example), sends you back to
729         the first week of the CURRENT year - the Monday of which, by the way,
730         in case of bad luck, might actually lie in the year BEFORE the
731         current year!
732
733         This actually happens in 2002, for example.
734
735         So you always need to provide the correct corresponding year number
736         by other means, keeping track of it yourself.
737
738         In case you do not understand this, never mind, but then simply DO
739         NOT USE this function in scalar context!
740
741       • "($year,$month,$day) = Monday_of_Week($week,$year);"
742
743         This function returns the date of the first day of the given week,
744         i.e., the Monday.
745
746         "$year" must be greater than or equal to "1", and "$week" must lie in
747         the range "1" to "Weeks_in_Year($year)".
748
749         Note that you can write ""($year,$month,$day) =
750         Monday_of_Week(Week_of_Year($year,$month,$day));"" in order to
751         calculate the date of the Monday of the same week as the given date.
752
753         If you want to calculate any other day of week in the same week as a
754         given date, use
755
756           @date = Add_Delta_Days(Monday_of_Week(Week_of_Year(@date)),$offset);
757
758         where "$offset = 1" for Tuesday, 2 for Wednesday etc.
759
760       • "if (($year,$month,$day) =
761         Nth_Weekday_of_Month_Year($year,$month,$dow,$n))"
762
763         This function calculates the date of the "$n"th day of week "$dow" in
764         the given month "$month" and year "$year"; such as, for example, the
765         3rd Thursday of a given month and year.
766
767         This can be used to send a notification mail to the members of a
768         group which meets regularly on every 3rd Thursday of a month, for
769         instance.
770
771         (See the section "RECIPES" near the end of this document for a code
772         snippet to actually do so.)
773
774         "$year" must be greater than or equal to "1", "$month" must lie in
775         the range "1" to "12", "$dow" must lie in the range "1" to "7" and
776         "$n" must lie in the range "1" to "5", or a fatal error (with
777         appropriate error message) occurs.
778
779         The function returns an empty list when the 5th of a given day of
780         week does not exist in the given month and year.
781
782       • "($year,$week,$dow) = Standard_to_Business($year,$month,$day);"
783
784         This function converts a given date from standard notation (year,
785         month, day (of month)) to business notation (year, week, day of
786         week).
787
788       • "($year,$month,$day) = Business_to_Standard($year,$week,$dow);"
789
790         This function converts a given date from business notation (year,
791         week, day of week) to standard notation (year, month, day (of
792         month)).
793
794       • "$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);"
795
796         This function returns the difference in days between the two given
797         dates.
798
799         The result is positive if the two dates are in chronological order,
800         i.e., if date #1 comes chronologically BEFORE date #2, and negative
801         if the order of the two dates is reversed.
802
803         The result is zero if the two dates are identical.
804
805       • "($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1,
806         $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"
807
808         This function returns the difference in days, hours, minutes and
809         seconds between the two given dates with times.
810
811         All four return values will be positive if the two dates are in
812         chronological order, i.e., if date #1 comes chronologically BEFORE
813         date #2, and negative (in all four return values!) if the order of
814         the two dates is reversed.
815
816         This is so that the two functions "Delta_DHMS()" and
817         "Add_Delta_DHMS()" (description see further below) are complementary,
818         i.e., mutually inverse:
819
820           Add_Delta_DHMS(@date1,@time1, Delta_DHMS(@date1,@time1, @date2,@time2))
821
822         yields ""(@date2,@time2)"" again, whereas
823
824           Add_Delta_DHMS(@date2,@time2,
825               map(-$_, Delta_DHMS(@date1,@time1, @date2,@time2)))
826
827         yields ""(@date1,@time1)"", and
828
829           Delta_DHMS(@date1,@time1, Add_Delta_DHMS(@date1,@time1, @delta))
830
831         yields "@delta" again.
832
833         The result is zero (in all four return values) if the two dates and
834         times are identical.
835
836       • "($Dy,$Dm,$Dd) = Delta_YMD($year1,$month1,$day1,
837         $year2,$month2,$day2);"
838
839         This function returns the vector
840
841             ( $year2 - $year1, $month2 - $month1, $day2 - $day1 )
842
843         This is called the "one-by-one" semantics.
844
845         Adding the result of this function to the first date always yields
846         the second date again, and adding the negative result (where the
847         signs of all elements of the result vector have been flipped) to the
848         second date gives the first date. See also the description of the
849         function "Add_Delta_YMD()" further below.
850
851         Example:
852
853           (6,2,-30) == Delta_YMD(1996,1,31, 2002,3,1]);
854
855           [1996,1,31] + ( 6, 2,-30) = [2002,3, 1]
856           [2002,3, 1] + (-6,-2, 30) = [1996,1,31]
857
858         An error occurs if any of the two given dates is invalid.
859
860       • "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) = Delta_YMDHMS($year1,$month1,$day1,
861         $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"
862
863         This function is based on the function "Delta_YMD()" above but
864         additionally calculates the time difference. When a carry over from
865         the time difference occurs, the value of "$D_d" is adjusted
866         accordingly, thus giving the correct total date/time difference.
867
868         Arguments are expected to be in chronological order to yield a
869         (usually) positive result.
870
871         In any case, adding the result of this function to the first
872         date/time value ("$year1,$month1,$day1," "$hour1,$min1,$sec1") always
873         gives the second date/time value ("$year2,$month2,$day2,"
874         "$hour2,$min2,$sec2") again, and adding the negative result (with the
875         signs of all elements of the result vector flipped) to the second
876         date/time value gives the first date/time value.
877
878         See the function "Add_Delta_YMDHMS()" further below for adding a
879         date/time value and a date/time difference.
880
881         An error occurs if any of the given two date/time values is invalid.
882
883       • "($Dy,$Dm,$Dd) = N_Delta_YMD($year1,$month1,$day1,
884         $year2,$month2,$day2);"
885
886         This function returns the difference between the two given dates in a
887         more intuitive way (as far as possible - more on that see a bit
888         further below) than the function "Delta_YMD()" described above.
889
890         The "N" which precedes its name is meant to signify "new" or
891         "normalized".
892
893         This function is loosely based on recipe #17 b) (see the section
894         "RECIPES" below near the end of this document).
895
896         However, the code of recipe #17 b) actually does not treat positive
897         and negative values symmetrically and consistently.
898
899         This new routine does.
900
901         The return values of this function are guaranteed to all have the
902         same sign (or to be zero). This is why this function is called
903         "normalized".
904
905         Moreover, the results are guaranteed to be "minimal", in the sense
906         that "|$Dm| < 12" and "|$Dd| < 31" (which is equivalent to $Dm lying
907         in the range "[-11..+11]" and $Dd lying in the range "[-30..+30]").
908
909         When the results are applied (i.e., added) to the first given date in
910         a left-to-right order, the second given date is guaranteed to be
911         obtained, provided that intermediary results are truncated, as done
912         by the function "Add_Delta_YM()" (see further below), i.e., that
913         invalid intermediate dates such as e.g. [2009,2,31] will
914         automatically be transformed into [2009,2,28] (and not "wrapped" into
915         the next month, e.g. to [2009,3,3]).
916
917         This is called the "left-to-right with truncation" semantics.
918
919         Note that reversing the order of the given dates and reversing the
920         sign of each of the result values will not always add up.
921
922         Consider the dates [2008,2,29] and [2009,2,1]: their difference is
923         (0,11,3) ([2008,2,29] plus 11 months is [2009,1,29], which plus 3
924         days is [2009,2,1]), but the difference between [2009,2,1] and
925         [2008,2,29] is (0,-11,-1), and not (0,-11,-3) ([2009,2,1] minus 11
926         months is [2008,3,1], which minus one day is [2008,2,29]).
927
928         Another example: The difference between [1996,2,29] and [1997,2,28]
929         is (1,0,0) (observe the truncation of the invalid date [1997,2,29] to
930         [1997,2,28] here!), whereas the difference between [1997,2,28] and
931         [1996,2,29] is (0,-11,-28) ([1997,2,28] minus 11 months is
932         [1996,3,28], which minus 28 days is not [1996,3,0] but of course
933         [1996,2,29]).
934
935         "Benign" examples such as for instance the difference between
936         [1964,1,3] and [2009,9,10] are completely symmetrical: The difference
937         in this example is (45,8,7), whereas the difference between
938         [2009,9,10] and [1964,1,3] is (-45,-8,-7), as would normally be
939         expected. In this example, the result is also the same as the one
940         returned by "Delta_YMD()".
941
942         All these counter-intuitive effects are due to the fact that months
943         (and due to leap years, also years) do not correspond to a fixed
944         number of days, so the semantics of "plus one month" or "plus one
945         year" are in fact undefined.
946
947         The present function is an attempt to provide a definition which is
948         intuitive most of the time, and at least consistent the rest of the
949         time.
950
951         Other definitions are of course possible, but most often lead to
952         contradictions (e.g., the results and the given first date do not add
953         up to the second given date).
954
955         See the file "datecalc.pl" in the "examples" subdirectory of this
956         distribution for a way to play around with this function, or go to
957         http://www.engelschall.com/u/sb/datecalc/ for the online version.
958
959         An error occurs if any of the two given dates is invalid, or if any
960         intermediate result leads to an invalid date (this does not apply to
961         truncation, however, as explained above).
962
963       • "($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
964         N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
965         $year2,$month2,$day2, $hour2,$min2,$sec2);"
966
967         This function essentially does the same as the function
968         "N_Delta_YMD()" described immediately above, except that also the
969         difference in hours, minutes and seconds is taken into account.
970
971         This function is loosely based on recipe #17 a) (see the section
972         "RECIPES" below near the end of this document).
973
974         However, the code of recipe #17 a) actually does not treat positive
975         and negative values symmetrically and consistently.
976
977         This new routine does.
978
979         The return values of this function (including the time differences)
980         are guaranteed to all have the same sign (or to be zero). This is the
981         reason for the "N" that precedes the name of this function, which is
982         intended to mean "normalized" (or "new").
983
984         Moreover, the results are guaranteed to be "minimal", in the sense
985         that "|$D_m| < 12", "|$D_d| < 31", "|$Dhh| < 24", "|$Dmm| < 60" and
986         "|$Dss| < 60" (which is equivalent to $D_m lying in the range
987         "[-11..+11]", $D_d lying in the range "[-30..+30]", $Dhh lying in the
988         range "[-23..+23]", and $Dmm and $Dss both lying in the range
989         "[-59..+59]").
990
991       • "($Dd,$Dh,$Dm,$Ds) = Normalize_DHMS($Dd,$Dh,$Dm,$Ds);"
992
993         This function takes four arbitrary values for days, hours, minutes
994         and seconds (which may have different signs) and renormalizes them so
995         that the values for hours, minutes and seconds will lie in the ranges
996         "[-23..23]", "[-59..59]" and "[-59..59]", respectively, and so that
997         all four values have the same sign (or are zero).
998
999         The given values are left untouched, i.e., unchanged.
1000
1001       • "($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);"
1002
1003         This function has two principal uses:
1004
1005         First, it can be used to calculate a new date, given an initial date
1006         and an offset (which may be positive or negative) in days, in order
1007         to answer questions like "today plus 90 days -- which date gives
1008         that?".
1009
1010         (In order to add a weeks offset, simply multiply the weeks offset
1011         with "7" and use that as your days offset.)
1012
1013         Second, it can be used to convert the canonical representation of a
1014         date, i.e., the number of that day (where counting starts at the 1st
1015         of January in 1 A.D.), back into a date given as year, month and day.
1016
1017         Because counting starts at "1", you will actually have to subtract
1018         "1" from the canonical date in order to get back the original date:
1019
1020           $canonical = Date_to_Days($year,$month,$day);
1021
1022           ($year,$month,$day) = Add_Delta_Days(1,1,1, $canonical - 1);
1023
1024         Moreover, this function is the inverse of the function
1025         "Delta_Days()":
1026
1027           Add_Delta_Days(@date1, Delta_Days(@date1, @date2))
1028
1029         yields "@date2" again, whereas
1030
1031           Add_Delta_Days(@date2, -Delta_Days(@date1, @date2))
1032
1033         yields "@date1", and
1034
1035           Delta_Days(@date1, Add_Delta_Days(@date1, $delta))
1036
1037         yields "$delta" again.
1038
1039       • "($year,$month,$day, $hour,$min,$sec) =
1040         Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);"
1041
1042         This function serves to add a days, hours, minutes and seconds offset
1043         to a given date and time, in order to answer questions like "today
1044         and now plus 7 days but minus 5 hours and then plus 30 minutes, what
1045         date and time gives that?":
1046
1047           ($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), +7,-5,+30,0);
1048
1049       • "($year,$month,$day) = Add_Delta_YM($year,$month,$day, $Dy,$Dm);"
1050
1051         This function can be used to add a year and/or month offset to a
1052         given date.
1053
1054         In contrast to the function described immediately below
1055         ("Add_Delta_YMD()"), this function does no "wrapping" into the next
1056         month if the day happens to lie outside the valid range for the
1057         resulting year and month (after adding the year and month offsets).
1058         Instead, it simply truncates the day to the last possible day of the
1059         resulting month.
1060
1061         Examples:
1062
1063         Adding an offset of 0 years, 1 month to the date [1999,1,31] would
1064         result in the (invalid) date [1999,2,31]. The function replaces this
1065         result by the (valid) date [1999,2,28].
1066
1067         Adding an offset of 1 year, 1 month to the same date [1999,1,31] as
1068         above would result in the (still invalid) date [2000,2,31]. The
1069         function replaces this result by the valid date [2000,2,29] (because
1070         2000 is a leap year).
1071
1072         Note that the year and month offsets can be negative, and that they
1073         can have different signs.
1074
1075         If you want to additionally add a days offset, use the function
1076         "Add_Delta_Days()" before or after calling "Add_Delta_YM()":
1077
1078           @date2 = Add_Delta_Days( Add_Delta_YM(@date1, $Dy,$Dm), $Dd );
1079           @date2 = Add_Delta_YM( Add_Delta_Days(@date1, $Dd), $Dy,$Dm );
1080
1081         Note that your result may depend on the order in which you call these
1082         two functions!
1083
1084         Consider the date [1999,2,28] and the offsets 0 years, 1 month and 1
1085         day:
1086
1087         [1999,2,28] plus one month is [1999,3,28], plus one day is
1088         [1999,3,29]. [1999,2,28] plus one day is [1999,3,1], plus one month
1089         is [1999,4,1].
1090
1091         (Which is also the reason why the "Add_Delta_YM()" function does not
1092         allow to add a days offset, because this would actually require TWO
1093         functions: One for adding the days offset BEFORE and one for adding
1094         it AFTER applying the year/month offsets.)
1095
1096         An error occurs if the initial date is not valid.
1097
1098         Note that ""Add_Delta_YM( Add_Delta_YM(@date, $Dy,$Dm), -$Dy,-$Dm
1099         );"" will not, in general, return the original date "@date" (consider
1100         the examples given above!).
1101
1102       • "($year,$month,$day) = Add_Delta_YMD($year,$month,$day,
1103         $Dy,$Dm,$Dd);"
1104
1105         This function serves to add a years, months and days offset to a
1106         given date.
1107
1108         (In order to add a weeks offset, simply multiply the weeks offset
1109         with "7" and add this number to your days offset.)
1110
1111         Note that the three offsets for years, months and days are applied
1112         independently from each other. This also allows them to have
1113         different signs.
1114
1115         The years and months offsets are applied first, and the days offset
1116         is applied last.
1117
1118         If the resulting date happens to fall on a day after the end of the
1119         resulting month, like the 32nd of April or the 30th of February, then
1120         the date is simply counted forward into the next month (possibly also
1121         into the next year) by the number of excessive days (e.g., the 32nd
1122         of April will become the 2nd of May).
1123
1124         BEWARE that this behaviour differs from that of previous versions of
1125         this module! In previous versions, the day was simply truncated to
1126         the maximum number of days in the resulting month.
1127
1128         If you want the previous behaviour, use the new function
1129         "Add_Delta_YM()" (described immediately above) plus the function
1130         "Add_Delta_Days()" instead.
1131
1132         BEWARE also that because a year and a month offset is not equivalent
1133         to a fixed number of days, the transformation performed by this
1134         function is NOT ALWAYS REVERSIBLE!
1135
1136         This is in contrast to the functions "Add_Delta_Days()" and
1137         "Add_Delta_DHMS()", which are fully and truly reversible (with the
1138         help of the functions "Delta_Days()" and "Delta_DHMS()", for
1139         instance).
1140
1141         Note that for this same reason,
1142
1143           @date = Add_Delta_YMD(
1144                   Add_Delta_YMD(@date, $Dy,$Dm,$Dd), -$Dy,-$Dm,-$Dd);
1145
1146         will in general NOT return the initial date "@date", even though
1147
1148           @date2 = Add_Delta_YMD( @date1, Delta_YMD(@date1, @date2) );
1149
1150         will always return the second date "@date2", and
1151
1152           @date1 = Add_Delta_YMD( @date2, map(-$_, Delta_YMD(@date1, @date2)) );
1153
1154         which is the same as
1155
1156           @date1 = Add_Delta_YMD( @date2, Delta_YMD(@date2, @date1) );
1157
1158         will always return the first date "@date1".
1159
1160         Examples:
1161
1162           [1996,1,31] + ( 6, 1,-2) = [2002,3,1]
1163           [2002,3, 1] + (-6,-1, 2) = [1996,2,3] # EXPECTED: [1996,1,31]
1164
1165           (6,2,-30) == Delta_YMD(1996,1,31, 2002,3,1);
1166
1167           [1996,1,31] + ( 6, 2,-30) = [2002,3, 1]
1168           [2002,3, 1] + (-6,-2, 30) = [1996,1,31] # OK
1169
1170           (6,1,-2) == Delta_YMD(1996,2,3, 2002,3,1);
1171
1172           [1996,2,3] + ( 6, 1,-2) = [2002,3,1]
1173           [2002,3,1] + (-6,-1, 2) = [1996,2,3] # OK
1174
1175         Note that this is NOT a program bug but NECESSARILY so, because of
1176         the variable lengths of years and months, and hence because of the
1177         ambiguity of the difference between two dates in terms of years,
1178         months and days, i.e., the fact that the difference between two dates
1179         can be expressed in more than one way:
1180
1181           [1996,1,31] + (6,1, -2) = [2002,3,1]
1182           [1996,1,31] + (6,2,-30) = [2002,3,1]
1183
1184       • "($year,$month,$day, $hour,$min,$sec) =
1185         Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec, $D_y,$D_m,$D_d,
1186         $Dh,$Dm,$Ds);"
1187
1188         Same as the function above, except that a time offset may be given in
1189         addition to the year, month and day offset.
1190
1191       • "($year,$month,$day) = Add_N_Delta_YMD($year,$month,$day,
1192         $Dy,$Dm,$Dd);"
1193
1194         This function is actually a shortcut for applying the function
1195         "Add_Delta_YM()" first, followed by the function "Add_Delta_Days()",
1196         i.e., this function does exactly the same as
1197
1198          ($year,$month,$day) = Add_Delta_Days( Add_Delta_YM($year,$month,$day,$Dy,$Dm), $Dd );
1199
1200         Beware that, if necessary, the function "Add_Delta_YM()" truncates
1201         the resulting day of the month to the largest allowable value for
1202         that month, i.e., the (invalid) result [2009,2,31] is automatically
1203         transformed into [2009,2,28].
1204
1205         For more details on this truncation, see the description of the
1206         function "Add_Delta_YM()" further above.
1207
1208         This function is meant to be complementary with the function
1209         "N_Delta_YMD()" described further above.
1210
1211         This means that it is guaranteed that the result returned by
1212
1213           Add_N_Delta_YMD( @date1, N_Delta_YMD(@date1, @date2) );
1214
1215         is always identical with the given date "@date2".
1216
1217         Note however that unlike with function "Add_Delta_YMD()", the reverse
1218         is not true here, i.e.,
1219
1220           ($Dy,$Dm,$Dd) = N_Delta_YMD(@date1,@date2);
1221           @date = Add_N_Delta_YMD(@date2, -$Dy,-$Dm,-$Dd);
1222
1223         will NOT always return the initial date "@date1".
1224
1225         Example:
1226
1227           (0,11,3) == N_Delta_YMD(2008,2,29, 2009,2,1);
1228
1229           [2008,2,29] + (0, 11, 3) = [2009,2, 1]
1230           [2009,2, 1] + (0,-11,-3) = [2008,2,27] # EXPECTED: [2008,2,29]
1231
1232       • "($year,$month,$day, $hour,$min,$sec) =
1233         Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
1234         $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);"
1235
1236         This function essentially does the same as the function
1237         "Add_N_Delta_YMD()" described immediately above, except that also the
1238         difference in hours, minutes and seconds is taken into account.
1239
1240       • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1241         System_Clock([$gmt]);"
1242
1243         If your operating system supports the corresponding system calls
1244         ("time()" and "localtime()" or "gmtime()"), this function will return
1245         the information provided by your system clock, i.e., the current date
1246         and time, the number of the day of year, the number of the day of
1247         week and a flag signaling whether daylight savings time is currently
1248         in effect or not.
1249
1250         The ranges of values returned (and their meanings) are as follows:
1251
1252                 $year   :   1970..2038 (or more)  [Unix etc.]
1253                 $year   :   1904..2040            [MacOS Classic]
1254
1255                 $month  :   1..12
1256                 $day    :   1..31
1257                 $hour   :   0..23
1258                 $min    :   0..59
1259                 $sec    :   0..59    (0..61 on some systems)
1260                 $doy    :   1..366
1261                 $dow    :   1..7
1262                 $dst    :  -1..1
1263
1264         "$doy" is the day of year, sometimes also referred to as the "julian
1265         date", which starts at "1" and goes up to the number of days in that
1266         year.
1267
1268         The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1269         so on until "7" for Sunday.
1270
1271         The daylight savings time flag ("$dst") will be "-1" if this
1272         information is not available on your system, "0" for no daylight
1273         savings time (i.e., winter time) and "1" when daylight savings time
1274         is in effect.
1275
1276         If your operating system does not provide the necessary system calls,
1277         calling this function will result in a fatal "not available on this
1278         system" error message.
1279
1280         If you want to handle this exception yourself, use ""eval"" as
1281         follows:
1282
1283           eval { ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1284             System_Clock(); };
1285
1286           if ($@)
1287           {
1288               # Handle missing system clock
1289               # (For instance, ask user to enter this information manually)
1290           }
1291
1292         Note that curlies ("{" and "}") are used here to delimit the
1293         statement to be "eval"ed (which is the way to catch exceptions in
1294         Perl), and not quotes (which is a way to evaluate Perl expressions at
1295         runtime).
1296
1297         If the optional (boolean) input parameter "$gmt" is given, a "true"
1298         value ("1") will cause "gmtime()" to be used instead of
1299         "localtime()", internally, thus returning Greenwich Mean Time (GMT,
1300         or UTC) instead of local time.
1301
1302       • "($year,$month,$day) = Today([$gmt]);"
1303
1304         This function returns a subset of the values returned by the function
1305         "System_Clock()" (see above for details), namely the current year,
1306         month and day.
1307
1308         A fatal "not available on this system" error message will appear if
1309         the corresponding system calls are not supported by your current
1310         operating system.
1311
1312         If the optional (boolean) input parameter "$gmt" is given, a "true"
1313         value ("1") will cause "gmtime()" to be used instead of
1314         "localtime()", internally, thus returning Greenwich Mean Time (GMT,
1315         or UTC) instead of local time.
1316
1317       • "($hour,$min,$sec) = Now([$gmt]);"
1318
1319         This function returns a subset of the values returned by the function
1320         "System_Clock()" (see above for details), namely the current time
1321         (hours, minutes and full seconds).
1322
1323         A fatal "not available on this system" error message will appear if
1324         the corresponding system calls are not supported by your current
1325         operating system.
1326
1327         If the optional (boolean) input parameter "$gmt" is given, a "true"
1328         value ("1") will cause "gmtime()" to be used instead of
1329         "localtime()", internally, thus returning Greenwich Mean Time (GMT,
1330         or UTC) instead of local time.
1331
1332       • "($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);"
1333
1334         This function returns a subset of the values returned by the function
1335         "System_Clock()" (see above for details), namely the current date
1336         (year, month, day) and time (hours, minutes and full seconds).
1337
1338         A fatal "not available on this system" error message will appear if
1339         the corresponding system calls are not supported by your current
1340         operating system.
1341
1342         If the optional (boolean) input parameter "$gmt" is given, a "true"
1343         value ("1") will cause "gmtime()" to be used instead of
1344         "localtime()", internally, thus returning Greenwich Mean Time (GMT,
1345         or UTC) instead of local time.
1346
1347       • "$year = This_Year([$gmt]);"
1348
1349         This function returns the current year, according to local time.
1350
1351         A fatal "not available on this system" error message will appear if
1352         the corresponding system calls are not supported by your current
1353         operating system.
1354
1355         If the optional (boolean) input parameter "$gmt" is given, a "true"
1356         value ("1") will cause "gmtime()" to be used instead of
1357         "localtime()", internally, thus returning Greenwich Mean Time (GMT,
1358         or UTC) instead of local time. However, this will only make a
1359         difference within a few hours around New Year (unless you are on a
1360         Pacific island, where this can be almost 24 hours).
1361
1362       • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1363         Gmtime([time]);"
1364
1365         This is Date::Pcalc's equivalent of Perl's built-in "gmtime()"
1366         function.  See also "gmtime" in perlfunc(1).
1367
1368         With the optional argument "time" (i.e., seconds since the epoch),
1369         this function will return the corresponding values for that
1370         particular time (instead of the current time when this parameter is
1371         omitted).
1372
1373         The ranges of values returned (and their meanings) are as follows:
1374
1375                 $year   :   1970..2038 (or more)  [Unix etc.]
1376                 $year   :   1904..2040            [MacOS Classic]
1377
1378                 $month  :   1..12
1379                 $day    :   1..31
1380                 $hour   :   0..23
1381                 $min    :   0..59
1382                 $sec    :   0..59
1383                 $doy    :   1..366
1384                 $dow    :   1..7
1385                 $dst    :  -1..1
1386
1387         "$doy" is the day of year, sometimes also referred to as the "julian
1388         date", which starts at "1" and goes up to the number of days in that
1389         year.
1390
1391         The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1392         so on until "7" for Sunday.
1393
1394         The daylight savings time flag ("$dst") will be "-1" if this
1395         information is not available on your system, "0" for no daylight
1396         savings time (i.e., winter time) and "1" when daylight savings time
1397         is in effect.
1398
1399         A fatal "time out of range" error will occur if the given time value
1400         is out of range "[0..(~0>>1)]".
1401
1402         If the time value is omitted, the "time()" function is called
1403         instead, internally.
1404
1405       • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1406         Localtime([time]);"
1407
1408         This is Date::Pcalc's equivalent of Perl's built-in "localtime()"
1409         function.  See also "localtime" in perlfunc(1).
1410
1411         The ranges of values returned (and their meanings) are as follows:
1412
1413                 $year   :   1970..2038 (or more)  [Unix etc.]
1414                 $year   :   1904..2040            [MacOS Classic]
1415
1416                 $month  :   1..12
1417                 $day    :   1..31
1418                 $hour   :   0..23
1419                 $min    :   0..59
1420                 $sec    :   0..59
1421                 $doy    :   1..366
1422                 $dow    :   1..7
1423                 $dst    :  -1..1
1424
1425         "$doy" is the day of year, sometimes also referred to as the "julian
1426         date", which starts at "1" and goes up to the number of days in that
1427         year.
1428
1429         The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1430         so on until "7" for Sunday.
1431
1432         The daylight savings time flag ("$dst") will be "-1" if this
1433         information is not available on your system, "0" for no daylight
1434         savings time (i.e., winter time) and "1" when daylight savings time
1435         is in effect.
1436
1437         A fatal "time out of range" error will occur if the given time value
1438         is out of range "[0..(~0>>1)]".
1439
1440         If the time value is omitted, the "time()" function is called
1441         instead, internally.
1442
1443       • "$time = Mktime($year,$month,$day, $hour,$min,$sec);"
1444
1445         This function converts a date into a time value, i.e., into the
1446         number of seconds since whatever moment in time your system considers
1447         to be the "epoch". On Unix and most other systems this is the number
1448         of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1449         this is the number of seconds since January 1st 1904 at midnight
1450         (local time).
1451
1452         The function is similar to the "POSIX::mktime()" function (see
1453         "mktime" in POSIX(1) for more details), but in contrast to the
1454         latter, it expects dates in the usual ranges used throughout this
1455         module: The year 2001 stays year 2001, and months are numbered from 1
1456         to 12.
1457
1458         A fatal "date out of range" error will occur if the given date cannot
1459         be expressed in terms of seconds since the epoch (this happens for
1460         instance when the date lies before the epoch, or if it is later than
1461         19-Jan-2038 03:14:07 GMT on 32 bit Unix systems, or later than
1462         06-Feb-2040 06:28:15 (local time) on a Macintosh with MacOS Classic).
1463
1464         Just like the "POSIX::mktime()" function, this function uses the
1465         "mktime()" system call, internally.
1466
1467         This means that the given date and time is considered to be in local
1468         time, and that the value returned by this function will depend on
1469         your machine's local settings such as the time zone, whether daylight
1470         savings time is (or was, at the time) in effect, and the system clock
1471         itself.
1472
1473         BEWARE that "mktime()" does not always return the same time value as
1474         fed into "localtime()", when you feed the output of "localtime()"
1475         back into "mktime()", on some systems!
1476
1477         I.e., ""Mktime((Localtime($time))[0..5])"" will not always return the
1478         same value as given in "$time"!
1479
1480         Note that since Perl does not provide any access to the internal
1481         system call "mktime()", in this pure Perl version, "Mktime()" is
1482         calculated as follows:
1483
1484           Date_to_Time(Add_Delta_YMDHMS(@_,map(-$_,(Timezone(Date_to_Time(@_)))[0..5])));
1485
1486         This may or may not yield the same result as "mktime()".
1487
1488         No guarantees whatsoever are given here for that!  Use at your own
1489         risk!
1490
1491       • "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);"
1492
1493         This function returns the difference between "localtime(time)" and
1494         "gmtime(time)", which is the timezone offset in effect for the
1495         current location and the given ""time"".
1496
1497         This offset is positive if you are located to the east of Greenwich,
1498         and is usually negative (except during daylight savings time, in some
1499         locations) if you are located to the west of Greenwich.
1500
1501         Note that this offset is influenced by all of the relevant system
1502         settings and parameters on your machine; such as locales, environment
1503         variables (e.g. ""TZ"") and the system clock itself. See the relevant
1504         documentation on your system for more details.
1505
1506         If the ""time"" is omitted, the "time()" function will be called
1507         automatically, internally (similar to the built-in functions
1508         "localtime()" and "gmtime()" in Perl).
1509
1510         A fatal "time out of range" error will occur if the given time value
1511         is out of range "[0..(~0>>1)]".
1512
1513         The last item of the returned list is a flag which indicates whether
1514         daylight savings time is currently in effect. This flag is negative
1515         (-1) if this information is not available on your system. It is zero
1516         (0) when daylight savings time is off, and positive (+1) when
1517         daylight savings time is on.
1518
1519         Thus you can check very quickly whether daylight savings time is
1520         currently in effect by evaluating this function in scalar context (in
1521         scalar context, Perl returns the last item of a list):
1522
1523           if (scalar Timezone > 0) { # yes, daylight savings time
1524
1525         However, a slightly more efficient way would be this:
1526
1527           if (scalar System_Clock > 0) { # yes, daylight savings time
1528
1529       • "$time = Date_to_Time($year,$month,$day, $hour,$min,$sec);"
1530
1531         This function is a replacement for the BSD function "timegm()" (which
1532         is not available on all Unix systems), which converts a given date
1533         and time into a time value, i.e., into the number of seconds since
1534         whatever moment in time your system considers to be the "epoch". On
1535         Unix and most other systems this is the number of seconds since
1536         January 1st 1970 at midnight (GMT). On MacOS Classic this is the
1537         number of seconds since January 1st 1904 at midnight (local time).
1538
1539         Under Unix, the date and time are considered to be in UTC ("Universal
1540         Time Coordinated", and so is the resulting time value.
1541
1542         UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1543         UTC has leap seconds (in order to account for small variations in the
1544         rotation of the earth, for instance), whereas GMT does not.
1545
1546         Under MacOS Classic, however, both input and output are considered to
1547         be in local time.
1548
1549         The ranges of year and month follow the same rules as throughout the
1550         rest of this module (and not the contorted rules of its Unix
1551         equivalent), i.e., the year "2001" stays "2001" and the month ranges
1552         from 1 to 12.
1553
1554         A fatal "date out of range" error will occur if the given date cannot
1555         be expressed in terms of seconds since the epoch (this happens for
1556         instance when the date lies before the epoch, or if it is later than
1557         19-Jan-2038 03:14:07 GMT on 32 bit Unix systems, or later than
1558         06-Feb-2040 06:28:15 (local time) on a Macintosh with MacOS Classic).
1559
1560         This function should be very fast, because it is implemented in a
1561         very straightforward manner and doesn't use any internal system
1562         calls.
1563
1564         Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1565         guaranteed to be complementary, i.e., that
1566         ""Date_to_Time(Time_to_Date($time))"" and
1567         ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1568         will always return the initial values.
1569
1570       • "($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);"
1571
1572         This function is an alternative to the POSIX "gmtime()" function (and
1573         its built-in Perl equivalent), which converts a given time value into
1574         the corresponding date and time. The given time value must be the
1575         number of seconds since whatever moment in time your system considers
1576         to be the "epoch". On Unix and most other systems this is the number
1577         of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1578         this is the number of seconds since January 1st 1904 at midnight
1579         (local time).
1580
1581         Under Unix, the given time value is considered to be in UTC
1582         ("Universal Time Coordinated", and so is the resulting date and time.
1583
1584         UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1585         UTC has leap seconds (in order to account for small variations in the
1586         rotation of the earth, for instance), whereas GMT does not.
1587
1588         Under MacOS Classic, however, both input and output are considered to
1589         be in local time.
1590
1591         If the input value ""time"" is omitted, the "time()" function will be
1592         called automatically, internally (similar to the built-in functions
1593         "localtime()" and "gmtime()" in Perl).
1594
1595         A fatal "time out of range" error will occur if the given time value
1596         is negative.
1597
1598         This function should be very fast, because it is implemented in a
1599         very straightforward manner and doesn't use any internal system calls
1600         (except for "time()", if the input value is omitted).
1601
1602         Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1603         guaranteed to be complementary, i.e., that
1604         ""Date_to_Time(Time_to_Date($time))"" and
1605         ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1606         will always return the initial values.
1607
1608       • "($year,$month,$day) = Easter_Sunday($year);"
1609
1610         This function calculates the date of Easter Sunday for all years in
1611         the range from 1583 to 2299 (all other year numbers will result in a
1612         fatal "year out of range" error message) using the method known as
1613         the "Gaussian Rule".
1614
1615         Some related christian feast days which depend on the date of Easter
1616         Sunday:
1617
1618           Carnival Monday / Rosenmontag / Veille du Mardi Gras   =  -48 days
1619           Mardi Gras / Karnevalsdienstag / Mardi Gras            =  -47 days
1620           Ash Wednesday / Aschermittwoch / Mercredi des Cendres  =  -46 days
1621           Palm Sunday / Palmsonntag / Dimanche des Rameaux       =   -7 days
1622           Easter Friday / Karfreitag / Vendredi Saint            =   -2 days
1623           Easter Saturday / Ostersamstag / Samedi de Paques      =   -1 day
1624           Easter Monday / Ostermontag / Lundi de Paques          =   +1 day
1625           Ascension of Christ / Christi Himmelfahrt / Ascension  =  +39 days
1626           Whitsunday / Pfingstsonntag / Dimanche de Pentecote    =  +49 days
1627           Whitmonday / Pfingstmontag / Lundi de Pentecote        =  +50 days
1628           Feast of Corpus Christi / Fronleichnam / Fete-Dieu     =  +60 days
1629
1630         Use the offsets shown above to calculate the date of the
1631         corresponding feast day as follows:
1632
1633           ($year,$month,$day) = Add_Delta_Days(Easter_Sunday($year), $offset));
1634
1635       • "if ($month = Decode_Month($string[,$lang]))"
1636
1637         This function takes a string as its argument, which should contain
1638         the name of a month in the given or currently selected language (see
1639         further below for details about the multi-language support of this
1640         package), or any uniquely identifying abbreviation of a month's name
1641         (i.e., the first few letters), and returns the corresponding number
1642         (1..12) upon a successful match, or "0" otherwise (therefore, the
1643         return value can also be used as the conditional expression in an
1644         "if" statement).
1645
1646         Note that the input string may not contain any other characters which
1647         do not pertain to the month's name, especially no leading or trailing
1648         whitespace.
1649
1650         Note also that matching is performed in a case-insensitive manner
1651         (this may depend on the "locale" setting on your current system,
1652         though!)
1653
1654         With "1" ("English") as the given language, the following examples
1655         will all return the value "9":
1656
1657           $month = Decode_Month("s",1);
1658           $month = Decode_Month("Sep",1);
1659           $month = Decode_Month("septemb",1);
1660           $month = Decode_Month("September",1);
1661
1662       • "if ($dow = Decode_Day_of_Week($string[,$lang]))"
1663
1664         This function takes a string as its argument, which should contain
1665         the name of a day of week in the given or currently selected language
1666         (see further below for details about the multi-language support of
1667         this package), or any uniquely identifying abbreviation of the name
1668         of a day of week (i.e., the first few letters), and returns the
1669         corresponding number (1..7) upon a successful match, or "0" otherwise
1670         (therefore, the return value can also be used as the conditional
1671         expression in an "if" statement).
1672
1673         Note that the input string may not contain any other characters which
1674         do not pertain to the name of the day of week, especially no leading
1675         or trailing whitespace.
1676
1677         Note also that matching is performed in a case-insensitive manner
1678         (this may depend on the "locale" setting on your current system,
1679         though!)
1680
1681         With "1" ("English") as the given language, the following examples
1682         will all return the value "3":
1683
1684           $dow = Decode_Day_of_Week("w",1);
1685           $dow = Decode_Day_of_Week("Wed",1);
1686           $dow = Decode_Day_of_Week("wednes",1);
1687           $dow = Decode_Day_of_Week("Wednesday",1);
1688
1689       • "if ($lang = Decode_Language($string))"
1690
1691         This function takes a string as its argument, which should contain
1692         the name of one of the languages supported by this package (IN THIS
1693         VERY LANGUAGE ITSELF), or any uniquely identifying abbreviation of
1694         the name of a language (i.e., the first few letters), and returns its
1695         corresponding internal number (1..14 in the original distribution)
1696         upon a successful match, or "0" otherwise (therefore, the return
1697         value can also be used as the conditional expression in an "if"
1698         statement).
1699
1700         Note that the input string may not contain any other characters which
1701         do not pertain to the name of a language, especially no leading or
1702         trailing whitespace.
1703
1704         Note also that matching is performed in a case-insensitive manner
1705         (this may depend on the "locale" setting on your current system,
1706         though!)
1707
1708         The original distribution supports the following fourteen languages:
1709
1710                     English                    ==>    1    (default)
1711                     Français    (French)       ==>    2
1712                     Deutsch     (German)       ==>    3
1713                     Español     (Spanish)      ==>    4
1714                     Português   (Portuguese)   ==>    5
1715                     Nederlands  (Dutch)        ==>    6
1716                     Italiano    (Italian)      ==>    7
1717                     Norsk       (Norwegian)    ==>    8
1718                     Svenska     (Swedish)      ==>    9
1719                     Dansk       (Danish)       ==>   10
1720                     suomi       (Finnish)      ==>   11
1721                     Magyar      (Hungarian)    ==>   12
1722                     polski      (Polish)       ==>   13
1723                     Romaneste   (Romanian)     ==>   14
1724
1725         See the section "How to install additional languages" in the file
1726         "INSTALL.txt" in this distribution for how to add more languages to
1727         this package.
1728
1729         In the original distribution (no other languages installed), the
1730         following examples will all return the value "3":
1731
1732           $lang = Decode_Language("d");
1733           $lang = Decode_Language("de");
1734           $lang = Decode_Language("Deutsch");
1735
1736         Note that you may not be able to enter the special international
1737         characters in some of the languages' names over the keyboard directly
1738         on some systems.
1739
1740         This should never be a problem, though; just enter an abbreviation of
1741         the name of the language consisting of the first few letters up to
1742         the character before the first special international character.
1743
1744       • "if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))"
1745
1746         This function scans a given string and tries to parse any date which
1747         might be embedded in it.
1748
1749         The function returns an empty list if it can't successfully extract a
1750         valid date from its input string, or else it returns the date found.
1751
1752         The function accepts almost any format, as long as the date is given
1753         in the european order (hence its name) day-month-year.
1754
1755         Thereby, zero or more NON-NUMERIC characters may PRECEDE the day and
1756         FOLLOW the year.
1757
1758         Moreover, zero or more NON-ALPHANUMERIC characters are permitted
1759         BETWEEN these three items (i.e., between day and month and between
1760         month and year).
1761
1762         The month may be given either numerically (i.e., a number from "1" to
1763         "12"), or alphanumerically, i.e., as the name of the month in the
1764         given or currently selected language, or any uniquely identifying
1765         abbreviation thereof.
1766
1767         (See further below for details about the multi-language support of
1768         this package!)
1769
1770         If the year is given as one or two digits only (i.e., if the year is
1771         less than 100), it is mapped to a "window" of +/- 50 years around the
1772         current year, as described by the "Moving_Window()" function (see
1773         further below).
1774
1775         If the day, month and year are all given numerically but WITHOUT any
1776         delimiting characters between them, this string of digits will be
1777         mapped to the day, month and year as follows:
1778
1779                         Length:        Mapping:
1780                           3              dmy
1781                           4              dmyy
1782                           5              dmmyy
1783                           6              ddmmyy
1784                           7              dmmyyyy
1785                           8              ddmmyyyy
1786
1787         (Where "d" stands for "day", "m" stands for "month" and "y" stands
1788         for "year".)
1789
1790         All other strings consisting purely of digits (without any
1791         intervening delimiters) are rejected, i.e., not recognized.
1792
1793         Examples:
1794
1795           "3.1.64"
1796           "3 1 64"
1797           "03.01.64"
1798           "03/01/64"
1799           "3. Jan 1964"
1800           "Birthday: 3. Jan '64 in Backnang/Germany"
1801           "03-Jan-64"
1802           "3.Jan1964"
1803           "3Jan64"
1804           "030164"
1805           "3ja64"
1806           "3164"
1807
1808         Experiment! (See the corresponding example applications in the
1809         "examples" subdirectory of this distribution in order to do so.)
1810
1811       • "if (($year,$month,$day) = Decode_Date_US($string[,$lang]))"
1812
1813         This function scans a given string and tries to parse any date which
1814         might be embedded in it.
1815
1816         The function returns an empty list if it can't successfully extract a
1817         valid date from its input string, or else it returns the date found.
1818
1819         The function accepts almost any format, as long as the date is given
1820         in the U.S. american order (hence its name) month-day-year.
1821
1822         Thereby, zero or more NON-ALPHANUMERIC characters may PRECEDE and
1823         FOLLOW the month (i.e., precede the month and separate it from the
1824         day which follows behind).
1825
1826         Moreover, zero or more NON-NUMERIC characters are permitted BETWEEN
1827         the day and the year, as well as AFTER the year.
1828
1829         The month may be given either numerically (i.e., a number from "1" to
1830         "12"), or alphanumerically, i.e., as the name of the month in the
1831         given or currently selected language, or any uniquely identifying
1832         abbreviation thereof.
1833
1834         (See further below for details about the multi-language support of
1835         this package!)
1836
1837         If the year is given as one or two digits only (i.e., if the year is
1838         less than 100), it is mapped to a "window" of +/- 50 years around the
1839         current year, as described by the "Moving_Window()" function (see
1840         further below).
1841
1842         If the month, day and year are all given numerically but WITHOUT any
1843         delimiting characters between them, this string of digits will be
1844         mapped to the month, day and year as follows:
1845
1846                         Length:        Mapping:
1847                           3              mdy
1848                           4              mdyy
1849                           5              mddyy
1850                           6              mmddyy
1851                           7              mddyyyy
1852                           8              mmddyyyy
1853
1854         (Where "m" stands for "month", "d" stands for "day" and "y" stands
1855         for "year".)
1856
1857         All other strings consisting purely of digits (without any
1858         intervening delimiters) are rejected, i.e., not recognized.
1859
1860         If only the day and the year form a contiguous string of digits, they
1861         will be mapped as follows:
1862
1863                         Length:        Mapping:
1864                           2              dy
1865                           3              dyy
1866                           4              ddyy
1867                           5              dyyyy
1868                           6              ddyyyy
1869
1870         (Where "d" stands for "day" and "y" stands for "year".)
1871
1872         Examples:
1873
1874           "1 3 64"
1875           "01/03/64"
1876           "Jan 3 '64"
1877           "Jan 3 1964"
1878           "===> January 3rd 1964 (birthday)"
1879           "Jan31964"
1880           "Jan364"
1881           "ja364"
1882           "1364"
1883
1884         Experiment! (See the corresponding example applications in the
1885         "examples" subdirectory of this distribution in order to do so.)
1886
1887       • "$year = Fixed_Window($yy);"
1888
1889         This function applies a "fixed window" strategy to two-digit year
1890         numbers in order to convert them into four-digit year numbers.
1891
1892         All other year numbers are passed through unchanged, except for
1893         negative year numbers, which cause the function to return zero ("0")
1894         instead.
1895
1896         Two-digit year numbers ""yy"" below 70 are converted to ""20yy"",
1897         whereas year numbers equal to or greater than 70 (but less than 100)
1898         are converted to ""19yy"".
1899
1900         In the original distribution of this package, the base century is set
1901         to "1900" and the base year to "70" (which is a standard on UNIX
1902         systems), but these constants (also called the "epoch") can actually
1903         be chosen at will.
1904
1905       • "$year = Moving_Window($yy);"
1906
1907         This function applies a "moving window" strategy to two-digit year
1908         numbers in order to convert them into four-digit year numbers,
1909         provided the necessary system calls (system clock) are available.
1910         Otherwise the function falls back to the "fixed window" strategy
1911         described in the function above.
1912
1913         All other year numbers are passed through unchanged, except for
1914         negative year numbers, which cause the function to return zero ("0")
1915         instead.
1916
1917         Two-digit year numbers are mapped according to a "window" of 50 years
1918         in both directions (past and future) around the current year.
1919
1920         That is, two-digit year numbers are first mapped to the same century
1921         as the current year. If the resulting year is smaller than the
1922         current year minus 50, then one more century is added to the result.
1923         If the resulting year is equal to or greater than the current year
1924         plus 50, then a century is subtracted from the result.
1925
1926       • "$date = Compress($year,$month,$day);"
1927
1928         WARNING: This function is legacy code, its use is deprecated!
1929
1930         This function encodes a date in 16 bits, which is the value being
1931         returned.
1932
1933         The encoding scheme is as follows:
1934
1935                     Bit number:    FEDCBA9 8765 43210
1936                     Contents:      yyyyyyy mmmm ddddd
1937
1938         (Where the "yyyyyyy" contain the number of the year, "mmmm" the
1939         number of the month and "ddddd" the number of the day.)
1940
1941         The function returns "0" if the given input values do not represent a
1942         valid date. Therefore, the return value of this function can also be
1943         used as the conditional expression in an "if" statement, in order to
1944         check whether the given input values constitute a valid date).
1945
1946         Through this special encoding scheme, it is possible to COMPARE
1947         compressed dates for equality and order (less than/greater than)
1948         WITHOUT any previous DECODING!
1949
1950         Note however that contiguous dates do NOT necessarily have contiguous
1951         compressed representations!
1952
1953         I.e., incrementing the compressed representation of a date MAY OR MAY
1954         NOT yield a valid new date!
1955
1956         Note also that this function can only handle dates within one
1957         century.
1958
1959         This century can be chosen at will (at compile time of this module)
1960         by defining a base century and year (also called the "epoch"). In the
1961         original distribution of this package, the base century is set to
1962         "1900" and the base year to "70" (which is standard on UNIX systems).
1963
1964         This allows this function to handle dates from "1970" up to "2069".
1965
1966         If the given year is equal to, say, "95", this package will
1967         automatically assume that you really meant "1995" instead. However,
1968         if you specify a year number which is SMALLER than 70, like "64", for
1969         instance, this package will assume that you really meant "2064".
1970
1971         You are not confined to two-digit (abbreviated) year numbers, though.
1972
1973         The function also accepts "full-length" year numbers, provided that
1974         they lie in the supported range (i.e., from "1970" to "2069", in the
1975         original configuration of this package).
1976
1977         Note that this function is maintained mainly for backward
1978         compatibility, and that its use is not recommended.
1979
1980       • "if (($century,$year,$month,$day) = Uncompress($date))"
1981
1982         WARNING: This function is legacy code, its use is deprecated!
1983
1984         This function decodes dates that were encoded previously using the
1985         function "Compress()".
1986
1987         It returns the century, year, month and day of the date encoded in
1988         "$date" if "$date" represents a valid date, or an empty list
1989         otherwise.
1990
1991         The year returned in "$year" is actually a two-digit year number
1992         (i.e., the year number taken modulo 100), and only the expression
1993         ""$century + $year"" yields the "full-length" year number (for
1994         example, "1900 + 95 = 1995").
1995
1996         Note that this function is maintained mainly for backward
1997         compatibility, and that its use is not recommended.
1998
1999       • "if (check_compressed($date))"
2000
2001         WARNING: This function is legacy code, its use is deprecated!
2002
2003         This function returns "true" ("1") if the given input value
2004         constitutes a valid compressed date, and "false" ("0") otherwise.
2005
2006         Note that this function is maintained mainly for backward
2007         compatibility, and that its use is not recommended.
2008
2009       • "$string = Compressed_to_Text($date[,$lang]);"
2010
2011         WARNING: This function is legacy code, its use is deprecated!
2012
2013         This function returns a string of fixed length (always 9 characters
2014         long) containing a textual representation of the compressed date
2015         encoded in "$date".
2016
2017         This string has the form "dd-Mmm-yy", where "dd" is the two-digit
2018         number of the day, "Mmm" are the first three letters of the name of
2019         the month in the given or currently selected language (see further
2020         below for details about the multi-language support of this package),
2021         and "yy" is the two-digit year number (i.e., the year number taken
2022         modulo 100).
2023
2024         If "$date" does not represent a valid date, the string "??-???-??" is
2025         returned instead.
2026
2027         Note that this function is maintained mainly for backward
2028         compatibility, and that its use is not recommended.
2029
2030       • "$string = Date_to_Text($year,$month,$day[,$lang]);"
2031
2032         This function returns a string containing a textual representation of
2033         the given date of the form "www dd-Mmm-yyyy", where "www" are the
2034         first three letters of the name of the day of week in the given or
2035         currently selected language, or a special abbreviation, if special
2036         abbreviations have been defined for the given or currently selected
2037         language (see further below for details about the multi-language
2038         support of this package), "dd" is the day (one or two digits), "Mmm"
2039         are the first three letters of the name of the month in the given or
2040         currently selected language, and "yyyy" is the number of the year in
2041         full length.
2042
2043         If the given input values do not constitute a valid date, a fatal
2044         "not a valid date" error occurs.
2045
2046         (See the section "RECIPES" near the end of this document for a code
2047         snippet for how to print dates in any format you like.)
2048
2049       • "$string = Date_to_Text_Long($year,$month,$day[,$lang]);"
2050
2051         This function returns a string containing a textual representation of
2052         the given date roughly of the form "Wwwwww, dd Mmmmmm yyyy", where
2053         "Wwwwww" is the name of the day of week in the given or currently
2054         selected language (see further below for details about the multi-
2055         language support of this package), "dd" is the day (one or two
2056         digits), "Mmmmmm" is the name of the month in the given or currently
2057         selected language, and "yyyy" is the number of the year in full
2058         length.
2059
2060         The exact format of the output string depends on the given or
2061         currently selected language. In the original distribution of this
2062         package, these formats are defined as follows:
2063
2064           1  English    :  "Wwwwww, Mmmmmm ddth yyyy"
2065           2  French     :  "Wwwwww dd mmmmmm yyyy"
2066           3  German     :  "Wwwwww, den dd. Mmmmmm yyyy"
2067           4  Spanish    :  "Wwwwww, dd de mmmmmm de yyyy"
2068           5  Portuguese :  "Wwwwww, dia dd de mmmmmm de yyyy"
2069           6  Dutch      :  "Wwwwww, dd mmmmmm yyyy"
2070           7  Italian    :  "Wwwwww, dd Mmmmmm yyyy"
2071           8  Norwegian  :  "wwwwww, dd. mmmmmm yyyy"
2072           9  Swedish    :  "wwwwww, dd mmmmmm yyyy"
2073          10  Danish     :  "wwwwww, dd. mmmmmm yyyy"
2074          11  Finnish    :  "wwwwww, dd. mmmmmmta yyyy"
2075          12  Hungarian  :  "dd. Mmmmmm yyyy., wwwwww"
2076          13  Polish     :  "Wwwwww, dd Mmmmmm yyyy"
2077          14  Romanian   :  "Wwwwww dd Mmmmmm yyyy"
2078
2079         (You can change these formats in the file "Pcalc.pm" before
2080         installing this module in order to suit your personal preferences.)
2081
2082         If the given input values do not constitute a valid date, a fatal
2083         "not a valid date" error occurs.
2084
2085         In order to capitalize the day of week at the beginning of the string
2086         in Norwegian, use
2087         ""ucfirst(Date_to_Text_Long($year,$month,$day,8));"".
2088
2089         (See the section "RECIPES" near the end of this document for an
2090         example on how to print dates in any format you like.)
2091
2092       • "$string = English_Ordinal($number);"
2093
2094         This function returns a string containing the (english) abbreviation
2095         of the ordinal number for the given (cardinal) number "$number".
2096
2097         I.e.,
2098
2099             0  =>  '0th'    10  =>  '10th'    20  =>  '20th'
2100             1  =>  '1st'    11  =>  '11th'    21  =>  '21st'
2101             2  =>  '2nd'    12  =>  '12th'    22  =>  '22nd'
2102             3  =>  '3rd'    13  =>  '13th'    23  =>  '23rd'
2103             4  =>  '4th'    14  =>  '14th'    24  =>  '24th'
2104             5  =>  '5th'    15  =>  '15th'    25  =>  '25th'
2105             6  =>  '6th'    16  =>  '16th'    26  =>  '26th'
2106             7  =>  '7th'    17  =>  '17th'    27  =>  '27th'
2107             8  =>  '8th'    18  =>  '18th'    28  =>  '28th'
2108             9  =>  '9th'    19  =>  '19th'    29  =>  '29th'
2109
2110         etc.
2111
2112       • "$string = Calendar($year,$month[,$orthodox[,$lang]]);"
2113
2114         This function returns a calendar of the given month in the given year
2115         (somewhat similar to the UNIX ""cal"" command), in the given or
2116         currently selected language (see further below for details about the
2117         multi-language support of this package).
2118
2119         Example:
2120
2121           print Calendar(1998,5);
2122
2123         This will print:
2124
2125                    May 1998
2126           Mon Tue Wed Thu Fri Sat Sun
2127                             1   2   3
2128             4   5   6   7   8   9  10
2129            11  12  13  14  15  16  17
2130            18  19  20  21  22  23  24
2131            25  26  27  28  29  30  31
2132
2133         If the optional boolean parameter "$orthodox" is given and true, the
2134         calendar starts on Sunday instead of Monday.
2135
2136       • "$string = Month_to_Text($month[,$lang]);"
2137
2138         This function returns the name of the given month in the given or
2139         currently selected language (see further below for details about the
2140         multi-language support of this package).
2141
2142         If the given month lies outside of the valid range from "1" to "12",
2143         a fatal "month out of range" error will occur.
2144
2145       • "$string = Day_of_Week_to_Text($dow[,$lang]);"
2146
2147         This function returns the name of the given day of week in the given
2148         or currently selected language (see further below for details about
2149         the multi-language support of this package).
2150
2151         If the given day of week lies outside of the valid range from "1" to
2152         "7", a fatal "day of week out of range" error will occur.
2153
2154       • "$string = Day_of_Week_Abbreviation($dow[,$lang]);"
2155
2156         This function returns the special abbreviation of the name of the
2157         given day of week, IF such special abbreviations have been defined
2158         for the given or currently selected language (see further below for
2159         details about the multi-language support of this package).
2160
2161         (In the original distribution of this package, this was only true for
2162         Portuguese. Starting with version 5.1, abbreviations for Polish have
2163         also been introduced. Starting with version 5.7, the abbreviations
2164         for Portuguese have been disabled. So Polish is currently the only
2165         language to define such special abbreviations.)
2166
2167         If not, the first three letters of the name of the day of week in the
2168         given or currently selected language are returned instead.
2169
2170         If the given day of week lies outside of the valid range from "1" to
2171         "7", a fatal "day of week out of range" error will occur.
2172
2173         Currently, this table of special abbreviations is only used by the
2174         functions "Date_to_Text()" and "Calendar()", internally.
2175
2176       • "$string = Language_to_Text($lang);"
2177
2178         This function returns the name of any language supported by this
2179         package when the internal number representing that language is given
2180         as input.
2181
2182         The original distribution supports the following fourteen languages:
2183
2184                     1   ==>   English                     (default)
2185                     2   ==>   Français    (French)
2186                     3   ==>   Deutsch     (German)
2187                     4   ==>   Español     (Spanish)
2188                     5   ==>   Português   (Portuguese)
2189                     6   ==>   Nederlands  (Dutch)
2190                     7   ==>   Italiano    (Italian)
2191                     8   ==>   Norsk       (Norwegian)
2192                     9   ==>   Svenska     (Swedish)
2193                    10   ==>   Dansk       (Danish)
2194                    11   ==>   suomi       (Finnish)
2195                    12   ==>   Magyar      (Hungarian)
2196                    13   ==>   polski      (Polish)
2197                    14   ==>   Romaneste   (Romanian)
2198
2199         See the section "How to install additional languages" in the file
2200         "INSTALL.txt" in this distribution for how to add more languages to
2201         this package.
2202
2203         See the description of the function "Languages()" further below to
2204         determine how many languages are actually available in a given
2205         installation of this package.
2206
2207       • "$lang = Language();"
2208
2209       • "Language($lang); # DEPRECATED"
2210
2211       • "$oldlang = Language($newlang); # DEPRECATED"
2212
2213         This function can be used to determine which language is currently
2214         selected, and to change the selected language (this latter use is
2215         deprecated, because this global setting may cause conflicts between
2216         threads or modules running concurrently).
2217
2218         Thereby, each language has a unique internal number.
2219
2220         The original distribution contains the following fourteen languages:
2221
2222                     1   ==>   English                     (default)
2223                     2   ==>   Français    (French)
2224                     3   ==>   Deutsch     (German)
2225                     4   ==>   Español     (Spanish)
2226                     5   ==>   Português   (Portuguese)
2227                     6   ==>   Nederlands  (Dutch)
2228                     7   ==>   Italiano    (Italian)
2229                     8   ==>   Norsk       (Norwegian)
2230                     9   ==>   Svenska     (Swedish)
2231                    10   ==>   Dansk       (Danish)
2232                    11   ==>   suomi       (Finnish)
2233                    12   ==>   Magyar      (Hungarian)
2234                    13   ==>   polski      (Polish)
2235                    14   ==>   Romaneste   (Romanian)
2236
2237         See the section "How to install additional languages" in the file
2238         "INSTALL.txt" in this distribution for how to add more languages to
2239         this package.
2240
2241         See the description of the function "Languages()" further below to
2242         determine how many languages are actually available in a given
2243         installation of this package.
2244
2245         BEWARE that in order for your programs to be portable, you should
2246         NEVER actually use the internal number of a language in this package
2247         EXPLICITLY, because the same number could mean different languages on
2248         different systems, depending on what languages have been added to any
2249         given installation of this package.
2250
2251         Therefore, you should always use a statement such as
2252
2253           Language(Decode_Language("Name_of_Language")); # DEPRECATED
2254
2255         or
2256
2257           DateCalc_Function(@parameters,Decode_Language("Name_of_Language")); # RECOMMENDED
2258
2259         to select the desired language, and
2260
2261           $language = Language_to_Text(Language());
2262
2263         or
2264
2265           $old_language = Language_to_Text(Language("Name_of_new_Language")); # DEPRECATED
2266
2267         to determine the (previously) selected language.
2268
2269         If the so chosen language is not available in the current
2270         installation, this will result in an appropriate error message,
2271         instead of silently using the wrong (a random) language (which just
2272         happens to have the same internal number in the other installation).
2273
2274         BEWARE that when using the function "Language()", the selected
2275         language is a global setting, shared by all threads or modules you
2276         might be running concurrently, thus possibly causing conflicts
2277         between them.
2278
2279         In order to avoid these conflicts, you should NEVER use the function
2280         "Language()", but should ALWAYS pass a language number (as returned
2281         by the function "Decode_Language()") to the functions which are
2282         language-dependent, which are:
2283
2284         "Decode_Month()", "Decode_Day_of_Week()", "Compressed_to_Text()",
2285         "Date_to_Text()", "Date_to_Text_Long()", "Calendar()",
2286         "Month_to_Text()", "Day_of_Week_to_Text()",
2287         "Day_of_Week_Abbreviation()", "Decode_Date_EU()", "Decode_Date_US()",
2288         "Decode_Date_EU2()", "Decode_Date_US2()", "Parse_Date()".
2289
2290         Note that when you pass an invalid number, such as e.g. zero, or no
2291         language parameter at all, these functions will revert to their
2292         behaviour in the versions of this module prior to 6.0, which means
2293         that the global setting (as set by "Language()") becomes active again
2294         (only in case of an invalid or missing language parameter!).
2295
2296       • "$max_lang = Languages();"
2297
2298         This function returns the (maximum) number of languages which are
2299         currently available in your installation of this package.
2300
2301         (This may vary from installation to installation.)
2302
2303         See the section "How to install additional languages" in the file
2304         "INSTALL.txt" in this distribution for how to add more languages to
2305         this package.
2306
2307         In the original distribution of this package there are fourteen
2308         built-in languages, therefore the value returned by this function
2309         will be "14" if no other languages have been added to your particular
2310         installation.
2311
2312       • "if (($year,$month,$day) = Decode_Date_EU2($string[,$lang))"
2313
2314         This function is the more "Perlish" equivalent of the function
2315         "Decode_Date_EU()" (translated from C), included here merely as an
2316         example to demonstrate how easy it is to write your own routine in
2317         Perl (using regular expressions) adapted to your own special needs,
2318         should the necessity arise, and intended primarily as a basis for
2319         your own development.
2320
2321         In one particular case this more "Perlish" version is actually
2322         slightly more permissive than its equivalent (translated from C), as
2323         far as the class of permitted intervening (i.e., delimiting)
2324         characters is concerned.
2325
2326         (Can you tell the subtle, almost insignificant difference by looking
2327         at the code? Or by experimenting? Hint: Try the string "a3b1c64d"
2328         with both functions.)
2329
2330       • "if (($year,$month,$day) = Decode_Date_US2($string[,$lang))"
2331
2332         This function is the more "Perlish" equivalent of the function
2333         "Decode_Date_US()" (translated from C), included here merely as an
2334         example to demonstrate how easy it is to write your own routine in
2335         Perl (using regular expressions) adapted to your own special needs,
2336         should the necessity arise, and intended primarily as a basis for
2337         your own development.
2338
2339         In one particular case this more "Perlish" version is actually
2340         slightly more permissive than its equivalent (translated from C).
2341
2342         (Hint: This is the same difference as with the "Decode_Date_EU()" and
2343         "Decode_Date_EU2()" pair of functions.)
2344
2345         In a different case, the version translated from C is a little bit
2346         more permissive than its Perl equivalent.
2347
2348         (Can you tell the difference by looking at the code? Or by
2349         experimenting?  Hint: Try the string "(1/364)" with both functions.)
2350
2351       • "if (($year,$month,$day) = Parse_Date($string[,$lang))"
2352
2353         This function is useful for parsing dates as returned by the UNIX
2354         ""date"" command or as found in the headers of e-mail (in order to
2355         determine the date at which some e-mail has been sent or received,
2356         for instance).
2357
2358         Example #1:
2359
2360           ($year,$month,$day) = Parse_Date(`/bin/date`);
2361
2362         Example #2:
2363
2364           while (<MAIL>)
2365           {
2366               if (/^From \S/)
2367               {
2368                   ($year,$month,$day) = Parse_Date($_);
2369                   ...
2370               }
2371               ...
2372           }
2373
2374         The function returns an empty list if it can't extract a valid date
2375         from the input string.
2376
2377       • "$lower = ISO_LC($string);"
2378
2379         Returns a copy of the given string where all letters of the
2380         ISO-Latin-1 character set have been replaced by their lower case
2381         equivalents.
2382
2383         Similar to Perl's built-in function "lc()" (see "lc" in perlfunc(1))
2384         but for the whole ISO-Latin-1 character set, not just plain ASCII.
2385
2386       • "$upper = ISO_UC($string);"
2387
2388         Returns a copy of the given string where all letters of the
2389         ISO-Latin-1 character set have been replaced by their upper case
2390         equivalents.
2391
2392         Similar to Perl's built-in function "uc()" (see "uc" in perlfunc(1))
2393         but for the whole ISO-Latin-1 character set, not just plain ASCII.
2394
2395       • "$string = Date::Pcalc::Version();"
2396
2397         This function returns a string with the (numeric) version number of
2398         the file "Pcalc.pm" at the core of this package.
2399
2400         Note that under all normal circumstances, this version number should
2401         be identical with the one found in the Perl variable
2402         "$Date::Pcalc::VERSION" (the version number of the "Pcalc.pm" file).
2403
2404         Since this function is not exported, you always have to qualify it
2405         explicitly, i.e., "Date::Pcalc::Version()".
2406
2407         This is to avoid possible name space conflicts with version functions
2408         from other modules.
2409

RECIPES

2411       1)  How do I compare two dates?
2412
2413           Solution #1:
2414
2415             use Date::Pcalc qw( Date_to_Days );
2416
2417             if (Date_to_Days($year1,$month1,$day1)  <
2418                 Date_to_Days($year2,$month2,$day2))
2419
2420             if (Date_to_Days($year1,$month1,$day1)  <=
2421                 Date_to_Days($year2,$month2,$day2))
2422
2423             if (Date_to_Days($year1,$month1,$day1)  >
2424                 Date_to_Days($year2,$month2,$day2))
2425
2426             if (Date_to_Days($year1,$month1,$day1)  >=
2427                 Date_to_Days($year2,$month2,$day2))
2428
2429             if (Date_to_Days($year1,$month1,$day1)  ==
2430                 Date_to_Days($year2,$month2,$day2))
2431
2432             if (Date_to_Days($year1,$month1,$day1)  !=
2433                 Date_to_Days($year2,$month2,$day2))
2434
2435             $cmp = (Date_to_Days($year1,$month1,$day1)  <=>
2436                     Date_to_Days($year2,$month2,$day2));
2437
2438           Solution #2:
2439
2440             use Date::Pcalc qw( Delta_Days );
2441
2442             if (Delta_Days($year1,$month1,$day1,
2443                            $year2,$month2,$day2) > 0)
2444
2445             if (Delta_Days($year1,$month1,$day1,
2446                            $year2,$month2,$day2) >= 0)
2447
2448             if (Delta_Days($year1,$month1,$day1,
2449                            $year2,$month2,$day2) < 0)
2450
2451             if (Delta_Days($year1,$month1,$day1,
2452                            $year2,$month2,$day2) <= 0)
2453
2454             if (Delta_Days($year1,$month1,$day1,
2455                            $year2,$month2,$day2) == 0)
2456
2457             if (Delta_Days($year1,$month1,$day1,
2458                            $year2,$month2,$day2) != 0)
2459
2460       2)  How do I check whether a given date lies within a certain range of
2461           dates?
2462
2463             use Date::Pcalc qw( Date_to_Days );
2464
2465             $lower = Date_to_Days($year1,$month1,$day1);
2466             $upper = Date_to_Days($year2,$month2,$day2);
2467
2468             $date = Date_to_Days($year,$month,$day);
2469
2470             if (($date >= $lower) && ($date <= $upper))
2471             {
2472                 # ok
2473             }
2474             else
2475             {
2476                 # not ok
2477             }
2478
2479       3)  How do I compare two dates with times? How do I check whether two
2480           dates and times lie more or less than a given time interval apart?
2481
2482           Solution #1:
2483
2484             use Date::Pcalc qw( Add_Delta_DHMS Date_to_Days );
2485
2486             @date1 = (2002,8,31,23,59,1);
2487             @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2488
2489             #@date1 = (2002,8,31,22,59,1);
2490             #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2491
2492             # Omit the next line if you just want to compare the two dates
2493             # (and change @date3 and @d3 to @date1 and @d1, respectively):
2494
2495             @date3 = Add_Delta_DHMS(@date1, 0,12,0,0); # ==> is the difference within 12 hours?
2496
2497             @d2 = ( Date_to_Days(@date2[0..2]), ($date2[3]*60+$date2[4])*60+$date2[5] );
2498             @d3 = ( Date_to_Days(@date3[0..2]), ($date3[3]*60+$date3[4])*60+$date3[5] );
2499
2500             @diff = ( $d2[0]-$d3[0], $d2[1]-$d3[1] );
2501
2502             if ($diff[0] > 0 and $diff[1] < 0) { $diff[0]--; $diff[1] += 86400; }
2503             if ($diff[0] < 0 and $diff[1] > 0) { $diff[0]++; $diff[1] -= 86400; }
2504
2505             if (($diff[0] || $diff[1]) >= 0) { print "More than 12 hours.\n"; }
2506             else                             { print "Less than 12 hours.\n"; }
2507
2508           Solution #2:
2509
2510           This solution is only feasible if your dates are guaranteed to lie
2511           within the range given by your system's epoch and overflow date and
2512           time!
2513
2514                Unix:    1-Jan-1970 00:00:00  to  19-Jan-2038 03:14:07
2515                MacOS:   1-Jan-1904 00:00:00  to   6-Feb-2040 06:28:15
2516
2517             use Date::Pcalc qw( Date_to_Time );
2518
2519             @date1 = (2002,8,31,23,59,1);
2520             @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2521
2522             #@date1 = (2002,8,31,22,59,1);
2523             #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2524
2525             $d1 = Date_to_Time(@date1);
2526             $d2 = Date_to_Time(@date2);
2527
2528             if ($d1 <= $d2) { print "The two dates are in chronological order.\n"; }
2529             else            { print "The two dates are in reversed order.\n"; }
2530
2531             if ($d1 + 12*60*60 <= $d2) { print "More than 12 hours.\n"; }
2532             else                       { print "Less than 12 hours.\n"; }
2533
2534       4)  How do I verify whether someone has a certain age?
2535
2536             use Date::Pcalc qw( Decode_Date_EU Today leap_year Delta_Days );
2537
2538             $date = <STDIN>; # get birthday
2539
2540             ($year1,$month1,$day1) = Decode_Date_EU($date);
2541
2542             ($year2,$month2,$day2) = Today();
2543
2544             if (($day1 == 29) && ($month1 == 2) && !leap_year($year2))
2545                 { $day1--; }
2546
2547             if ( (($year2 - $year1) >  18) ||
2548                ( (($year2 - $year1) == 18) &&
2549                (Delta_Days($year2,$month1,$day1, $year2,$month2,$day2) >= 0) ) )
2550             {
2551                 print "Ok - you are over 18.\n";
2552             }
2553             else
2554             {
2555                 print "Sorry - you aren't 18 yet!\n";
2556             }
2557
2558             Or, alternatively (substituting the last "if" statement above):
2559
2560             if (($year1+18 <=> $year2 || $month1 <=> $month2 || $day1 <=> $day2) <= 0)
2561                 { print "Ok - you are over 18.\n"; }
2562             else
2563                 { print "Sorry - you aren't 18 yet!\n"; }
2564
2565       5)  How do I calculate the number of the week of month the current date
2566           lies in?
2567
2568           For example:
2569
2570                       April 1998
2571               Mon Tue Wed Thu Fri Sat Sun
2572                         1   2   3   4   5  =  week #1
2573                 6   7   8   9  10  11  12  =  week #2
2574                13  14  15  16  17  18  19  =  week #3
2575                20  21  22  23  24  25  26  =  week #4
2576                27  28  29  30              =  week #5
2577
2578           Solution:
2579
2580             use Date::Pcalc qw( Today Day_of_Week );
2581
2582             ($year,$month,$day) = Today();
2583
2584             $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;
2585
2586       6)  How do I calculate whether a given date is the 1st, 2nd, 3rd, 4th
2587           or 5th of that day of week in the given month?
2588
2589           For example:
2590
2591                      October 2000
2592               Mon Tue Wed Thu Fri Sat Sun
2593                                         1
2594                 2   3   4   5   6   7   8
2595                 9  10  11  12  13  14  15
2596                16  17  18  19  20  21  22
2597                23  24  25  26  27  28  29
2598                30  31
2599
2600           Is Sunday, the 15th of October 2000, the 1st, 2nd, 3rd, 4th or 5th
2601           Sunday of that month?
2602
2603           Solution:
2604
2605             use Date::Pcalc qw( Day_of_Week Delta_Days
2606                                 Nth_Weekday_of_Month_Year
2607                                 Date_to_Text_Long English_Ordinal
2608                                 Day_of_Week_to_Text Month_to_Text );
2609
2610             ($year,$month,$day) = (2000,10,15);
2611
2612             $dow = Day_of_Week($year,$month,$day);
2613
2614             $n = int( Delta_Days(
2615                       Nth_Weekday_of_Month_Year($year,$month,$dow,1),
2616                       $year,$month,$day)
2617                       / 7) + 1;
2618
2619             printf("%s is the %s %s in %s %d.\n",
2620                 Date_to_Text_Long($year,$month,$day),
2621                 English_Ordinal($n),
2622                 Day_of_Week_to_Text($dow),
2623                 Month_to_Text($month),
2624                 $year);
2625
2626           This prints:
2627
2628             Sunday, October 15th 2000 is the 3rd Sunday in October 2000.
2629
2630       7)  How do I calculate the date of the Wednesday of the same week as
2631           the current date?
2632
2633           Solution #1:
2634
2635             use Date::Pcalc qw( Today Day_of_Week Add_Delta_Days );
2636
2637             $searching_dow = 3; # 3 = Wednesday
2638
2639             @today = Today();
2640
2641             $current_dow = Day_of_Week(@today);
2642
2643             @date = Add_Delta_Days(@today, $searching_dow - $current_dow);
2644
2645           Solution #2:
2646
2647             use Date::Pcalc qw( Today Add_Delta_Days
2648                                 Monday_of_Week Week_of_Year );
2649
2650             $searching_dow = 3; # 3 = Wednesday
2651
2652             @today = Today();
2653
2654             @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
2655                                     $searching_dow - 1 );
2656
2657           Solution #3:
2658
2659             use Date::Pcalc qw( Standard_to_Business Today
2660                                 Business_to_Standard );
2661
2662             @business = Standard_to_Business(Today());
2663
2664             $business[2] = 3; # 3 = Wednesday
2665
2666             @date = Business_to_Standard(@business);
2667
2668       8)  How can I add a week offset to a business date (including across
2669           year boundaries)?
2670
2671             use Date::Pcalc qw( Business_to_Standard Add_Delta_Days
2672                                 Standard_to_Business );
2673
2674             @temp = Business_to_Standard($year,$week,$dow);
2675
2676             @temp = Add_Delta_Days(@temp, $week_offset * 7);
2677
2678             ($year,$week,$dow) = Standard_to_Business(@temp);
2679
2680       9)  How do I calculate the last and the next Saturday for any given
2681           date?
2682
2683             use Date::Pcalc qw( Today Day_of_Week Add_Delta_Days
2684                                 Day_of_Week_to_Text Date_to_Text );
2685
2686             $searching_dow = 6; # 6 = Saturday
2687
2688             @today = Today();
2689
2690             $current_dow = Day_of_Week(@today);
2691
2692             if ($searching_dow == $current_dow)
2693             {
2694                 @prev = Add_Delta_Days(@today,-7);
2695                 @next = Add_Delta_Days(@today,+7);
2696             }
2697             else
2698             {
2699                 if ($searching_dow > $current_dow)
2700                 {
2701                     @next = Add_Delta_Days(@today,
2702                               $searching_dow - $current_dow);
2703                     @prev = Add_Delta_Days(@next,-7);
2704                 }
2705                 else
2706                 {
2707                     @prev = Add_Delta_Days(@today,
2708                               $searching_dow - $current_dow);
2709                     @next = Add_Delta_Days(@prev,+7);
2710                 }
2711             }
2712
2713             $dow = Day_of_Week_to_Text($searching_dow);
2714
2715             print "Today is:      ", ' ' x length($dow),
2716                                          Date_to_Text(@today), "\n";
2717             print "Last $dow was:     ", Date_to_Text(@prev),  "\n";
2718             print "Next $dow will be: ", Date_to_Text(@next),  "\n";
2719
2720           This will print something like:
2721
2722             Today is:              Sun 12-Apr-1998
2723             Last Saturday was:     Sat 11-Apr-1998
2724             Next Saturday will be: Sat 18-Apr-1998
2725
2726       10) How can I calculate the last business day (payday!) of a month?
2727
2728           Solution #1 (holidays NOT taken into account):
2729
2730             use Date::Pcalc qw( Days_in_Month Day_of_Week Add_Delta_Days );
2731
2732             $day = Days_in_Month($year,$month);
2733             $dow = Day_of_Week($year,$month,$day);
2734             if ($dow > 5)
2735             {
2736                 ($year,$month,$day) =
2737                     Add_Delta_Days($year,$month,$day, 5-$dow);
2738             }
2739
2740           Solution #2 (holidays taken into account):
2741
2742           This solution expects a multi-dimensional array "@holiday", which
2743           contains all holidays, as follows: ""$holiday[$year][$month][$day]
2744           = 1;"".
2745
2746           (See the description of the function "Easter_Sunday()" further
2747           above for how to calculate the moving (variable) christian feast
2748           days!)
2749
2750           Days which are not holidays remain undefined or should have a value
2751           of zero in this array.
2752
2753             use Date::Pcalc qw( Days_in_Month Add_Delta_Days Day_of_Week );
2754
2755             $day = Days_in_Month($year,$month);
2756             while (1)
2757             {
2758                 while ($holiday[$year][$month][$day])
2759                 {
2760                     ($year,$month,$day) =
2761                         Add_Delta_Days($year,$month,$day, -1);
2762                 }
2763                 $dow = Day_of_Week($year,$month,$day);
2764                 if ($dow > 5)
2765                 {
2766                     ($year,$month,$day) =
2767                         Add_Delta_Days($year,$month,$day, 5-$dow);
2768                 }
2769                 else { last; }
2770             }
2771
2772           Solution #3 (holidays taken into account, more comfortable, but
2773           requires Date::Pcalendar(3) and Date::Pcalc::Object(3)):
2774
2775             use Date::Pcalc::Object qw( Today Add_Delta_YM Date_to_Text_Long );
2776             use Date::Pcalendar::Profiles qw($Profiles);
2777             use Date::Pcalendar;
2778
2779             $calendar = Date::Pcalendar->new( $Profiles->{'DE-BW'} );
2780
2781             @today = Today();
2782             @nextmonth = Add_Delta_YM(@today[0,1],1, 0,1);
2783
2784             $workaround = $calendar->add_delta_workdays(@nextmonth,+1);
2785             $payday     = $calendar->add_delta_workdays($workaround,-2);
2786
2787             print "Pay day = ", Date_to_Text_Long($payday->date()), "\n";
2788
2789           The "workaround" is necessary due to a bug in the method
2790           "add_delta_workdays()" when adding a negative number of workdays.
2791
2792       11) How do I convert a MS Visual Basic "DATETIME" value into its date
2793           and time constituents?
2794
2795             use Date::Pcalc qw( Add_Delta_DHMS Date_to_Text );
2796
2797             $datetime = "35883.121653";
2798
2799             ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);
2800
2801             ($year,$month,$day, $hour,$min,$sec) =
2802                 Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);
2803
2804             printf("The given date is %s %02d:%02d:%02d\n",
2805                 Date_to_Text($year,$month,$day), $hour, $min, $sec);
2806
2807           This prints:
2808
2809             The given date is Tue 31-Mar-1998 12:16:53
2810
2811           Since I do not have or use Visual Basic, I can't guarantee that the
2812           number format assumed here is really the one used by Visual Basic -
2813           but you get the general idea. ":-)"
2814
2815           Moreover, consider the following:
2816
2817           Morten Sickel <Morten.Sickel@nrpa.no> wrote:
2818
2819           I discovered a bug in Excel (2000): Excel thinks that 1900 was a
2820           leap year. Users should use 31-Dec-1899 as the date to add an Excel
2821           date value to in order to get the correct date.
2822
2823           I found out on the web that this bug originated in Lotus 123, which
2824           made 29-Feb-1900 an "industrial standard". MS chose to keep the bug
2825           in order to be compatible with Lotus 123. But they have not
2826           mentioned anything about it in the help files.
2827
2828       12) How can I send a reminder to members of a group on the day before a
2829           meeting which occurs every first Friday of a month?
2830
2831             use Date::Pcalc qw( Today Date_to_Days Add_Delta_YMD
2832                                 Nth_Weekday_of_Month_Year );
2833
2834             ($year,$month,$day) = Today();
2835
2836             $tomorrow = Date_to_Days($year,$month,$day) + 1;
2837
2838             $dow = 5; # 5 = Friday
2839             $n   = 1; # 1 = First of that day of week
2840
2841             $meeting_this_month = Date_to_Days(
2842                 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2843
2844             ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);
2845
2846             $meeting_next_month = Date_to_Days(
2847                 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2848
2849             if (($tomorrow == $meeting_this_month) ||
2850                 ($tomorrow == $meeting_next_month))
2851             {
2852                 # Send reminder e-mail!
2853             }
2854
2855       13) How can I print a date in a different format than provided by the
2856           functions "Date_to_Text()", "Date_to_Text_Long()" or
2857           "Compressed_to_Text()"?
2858
2859             use Date::Pcalc qw( Today Day_of_Week_to_Text
2860                                 Day_of_Week Month_to_Text
2861                                 English_Ordinal );
2862
2863             ($year,$month,$day) = Today();
2864
2865           For example with leading zeros for the day: "Fri 03-Jan-1964"
2866
2867             printf("%.3s %02d-%.3s-%d\n",
2868                 Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
2869                 $day,
2870                 Month_to_Text($month),
2871                 $year);
2872
2873           For example in U.S. american format: "April 12th, 1998"
2874
2875             $string = sprintf("%s %s, %d",
2876                           Month_to_Text($month),
2877                           English_Ordinal($day),
2878                           $year);
2879
2880           For example in one of the possible formats as specified by
2881           ISO 8601:
2882
2883             @date = ($year,$month,$day,$hour,$min,$sec);
2884             $date = sprintf("%d-%02d-%02d %02d:%02d:%02d", @date);
2885
2886           (See also "printf" in perlfunc(1) and/or "sprintf" in perlfunc(1)!)
2887
2888       14) How can I iterate through a range of dates?
2889
2890             use Date::Pcalc qw( Delta_Days Add_Delta_Days );
2891
2892             @start = (1999,5,27);
2893             @stop  = (1999,6,1);
2894
2895             $j = Delta_Days(@start,@stop);
2896
2897             for ( $i = 0; $i <= $j; $i++ )
2898             {
2899                 @date = Add_Delta_Days(@start,$i);
2900                 printf("%4d/%02d/%02d\n", @date);
2901             }
2902
2903           Note that the loop can be improved; see also the recipe below.
2904
2905       15) How can I create a (Perl) list of dates in a certain range?
2906
2907             use Date::Pcalc qw( Delta_Days Add_Delta_Days Date_to_Text );
2908
2909             sub date_range
2910             {
2911                 my(@date) = (@_)[0,1,2];
2912                 my(@list);
2913                 my($i);
2914
2915                 $i = Delta_Days(@_);
2916                 while ($i-- >= 0)
2917                 {
2918                     push( @list, [ @date ] );
2919                     @date = Add_Delta_Days(@date, 1) if ($i >= 0);
2920                 }
2921                 return(@list);
2922             }
2923
2924             @range = &date_range(1999,11,3, 1999,12,24); # in chronological order
2925
2926             foreach $date (@range)
2927             {
2928                 print Date_to_Text(@{$date}), "\n";
2929             }
2930
2931           Note that you probably shouldn't use this one, because it is much
2932           more efficient to iterate through all the dates (as shown in the
2933           recipe immediately above) than to construct such an array and then
2934           to loop through it. Also, it is much more space-efficient not to
2935           create this array.
2936
2937       16) How can I calculate the difference in days between dates, but
2938           without counting Saturdays and Sundays?
2939
2940             sub Delta_Business_Days
2941             {
2942                 my(@date1) = (@_)[0,1,2];
2943                 my(@date2) = (@_)[3,4,5];
2944                 my($minus,$result,$dow1,$dow2,$diff,$temp);
2945
2946                 $minus  = 0;
2947                 $result = Delta_Days(@date1,@date2);
2948                 if ($result != 0)
2949                 {
2950                     if ($result < 0)
2951                     {
2952                         $minus = 1;
2953                         $result = -$result;
2954                         $dow1 = Day_of_Week(@date2);
2955                         $dow2 = Day_of_Week(@date1);
2956                     }
2957                     else
2958                     {
2959                         $dow1 = Day_of_Week(@date1);
2960                         $dow2 = Day_of_Week(@date2);
2961                     }
2962                     $diff = $dow2 - $dow1;
2963                     $temp = $result;
2964                     if ($diff != 0)
2965                     {
2966                         if ($diff < 0)
2967                         {
2968                             $diff += 7;
2969                         }
2970                         $temp -= $diff;
2971                         $dow1 += $diff;
2972                         if ($dow1 > 6)
2973                         {
2974                             $result--;
2975                             if ($dow1 > 7)
2976                             {
2977                                 $result--;
2978                             }
2979                         }
2980                     }
2981                     if ($temp != 0)
2982                     {
2983                         $temp /= 7;
2984                         $result -= ($temp << 1);
2985                     }
2986                 }
2987                 if ($minus) { return -$result; }
2988                 else        { return  $result; }
2989             }
2990
2991           This solution is probably of little practical value, however,
2992           because it doesn't take legal holidays into account.
2993
2994           See Date::Pcalendar(3) for how to do that.
2995
2996       17) How can I "normalize" the output of the "Delta_YMDHMS()" (or
2997           "Delta_YMD()") function so that it contains only positive values?
2998
2999           I.e., how can I show a difference in date (and time) in a more
3000           human-readable form, for example in order to show how much time
3001           until (or since) the expiration of something (e.g. an account, a
3002           domain, a credit card, etc.) is left (has passed)?
3003
3004           Correct solution: Use the functions "N_Delta_YMDHMS()" and
3005           "N_Delta_YMD()" instead!
3006
3007           The following gives a rudimentary sketch of a (much inferior)
3008           solution, which is maintained here only for historical reasons of
3009           this module:
3010
3011           a) Delta_YMDHMS():
3012
3013             #!perl
3014             use strict;
3015             use Date::Pcalc qw(Today_and_Now Delta_YMDHMS Add_Delta_YMDHMS Delta_DHMS Date_to_Text);
3016
3017             my $today = [Today_and_Now()];
3018             my $target = [2005,1,1,0,0,0];
3019
3020             my $sign = "until";
3021             my $delta = Normalize_Delta_YMDHMS($today,$target);
3022             if ($delta->[0] < 0)
3023             {
3024                 $sign = "since";
3025                 $delta = Normalize_Delta_YMDHMS($target,$today);
3026             }
3027             printf("Today is %s %02d:%02d:%02d\n", Date_to_Text(@{$today}[0..2]), @{$today}[3..5]);
3028             printf
3029             (
3030                 "%d year%s, %d month%s, %d day%s, %d hour%s, %d minute%s, %d second%s %s %s %02d:%02d:%02d\n",
3031                 $delta->[0], (($delta->[0]==1)?'':'s'),
3032                 $delta->[1], (($delta->[1]==1)?'':'s'),
3033                 $delta->[2], (($delta->[2]==1)?'':'s'),
3034                 $delta->[3], (($delta->[3]==1)?'':'s'),
3035                 $delta->[4], (($delta->[4]==1)?'':'s'),
3036                 $delta->[5], (($delta->[5]==1)?'':'s'),
3037                 $sign,
3038                 Date_to_Text(@{$target}[0..2]),
3039                 @{$target}[3..5]
3040             );
3041
3042             sub Normalize_Delta_YMDHMS
3043             {
3044                 my($date1,$date2) = @_;
3045                 my(@delta);
3046
3047                 @delta = Delta_YMDHMS(@$date1,@$date2);
3048                 while ($delta[1] < 0 or
3049                        $delta[2] < 0 or
3050                        $delta[3] < 0 or
3051                        $delta[4] < 0 or
3052                        $delta[5] < 0)
3053                 {
3054                     if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3055                     if ($delta[2] < 0)
3056                     {
3057                         $delta[1]--;
3058                         @delta[2..5] = (0,0,0,0);
3059                         @delta[2..5] = Delta_DHMS(Add_Delta_YMDHMS(@$date1,@delta),@$date2);
3060                     }
3061                     if ($delta[3] < 0) { $delta[2]--; $delta[3] += 24; }
3062                     if ($delta[4] < 0) { $delta[3]--; $delta[4] += 60; }
3063                     if ($delta[5] < 0) { $delta[4]--; $delta[5] += 60; }
3064                 }
3065                 return \@delta;
3066             }
3067
3068           b) Delta_YMD():
3069
3070             #!perl
3071             use strict;
3072             use Date::Pcalc qw(Today Delta_YMD Add_Delta_YM Delta_Days Date_to_Text);
3073
3074             my($sign,$delta);
3075             my $today = [Today()];
3076             my $target = [2005,1,1];
3077
3078             if (Delta_Days(@$today,@$target) < 0)
3079             {
3080                 $sign = "since";
3081                 $delta = Normalize_Delta_YMD($target,$today);
3082             }
3083             else
3084             {
3085                 $sign = "until";
3086                 $delta = Normalize_Delta_YMD($today,$target);
3087             }
3088             print "Today is ", Date_to_Text(@$today), "\n";
3089             printf
3090             (
3091                 "%d year%s, %d month%s, %d day%s %s %s\n",
3092                 $delta->[0], (($delta->[0]==1)?'':'s'),
3093                 $delta->[1], (($delta->[1]==1)?'':'s'),
3094                 $delta->[2], (($delta->[2]==1)?'':'s'),
3095                 $sign,
3096                 Date_to_Text(@$target)
3097             );
3098
3099             sub Normalize_Delta_YMD
3100             {
3101                 my($date1,$date2) = @_;
3102                 my(@delta);
3103
3104                 @delta = Delta_YMD(@$date1,@$date2);
3105                 while ($delta[1] < 0 or $delta[2] < 0)
3106                 {
3107                     if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3108                     if ($delta[2] < 0)
3109                     {
3110                         $delta[1]--;
3111                         $delta[2] = Delta_Days(Add_Delta_YM(@$date1,@delta[0,1]),@$date2);
3112                     }
3113                 }
3114                 return \@delta;
3115             }
3116
3117           Note that for normalizing just a time vector, you can use the
3118           built-in function "Normalize_DHMS()". However, this will yield
3119           either all positive OR all negative values, NOT all positive values
3120           as above.
3121

SEE ALSO

3123       Date::Calc(3), Date::Calc::Util(3), Date::Pcalc::Object(3),
3124       Date::Pcalendar(3), Date::Pcalendar::Year(3),
3125       Date::Pcalendar::Profiles(3).
3126
3127         "The Calendar FAQ":
3128         http://www.tondering.dk/claus/calendar.html
3129         by Claus Tondering <claus@tondering.dk>
3130

BEWARE

3132       When you are using the (deprecated) function "Language()", the language
3133       setting is stored in a global variable.
3134
3135       This may cause conflicts between threads or modules running
3136       concurrently.
3137
3138       Therefore, in order to avoid such conflicts, NEVER use the function
3139       "Language()", but ALWAYS pass a language parameter to the functions
3140       which are language-dependent.
3141

VERSION

3143       This man page documents "Date::Pcalc" version 6.1.
3144

AUTHOR

3146         Steffen Beyer
3147         mailto:STBEY@cpan.org
3148         http://www.engelschall.com/u/sb/download/
3149
3151       Copyright (c) 1995 - 2009 by Steffen Beyer. All rights reserved.
3152

LICENSE

3154       This package is free software; you can redistribute it and/or modify it
3155       under the same terms as Perl itself, i.e., under the terms of the
3156       "Artistic License" or the "GNU General Public License".
3157
3158       Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
3159       distribution for details!
3160

DISCLAIMER

3162       This package is distributed in the hope that it will be useful, but
3163       WITHOUT ANY WARRANTY; without even the implied warranty of
3164       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3165
3166       See the "GNU General Public License" for more details.
3167

POD ERRORS

3169       Hey! The above document had some coding errors, which are explained
3170       below:
3171
3172       Around line 1777:
3173           Non-ASCII character seen before =encoding in 'Français'. Assuming
3174           CP1252
3175
3176
3177
3178perl v5.38.0                      2023-07-20                          Pcalc(3)
Impressum