1Pcalc(3) User Contributed Perl Documentation Pcalc(3)
2
3
4
6 Date::Pcalc - Gregorian calendar date calculations
7
9 Keep it small, fast and simple
10
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
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
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
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
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
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
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
3143 This man page documents "Date::Pcalc" version 6.1.
3144
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
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
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
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)