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
471 fact return "0" when the given date actually lies in the last week of
472 the PREVIOUS year, and of course the numbers for hours (0..23),
473 minutes (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
613 below), 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
646 below), 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
818 complementary, 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
1016 day.
1017
1018 Because counting starts at "1", you will actually have to subtract
1019 "1" from the canonical date in order to get back the original date:
1020
1021 $canonical = Date_to_Days($year,$month,$day);
1022
1023 ($year,$month,$day) = Add_Delta_Days(1,1,1, $canonical - 1);
1024
1025 Moreover, this function is the inverse of the function
1026 ""Delta_Days()"":
1027
1028 Add_Delta_Days(@date1, Delta_Days(@date1, @date2))
1029
1030 yields "@date2" again, whereas
1031
1032 Add_Delta_Days(@date2, -Delta_Days(@date1, @date2))
1033
1034 yields "@date1", and
1035
1036 Delta_Days(@date1, Add_Delta_Days(@date1, $delta))
1037
1038 yields "$delta" again.
1039
1040 · "($year,$month,$day, $hour,$min,$sec) =
1041 Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);"
1042
1043 This function serves to add a days, hours, minutes and seconds offset
1044 to a given date and time, in order to answer questions like "today
1045 and now plus 7 days but minus 5 hours and then plus 30 minutes, what
1046 date and time gives that?":
1047
1048 ($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), +7,-5,+30,0);
1049
1050 · "($year,$month,$day) = Add_Delta_YM($year,$month,$day, $Dy,$Dm);"
1051
1052 This function can be used to add a year and/or month offset to a
1053 given date.
1054
1055 In contrast to the function described immediately below
1056 (""Add_Delta_YMD()""), this function does no "wrapping" into the next
1057 month if the day happens to lie outside the valid range for the
1058 resulting year and month (after adding the year and month offsets).
1059 Instead, it simply truncates the day to the last possible day of the
1060 resulting month.
1061
1062 Examples:
1063
1064 Adding an offset of 0 years, 1 month to the date [1999,1,31] would
1065 result in the (invalid) date [1999,2,31]. The function replaces this
1066 result by the (valid) date [1999,2,28].
1067
1068 Adding an offset of 1 year, 1 month to the same date [1999,1,31] as
1069 above would result in the (still invalid) date [2000,2,31]. The
1070 function replaces this result by the valid date [2000,2,29] (because
1071 2000 is a leap year).
1072
1073 Note that the year and month offsets can be negative, and that they
1074 can have different signs.
1075
1076 If you want to additionally add a days offset, use the function
1077 ""Add_Delta_Days()"" before or after calling ""Add_Delta_YM()"":
1078
1079 @date2 = Add_Delta_Days( Add_Delta_YM(@date1, $Dy,$Dm), $Dd );
1080 @date2 = Add_Delta_YM( Add_Delta_Days(@date1, $Dd), $Dy,$Dm );
1081
1082 Note that your result may depend on the order in which you call these
1083 two functions!
1084
1085 Consider the date [1999,2,28] and the offsets 0 years, 1 month and 1
1086 day:
1087
1088 [1999,2,28] plus one month is [1999,3,28], plus one day is
1089 [1999,3,29]. [1999,2,28] plus one day is [1999,3,1], plus one month
1090 is [1999,4,1].
1091
1092 (Which is also the reason why the ""Add_Delta_YM()"" function does
1093 not allow to add a days offset, because this would actually require
1094 TWO functions: One for adding the days offset BEFORE and one for
1095 adding it AFTER applying the year/month offsets.)
1096
1097 An error occurs if the initial date is not valid.
1098
1099 Note that ""Add_Delta_YM( Add_Delta_YM(@date, $Dy,$Dm), -$Dy,-$Dm
1100 );"" will not, in general, return the original date "@date" (consider
1101 the examples given above!).
1102
1103 · "($year,$month,$day) = Add_Delta_YMD($year,$month,$day,
1104 $Dy,$Dm,$Dd);"
1105
1106 This function serves to add a years, months and days offset to a
1107 given date.
1108
1109 (In order to add a weeks offset, simply multiply the weeks offset
1110 with "7" and add this number to your days offset.)
1111
1112 Note that the three offsets for years, months and days are applied
1113 independently from each other. This also allows them to have
1114 different signs.
1115
1116 The years and months offsets are applied first, and the days offset
1117 is applied last.
1118
1119 If the resulting date happens to fall on a day after the end of the
1120 resulting month, like the 32nd of April or the 30th of February, then
1121 the date is simply counted forward into the next month (possibly also
1122 into the next year) by the number of excessive days (e.g., the 32nd
1123 of April will become the 2nd of May).
1124
1125 BEWARE that this behaviour differs from that of previous versions of
1126 this module! In previous versions, the day was simply truncated to
1127 the maximum number of days in the resulting month.
1128
1129 If you want the previous behaviour, use the new function
1130 ""Add_Delta_YM()"" (described immediately above) plus the function
1131 ""Add_Delta_Days()"" instead.
1132
1133 BEWARE also that because a year and a month offset is not equivalent
1134 to a fixed number of days, the transformation performed by this
1135 function is NOT ALWAYS REVERSIBLE!
1136
1137 This is in contrast to the functions ""Add_Delta_Days()"" and
1138 ""Add_Delta_DHMS()"", which are fully and truly reversible (with the
1139 help of the functions ""Delta_Days()"" and ""Delta_DHMS()"", for
1140 instance).
1141
1142 Note that for this same reason,
1143
1144 @date = Add_Delta_YMD(
1145 Add_Delta_YMD(@date, $Dy,$Dm,$Dd), -$Dy,-$Dm,-$Dd);
1146
1147 will in general NOT return the initial date "@date", even though
1148
1149 @date2 = Add_Delta_YMD( @date1, Delta_YMD(@date1, @date2) );
1150
1151 will always return the second date "@date2", and
1152
1153 @date1 = Add_Delta_YMD( @date2, map(-$_, Delta_YMD(@date1, @date2)) );
1154
1155 which is the same as
1156
1157 @date1 = Add_Delta_YMD( @date2, Delta_YMD(@date2, @date1) );
1158
1159 will always return the first date "@date1".
1160
1161 Examples:
1162
1163 [1996,1,31] + ( 6, 1,-2) = [2002,3,1]
1164 [2002,3, 1] + (-6,-1, 2) = [1996,2,3] # EXPECTED: [1996,1,31]
1165
1166 (6,2,-30) == Delta_YMD(1996,1,31, 2002,3,1);
1167
1168 [1996,1,31] + ( 6, 2,-30) = [2002,3, 1]
1169 [2002,3, 1] + (-6,-2, 30) = [1996,1,31] # OK
1170
1171 (6,1,-2) == Delta_YMD(1996,2,3, 2002,3,1);
1172
1173 [1996,2,3] + ( 6, 1,-2) = [2002,3,1]
1174 [2002,3,1] + (-6,-1, 2) = [1996,2,3] # OK
1175
1176 Note that this is NOT a program bug but NECESSARILY so, because of
1177 the variable lengths of years and months, and hence because of the
1178 ambiguity of the difference between two dates in terms of years,
1179 months and days, i.e., the fact that the difference between two dates
1180 can be expressed in more than one way:
1181
1182 [1996,1,31] + (6,1, -2) = [2002,3,1]
1183 [1996,1,31] + (6,2,-30) = [2002,3,1]
1184
1185 · "($year,$month,$day, $hour,$min,$sec) =
1186 Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec, $D_y,$D_m,$D_d,
1187 $Dh,$Dm,$Ds);"
1188
1189 Same as the function above, except that a time offset may be given in
1190 addition to the year, month and day offset.
1191
1192 · "($year,$month,$day) = Add_N_Delta_YMD($year,$month,$day,
1193 $Dy,$Dm,$Dd);"
1194
1195 This function is actually a shortcut for applying the function
1196 "Add_Delta_YM()" first, followed by the function "Add_Delta_Days()",
1197 i.e., this function does exactly the same as
1198
1199 ($year,$month,$day) = Add_Delta_Days( Add_Delta_YM($year,$month,$day,$Dy,$Dm), $Dd );
1200
1201 Beware that, if necessary, the function "Add_Delta_YM()" truncates
1202 the resulting day of the month to the largest allowable value for
1203 that month, i.e., the (invalid) result [2009,2,31] is automatically
1204 transformed into [2009,2,28].
1205
1206 For more details on this truncation, see the description of the
1207 function "Add_Delta_YM()" further above.
1208
1209 This function is meant to be complementary with the function
1210 "N_Delta_YMD()" described further above.
1211
1212 This means that it is guaranteed that the result returned by
1213
1214 Add_N_Delta_YMD( @date1, N_Delta_YMD(@date1, @date2) );
1215
1216 is always identical with the given date "@date2".
1217
1218 Note however that unlike with function "Add_Delta_YMD()", the reverse
1219 is not true here, i.e.,
1220
1221 ($Dy,$Dm,$Dd) = N_Delta_YMD(@date1,@date2);
1222 @date = Add_N_Delta_YMD(@date2, -$Dy,-$Dm,-$Dd);
1223
1224 will NOT always return the initial date "@date1".
1225
1226 Example:
1227
1228 (0,11,3) == N_Delta_YMD(2008,2,29, 2009,2,1);
1229
1230 [2008,2,29] + (0, 11, 3) = [2009,2, 1]
1231 [2009,2, 1] + (0,-11,-3) = [2008,2,27] # EXPECTED: [2008,2,29]
1232
1233 · "($year,$month,$day, $hour,$min,$sec) =
1234 Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
1235 $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);"
1236
1237 This function essentially does the same as the function
1238 "Add_N_Delta_YMD()" described immediately above, except that also the
1239 difference in hours, minutes and seconds is taken into account.
1240
1241 · "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1242 System_Clock([$gmt]);"
1243
1244 If your operating system supports the corresponding system calls
1245 (""time()"" and ""localtime()"" or ""gmtime()""), this function will
1246 return the information provided by your system clock, i.e., the
1247 current date and time, the number of the day of year, the number of
1248 the day of week and a flag signaling whether daylight savings time is
1249 currently in effect or not.
1250
1251 The ranges of values returned (and their meanings) are as follows:
1252
1253 $year : 1970..2038 (or more) [Unix etc.]
1254 $year : 1904..2040 [MacOS Classic]
1255
1256 $month : 1..12
1257 $day : 1..31
1258 $hour : 0..23
1259 $min : 0..59
1260 $sec : 0..59 (0..61 on some systems)
1261 $doy : 1..366
1262 $dow : 1..7
1263 $dst : -1..1
1264
1265 "$doy" is the day of year, sometimes also referred to as the "julian
1266 date", which starts at "1" and goes up to the number of days in that
1267 year.
1268
1269 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1270 so on until "7" for Sunday.
1271
1272 The daylight savings time flag ("$dst") will be ""-1"" if this
1273 information is not available on your system, "0" for no daylight
1274 savings time (i.e., winter time) and "1" when daylight savings time
1275 is in effect.
1276
1277 If your operating system does not provide the necessary system calls,
1278 calling this function will result in a fatal "not available on this
1279 system" error message.
1280
1281 If you want to handle this exception yourself, use ""eval"" as
1282 follows:
1283
1284 eval { ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1285 System_Clock(); };
1286
1287 if ($@)
1288 {
1289 # Handle missing system clock
1290 # (For instance, ask user to enter this information manually)
1291 }
1292
1293 Note that curlies ("{" and "}") are used here to delimit the
1294 statement to be "eval"ed (which is the way to catch exceptions in
1295 Perl), and not quotes (which is a way to evaluate Perl expressions at
1296 runtime).
1297
1298 If the optional (boolean) input parameter "$gmt" is given, a "true"
1299 value ("1") will cause ""gmtime()"" to be used instead of
1300 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1301 or UTC) instead of local time.
1302
1303 · "($year,$month,$day) = Today([$gmt]);"
1304
1305 This function returns a subset of the values returned by the function
1306 ""System_Clock()"" (see above for details), namely the current year,
1307 month and day.
1308
1309 A fatal "not available on this system" error message will appear if
1310 the corresponding system calls are not supported by your current
1311 operating system.
1312
1313 If the optional (boolean) input parameter "$gmt" is given, a "true"
1314 value ("1") will cause ""gmtime()"" to be used instead of
1315 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1316 or UTC) instead of local time.
1317
1318 · "($hour,$min,$sec) = Now([$gmt]);"
1319
1320 This function returns a subset of the values returned by the function
1321 ""System_Clock()"" (see above for details), namely the current time
1322 (hours, minutes and full seconds).
1323
1324 A fatal "not available on this system" error message will appear if
1325 the corresponding system calls are not supported by your current
1326 operating system.
1327
1328 If the optional (boolean) input parameter "$gmt" is given, a "true"
1329 value ("1") will cause ""gmtime()"" to be used instead of
1330 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1331 or UTC) instead of local time.
1332
1333 · "($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);"
1334
1335 This function returns a subset of the values returned by the function
1336 ""System_Clock()"" (see above for details), namely the current date
1337 (year, month, day) and time (hours, minutes and full seconds).
1338
1339 A fatal "not available on this system" error message will appear if
1340 the corresponding system calls are not supported by your current
1341 operating system.
1342
1343 If the optional (boolean) input parameter "$gmt" is given, a "true"
1344 value ("1") will cause ""gmtime()"" to be used instead of
1345 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1346 or UTC) instead of local time.
1347
1348 · "$year = This_Year([$gmt]);"
1349
1350 This function returns the current year, according to local time.
1351
1352 A fatal "not available on this system" error message will appear if
1353 the corresponding system calls are not supported by your current
1354 operating system.
1355
1356 If the optional (boolean) input parameter "$gmt" is given, a "true"
1357 value ("1") will cause ""gmtime()"" to be used instead of
1358 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1359 or UTC) instead of local time. However, this will only make a
1360 difference within a few hours around New Year (unless you are on a
1361 Pacific island, where this can be almost 24 hours).
1362
1363 · "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1364 Gmtime([time]);"
1365
1366 This is Date::Pcalc's equivalent of Perl's built-in "gmtime()"
1367 function. See also "gmtime" in perlfunc(1).
1368
1369 With the optional argument "time" (i.e., seconds since the epoch),
1370 this function will return the corresponding values for that
1371 particular time (instead of the current time when this parameter is
1372 omitted).
1373
1374 The ranges of values returned (and their meanings) are as follows:
1375
1376 $year : 1970..2038 (or more) [Unix etc.]
1377 $year : 1904..2040 [MacOS Classic]
1378
1379 $month : 1..12
1380 $day : 1..31
1381 $hour : 0..23
1382 $min : 0..59
1383 $sec : 0..59
1384 $doy : 1..366
1385 $dow : 1..7
1386 $dst : -1..1
1387
1388 "$doy" is the day of year, sometimes also referred to as the "julian
1389 date", which starts at "1" and goes up to the number of days in that
1390 year.
1391
1392 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1393 so on until "7" for Sunday.
1394
1395 The daylight savings time flag ("$dst") will be ""-1"" if this
1396 information is not available on your system, "0" for no daylight
1397 savings time (i.e., winter time) and "1" when daylight savings time
1398 is in effect.
1399
1400 A fatal "time out of range" error will occur if the given time value
1401 is out of range "[0..(~0>>1)]".
1402
1403 If the time value is omitted, the "time()" function is called
1404 instead, internally.
1405
1406 · "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1407 Localtime([time]);"
1408
1409 This is Date::Pcalc's equivalent of Perl's built-in "localtime()"
1410 function. See also "localtime" in perlfunc(1).
1411
1412 The ranges of values returned (and their meanings) are as follows:
1413
1414 $year : 1970..2038 (or more) [Unix etc.]
1415 $year : 1904..2040 [MacOS Classic]
1416
1417 $month : 1..12
1418 $day : 1..31
1419 $hour : 0..23
1420 $min : 0..59
1421 $sec : 0..59
1422 $doy : 1..366
1423 $dow : 1..7
1424 $dst : -1..1
1425
1426 "$doy" is the day of year, sometimes also referred to as the "julian
1427 date", which starts at "1" and goes up to the number of days in that
1428 year.
1429
1430 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1431 so on until "7" for Sunday.
1432
1433 The daylight savings time flag ("$dst") will be ""-1"" if this
1434 information is not available on your system, "0" for no daylight
1435 savings time (i.e., winter time) and "1" when daylight savings time
1436 is in effect.
1437
1438 A fatal "time out of range" error will occur if the given time value
1439 is out of range "[0..(~0>>1)]".
1440
1441 If the time value is omitted, the "time()" function is called
1442 instead, internally.
1443
1444 · "$time = Mktime($year,$month,$day, $hour,$min,$sec);"
1445
1446 This function converts a date into a time value, i.e., into the
1447 number of seconds since whatever moment in time your system considers
1448 to be the "epoch". On Unix and most other systems this is the number
1449 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1450 this is the number of seconds since January 1st 1904 at midnight
1451 (local time).
1452
1453 The function is similar to the "POSIX::mktime()" function (see
1454 "mktime" in POSIX(1) for more details), but in contrast to the
1455 latter, it expects dates in the usual ranges used throughout this
1456 module: The year 2001 stays year 2001, and months are numbered from 1
1457 to 12.
1458
1459 A fatal "date out of range" error will occur if the given date cannot
1460 be expressed in terms of seconds since the epoch (this happens for
1461 instance when the date lies before the epoch, or if it is later than
1462 19-Jan-2038Â 03:14:07Â GMT on 32Â bit Unix systems, or later than
1463 06-Feb-2040Â 06:28:15 (local time) on a Macintosh with MacOS
1464 Classic).
1465
1466 Just like the "POSIX::mktime()" function, this function uses the
1467 "mktime()" system call, internally.
1468
1469 This means that the given date and time is considered to be in local
1470 time, and that the value returned by this function will depend on
1471 your machine's local settings such as the time zone, whether daylight
1472 savings time is (or was, at the time) in effect, and the system clock
1473 itself.
1474
1475 BEWARE that "mktime()" does not always return the same time value as
1476 fed into "localtime()", when you feed the output of "localtime()"
1477 back into "mktime()", on some systems!
1478
1479 I.e., ""Mktime((Localtime($time))[0..5])"" will not always return the
1480 same value as given in "$time"!
1481
1482 Note that since Perl does not provide any access to the internal
1483 system call "mktime()", in this pure Perl version, "Mktime()" is
1484 calculated as follows:
1485
1486 Date_to_Time(Add_Delta_YMDHMS(@_,map(-$_,(Timezone(Date_to_Time(@_)))[0..5])));
1487
1488 This may or may not yield the same result as "mktime()".
1489
1490 No guarantees whatsoever are given here for that! Use at your own
1491 risk!
1492
1493 · "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);"
1494
1495 This function returns the difference between ""localtime(time)"" and
1496 ""gmtime(time)"", which is the timezone offset in effect for the
1497 current location and the given ""time"".
1498
1499 This offset is positive if you are located to the east of Greenwich,
1500 and is usually negative (except during daylight savings time, in some
1501 locations) if you are located to the west of Greenwich.
1502
1503 Note that this offset is influenced by all of the relevant system
1504 settings and parameters on your machine; such as locales, environment
1505 variables (e.g. ""TZ"") and the system clock itself. See the relevant
1506 documentation on your system for more details.
1507
1508 If the ""time"" is omitted, the ""time()"" function will be called
1509 automatically, internally (similar to the built-in functions
1510 ""localtime()"" and ""gmtime()"" in Perl).
1511
1512 A fatal "time out of range" error will occur if the given time value
1513 is out of range "[0..(~0>>1)]".
1514
1515 The last item of the returned list is a flag which indicates whether
1516 daylight savings time is currently in effect. This flag is negative
1517 (-1) if this information is not available on your system. It is zero
1518 (0) when daylight savings time is off, and positive (+1) when
1519 daylight savings time is on.
1520
1521 Thus you can check very quickly whether daylight savings time is
1522 currently in effect by evaluating this function in scalar context (in
1523 scalar context, Perl returns the last item of a list):
1524
1525 if (scalar Timezone > 0) { # yes, daylight savings time
1526
1527 However, a slightly more efficient way would be this:
1528
1529 if (scalar System_Clock > 0) { # yes, daylight savings time
1530
1531 · "$time = Date_to_Time($year,$month,$day, $hour,$min,$sec);"
1532
1533 This function is a replacement for the BSD function "timegm()" (which
1534 is not available on all Unix systems), which converts a given date
1535 and time into a time value, i.e., into the number of seconds since
1536 whatever moment in time your system considers to be the "epoch". On
1537 Unix and most other systems this is the number of seconds since
1538 January 1st 1970 at midnight (GMT). On MacOS Classic this is the
1539 number of seconds since January 1st 1904 at midnight (local time).
1540
1541 Under Unix, the date and time are considered to be in UTC ("Universal
1542 Time Coordinated", and so is the resulting time value.
1543
1544 UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1545 UTC has leap seconds (in order to account for small variations in the
1546 rotation of the earth, for instance), whereas GMT does not.
1547
1548 Under MacOS Classic, however, both input and output are considered to
1549 be in local time.
1550
1551 The ranges of year and month follow the same rules as throughout the
1552 rest of this module (and not the contorted rules of its Unix
1553 equivalent), i.e., the year "2001" stays "2001" and the month ranges
1554 from 1 to 12.
1555
1556 A fatal "date out of range" error will occur if the given date cannot
1557 be expressed in terms of seconds since the epoch (this happens for
1558 instance when the date lies before the epoch, or if it is later than
1559 19-Jan-2038Â 03:14:07Â GMT on 32Â bit Unix systems, or later than
1560 06-Feb-2040Â 06:28:15 (local time) on a Macintosh with MacOS
1561 Classic).
1562
1563 This function should be very fast, because it is implemented in a
1564 very straightforward manner and doesn't use any internal system
1565 calls.
1566
1567 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1568 guaranteed to be complementary, i.e., that
1569 ""Date_to_Time(Time_to_Date($time))"" and
1570 ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1571 will always return the initial values.
1572
1573 · "($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);"
1574
1575 This function is an alternative to the POSIX "gmtime()" function (and
1576 its built-in Perl equivalent), which converts a given time value into
1577 the corresponding date and time. The given time value must be the
1578 number of seconds since whatever moment in time your system considers
1579 to be the "epoch". On Unix and most other systems this is the number
1580 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1581 this is the number of seconds since January 1st 1904 at midnight
1582 (local time).
1583
1584 Under Unix, the given time value is considered to be in UTC
1585 ("Universal Time Coordinated", and so is the resulting date and time.
1586
1587 UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1588 UTC has leap seconds (in order to account for small variations in the
1589 rotation of the earth, for instance), whereas GMT does not.
1590
1591 Under MacOS Classic, however, both input and output are considered to
1592 be in local time.
1593
1594 If the input value ""time"" is omitted, the ""time()"" function will
1595 be called automatically, internally (similar to the built-in
1596 functions ""localtime()"" and ""gmtime()"" in Perl).
1597
1598 A fatal "time out of range" error will occur if the given time value
1599 is negative.
1600
1601 This function should be very fast, because it is implemented in a
1602 very straightforward manner and doesn't use any internal system calls
1603 (except for "time()", if the input value is omitted).
1604
1605 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1606 guaranteed to be complementary, i.e., that
1607 ""Date_to_Time(Time_to_Date($time))"" and
1608 ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1609 will always return the initial values.
1610
1611 · "($year,$month,$day) = Easter_Sunday($year);"
1612
1613 This function calculates the date of Easter Sunday for all years in
1614 the range from 1583 to 2299 (all other year numbers will result in a
1615 fatal "year out of range" error message) using the method known as
1616 the "Gaussian Rule".
1617
1618 Some related christian feast days which depend on the date of Easter
1619 Sunday:
1620
1621 Carnival Monday / Rosenmontag / Veille du Mardi Gras = -48 days
1622 Mardi Gras / Karnevalsdienstag / Mardi Gras = -47 days
1623 Ash Wednesday / Aschermittwoch / Mercredi des Cendres = -46 days
1624 Palm Sunday / Palmsonntag / Dimanche des Rameaux = -7 days
1625 Easter Friday / Karfreitag / Vendredi Saint = -2 days
1626 Easter Saturday / Ostersamstag / Samedi de Paques = -1 day
1627 Easter Monday / Ostermontag / Lundi de Paques = +1 day
1628 Ascension of Christ / Christi Himmelfahrt / Ascension = +39 days
1629 Whitsunday / Pfingstsonntag / Dimanche de Pentecote = +49 days
1630 Whitmonday / Pfingstmontag / Lundi de Pentecote = +50 days
1631 Feast of Corpus Christi / Fronleichnam / Fete-Dieu = +60 days
1632
1633 Use the offsets shown above to calculate the date of the
1634 corresponding feast day as follows:
1635
1636 ($year,$month,$day) = Add_Delta_Days(Easter_Sunday($year), $offset));
1637
1638 · "if ($month = Decode_Month($string[,$lang]))"
1639
1640 This function takes a string as its argument, which should contain
1641 the name of a month in the given or currently selected language (see
1642 further below for details about the multi-language support of this
1643 package), or any uniquely identifying abbreviation of a month's name
1644 (i.e., the first few letters), and returns the corresponding number
1645 (1..12) upon a successful match, or "0" otherwise (therefore, the
1646 return value can also be used as the conditional expression in an
1647 "if" statement).
1648
1649 Note that the input string may not contain any other characters which
1650 do not pertain to the month's name, especially no leading or trailing
1651 whitespace.
1652
1653 Note also that matching is performed in a case-insensitive manner
1654 (this may depend on the "locale" setting on your current system,
1655 though!)
1656
1657 With "1" ("English") as the given language, the following examples
1658 will all return the value "9":
1659
1660 $month = Decode_Month("s",1);
1661 $month = Decode_Month("Sep",1);
1662 $month = Decode_Month("septemb",1);
1663 $month = Decode_Month("September",1);
1664
1665 · "if ($dow = Decode_Day_of_Week($string[,$lang]))"
1666
1667 This function takes a string as its argument, which should contain
1668 the name of a day of week in the given or currently selected language
1669 (see further below for details about the multi-language support of
1670 this package), or any uniquely identifying abbreviation of the name
1671 of a day of week (i.e., the first few letters), and returns the
1672 corresponding number (1..7) upon a successful match, or "0" otherwise
1673 (therefore, the return value can also be used as the conditional
1674 expression in an "if" statement).
1675
1676 Note that the input string may not contain any other characters which
1677 do not pertain to the name of the day of week, especially no leading
1678 or trailing whitespace.
1679
1680 Note also that matching is performed in a case-insensitive manner
1681 (this may depend on the "locale" setting on your current system,
1682 though!)
1683
1684 With "1" ("English") as the given language, the following examples
1685 will all return the value "3":
1686
1687 $dow = Decode_Day_of_Week("w",1);
1688 $dow = Decode_Day_of_Week("Wed",1);
1689 $dow = Decode_Day_of_Week("wednes",1);
1690 $dow = Decode_Day_of_Week("Wednesday",1);
1691
1692 · "if ($lang = Decode_Language($string))"
1693
1694 This function takes a string as its argument, which should contain
1695 the name of one of the languages supported by this package (IN THIS
1696 VERY LANGUAGE ITSELF), or any uniquely identifying abbreviation of
1697 the name of a language (i.e., the first few letters), and returns its
1698 corresponding internal number (1..14 in the original distribution)
1699 upon a successful match, or "0" otherwise (therefore, the return
1700 value can also be used as the conditional expression in an "if"
1701 statement).
1702
1703 Note that the input string may not contain any other characters which
1704 do not pertain to the name of a language, especially no leading or
1705 trailing whitespace.
1706
1707 Note also that matching is performed in a case-insensitive manner
1708 (this may depend on the "locale" setting on your current system,
1709 though!)
1710
1711 The original distribution supports the following fourteen languages:
1712
1713 English ==> 1 (default)
1714 Français (French) ==> 2
1715 Deutsch (German) ==> 3
1716 Español (Spanish) ==> 4
1717 Português (Portuguese) ==> 5
1718 Nederlands (Dutch) ==> 6
1719 Italiano (Italian) ==> 7
1720 Norsk (Norwegian) ==> 8
1721 Svenska (Swedish) ==> 9
1722 Dansk (Danish) ==> 10
1723 suomi (Finnish) ==> 11
1724 Magyar (Hungarian) ==> 12
1725 polski (Polish) ==> 13
1726 Romaneste (Romanian) ==> 14
1727
1728 See the section "How to install additional languages" in the file
1729 "INSTALL.txt" in this distribution for how to add more languages to
1730 this package.
1731
1732 In the original distribution (no other languages installed), the
1733 following examples will all return the value "3":
1734
1735 $lang = Decode_Language("d");
1736 $lang = Decode_Language("de");
1737 $lang = Decode_Language("Deutsch");
1738
1739 Note that you may not be able to enter the special international
1740 characters in some of the languages' names over the keyboard directly
1741 on some systems.
1742
1743 This should never be a problem, though; just enter an abbreviation of
1744 the name of the language consisting of the first few letters up to
1745 the character before the first special international character.
1746
1747 · "if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))"
1748
1749 This function scans a given string and tries to parse any date which
1750 might be embedded in it.
1751
1752 The function returns an empty list if it can't successfully extract a
1753 valid date from its input string, or else it returns the date found.
1754
1755 The function accepts almost any format, as long as the date is given
1756 in the european order (hence its name) day-month-year.
1757
1758 Thereby, zero or more NON-NUMERIC characters may PRECEDE the day and
1759 FOLLOW the year.
1760
1761 Moreover, zero or more NON-ALPHANUMERIC characters are permitted
1762 BETWEEN these three items (i.e., between day and month and between
1763 month and year).
1764
1765 The month may be given either numerically (i.e., a number from "1" to
1766 "12"), or alphanumerically, i.e., as the name of the month in the
1767 given or currently selected language, or any uniquely identifying
1768 abbreviation thereof.
1769
1770 (See further below for details about the multi-language support of
1771 this package!)
1772
1773 If the year is given as one or two digits only (i.e., if the year is
1774 less than 100), it is mapped to a "window" of +/- 50 years around the
1775 current year, as described by the "Moving_Window()" function (see
1776 further below).
1777
1778 If the day, month and year are all given numerically but WITHOUT any
1779 delimiting characters between them, this string of digits will be
1780 mapped to the day, month and year as follows:
1781
1782 Length: Mapping:
1783 3 dmy
1784 4 dmyy
1785 5 dmmyy
1786 6 ddmmyy
1787 7 dmmyyyy
1788 8 ddmmyyyy
1789
1790 (Where "d" stands for "day", "m" stands for "month" and "y" stands
1791 for "year".)
1792
1793 All other strings consisting purely of digits (without any
1794 intervening delimiters) are rejected, i.e., not recognized.
1795
1796 Examples:
1797
1798 "3.1.64"
1799 "3 1 64"
1800 "03.01.64"
1801 "03/01/64"
1802 "3. Jan 1964"
1803 "Birthday: 3. Jan '64 in Backnang/Germany"
1804 "03-Jan-64"
1805 "3.Jan1964"
1806 "3Jan64"
1807 "030164"
1808 "3ja64"
1809 "3164"
1810
1811 Experiment! (See the corresponding example applications in the
1812 "examples" subdirectory of this distribution in order to do so.)
1813
1814 · "if (($year,$month,$day) = Decode_Date_US($string[,$lang]))"
1815
1816 This function scans a given string and tries to parse any date which
1817 might be embedded in it.
1818
1819 The function returns an empty list if it can't successfully extract a
1820 valid date from its input string, or else it returns the date found.
1821
1822 The function accepts almost any format, as long as the date is given
1823 in the U.S. american order (hence its name) month-day-year.
1824
1825 Thereby, zero or more NON-ALPHANUMERIC characters may PRECEDE and
1826 FOLLOW the month (i.e., precede the month and separate it from the
1827 day which follows behind).
1828
1829 Moreover, zero or more NON-NUMERIC characters are permitted BETWEEN
1830 the day and the year, as well as AFTER the year.
1831
1832 The month may be given either numerically (i.e., a number from "1" to
1833 "12"), or alphanumerically, i.e., as the name of the month in the
1834 given or currently selected language, or any uniquely identifying
1835 abbreviation thereof.
1836
1837 (See further below for details about the multi-language support of
1838 this package!)
1839
1840 If the year is given as one or two digits only (i.e., if the year is
1841 less than 100), it is mapped to a "window" of +/- 50 years around the
1842 current year, as described by the "Moving_Window()" function (see
1843 further below).
1844
1845 If the month, day and year are all given numerically but WITHOUT any
1846 delimiting characters between them, this string of digits will be
1847 mapped to the month, day and year as follows:
1848
1849 Length: Mapping:
1850 3 mdy
1851 4 mdyy
1852 5 mddyy
1853 6 mmddyy
1854 7 mddyyyy
1855 8 mmddyyyy
1856
1857 (Where "m" stands for "month", "d" stands for "day" and "y" stands
1858 for "year".)
1859
1860 All other strings consisting purely of digits (without any
1861 intervening delimiters) are rejected, i.e., not recognized.
1862
1863 If only the day and the year form a contiguous string of digits, they
1864 will be mapped as follows:
1865
1866 Length: Mapping:
1867 2 dy
1868 3 dyy
1869 4 ddyy
1870 5 dyyyy
1871 6 ddyyyy
1872
1873 (Where "d" stands for "day" and "y" stands for "year".)
1874
1875 Examples:
1876
1877 "1 3 64"
1878 "01/03/64"
1879 "Jan 3 '64"
1880 "Jan 3 1964"
1881 "===> January 3rd 1964 (birthday)"
1882 "Jan31964"
1883 "Jan364"
1884 "ja364"
1885 "1364"
1886
1887 Experiment! (See the corresponding example applications in the
1888 "examples" subdirectory of this distribution in order to do so.)
1889
1890 · "$year = Fixed_Window($yy);"
1891
1892 This function applies a "fixed window" strategy to two-digit year
1893 numbers in order to convert them into four-digit year numbers.
1894
1895 All other year numbers are passed through unchanged, except for
1896 negative year numbers, which cause the function to return zero ("0")
1897 instead.
1898
1899 Two-digit year numbers ""yy"" below 70 are converted to ""20yy"",
1900 whereas year numbers equal to or greater than 70 (but less than 100)
1901 are converted to ""19yy"".
1902
1903 In the original distribution of this package, the base century is set
1904 to "1900" and the base year to "70" (which is a standard on UNIX
1905 systems), but these constants (also called the "epoch") can actually
1906 be chosen at will.
1907
1908 · "$year = Moving_Window($yy);"
1909
1910 This function applies a "moving window" strategy to two-digit year
1911 numbers in order to convert them into four-digit year numbers,
1912 provided the necessary system calls (system clock) are available.
1913 Otherwise the function falls back to the "fixed window" strategy
1914 described in the function above.
1915
1916 All other year numbers are passed through unchanged, except for
1917 negative year numbers, which cause the function to return zero ("0")
1918 instead.
1919
1920 Two-digit year numbers are mapped according to a "window" of 50 years
1921 in both directions (past and future) around the current year.
1922
1923 That is, two-digit year numbers are first mapped to the same century
1924 as the current year. If the resulting year is smaller than the
1925 current year minus 50, then one more century is added to the result.
1926 If the resulting year is equal to or greater than the current year
1927 plus 50, then a century is subtracted from the result.
1928
1929 · "$date = Compress($year,$month,$day);"
1930
1931 WARNING: This function is legacy code, its use is deprecated!
1932
1933 This function encodes a date in 16 bits, which is the value being
1934 returned.
1935
1936 The encoding scheme is as follows:
1937
1938 Bit number: FEDCBA9 8765 43210
1939 Contents: yyyyyyy mmmm ddddd
1940
1941 (Where the "yyyyyyy" contain the number of the year, "mmmm" the
1942 number of the month and "ddddd" the number of the day.)
1943
1944 The function returns "0" if the given input values do not represent a
1945 valid date. Therefore, the return value of this function can also be
1946 used as the conditional expression in an "if" statement, in order to
1947 check whether the given input values constitute a valid date).
1948
1949 Through this special encoding scheme, it is possible to COMPARE
1950 compressed dates for equality and order (less than/greater than)
1951 WITHOUT any previous DECODING!
1952
1953 Note however that contiguous dates do NOT necessarily have contiguous
1954 compressed representations!
1955
1956 I.e., incrementing the compressed representation of a date MAY OR MAY
1957 NOT yield a valid new date!
1958
1959 Note also that this function can only handle dates within one
1960 century.
1961
1962 This century can be chosen at will (at compile time of this module)
1963 by defining a base century and year (also called the "epoch"). In the
1964 original distribution of this package, the base century is set to
1965 "1900" and the base year to "70" (which is standard on UNIX systems).
1966
1967 This allows this function to handle dates from "1970" up to "2069".
1968
1969 If the given year is equal to, say, "95", this package will
1970 automatically assume that you really meant "1995" instead. However,
1971 if you specify a year number which is SMALLER than 70, like "64", for
1972 instance, this package will assume that you really meant "2064".
1973
1974 You are not confined to two-digit (abbreviated) year numbers, though.
1975
1976 The function also accepts "full-length" year numbers, provided that
1977 they lie in the supported range (i.e., from "1970" to "2069", in the
1978 original configuration of this package).
1979
1980 Note that this function is maintained mainly for backward
1981 compatibility, and that its use is not recommended.
1982
1983 · "if (($century,$year,$month,$day) = Uncompress($date))"
1984
1985 WARNING: This function is legacy code, its use is deprecated!
1986
1987 This function decodes dates that were encoded previously using the
1988 function ""Compress()"".
1989
1990 It returns the century, year, month and day of the date encoded in
1991 "$date" if "$date" represents a valid date, or an empty list
1992 otherwise.
1993
1994 The year returned in "$year" is actually a two-digit year number
1995 (i.e., the year number taken modulo 100), and only the expression
1996 ""$century + $year"" yields the "full-length" year number (for
1997 example, "1900 + 95 = 1995").
1998
1999 Note that this function is maintained mainly for backward
2000 compatibility, and that its use is not recommended.
2001
2002 · "if (check_compressed($date))"
2003
2004 WARNING: This function is legacy code, its use is deprecated!
2005
2006 This function returns "true" ("1") if the given input value
2007 constitutes a valid compressed date, and "false" ("0") otherwise.
2008
2009 Note that this function is maintained mainly for backward
2010 compatibility, and that its use is not recommended.
2011
2012 · "$string = Compressed_to_Text($date[,$lang]);"
2013
2014 WARNING: This function is legacy code, its use is deprecated!
2015
2016 This function returns a string of fixed length (always 9 characters
2017 long) containing a textual representation of the compressed date
2018 encoded in "$date".
2019
2020 This string has the form "dd-Mmm-yy", where "dd" is the two-digit
2021 number of the day, "Mmm" are the first three letters of the name of
2022 the month in the given or currently selected language (see further
2023 below for details about the multi-language support of this package),
2024 and "yy" is the two-digit year number (i.e., the year number taken
2025 modulo 100).
2026
2027 If "$date" does not represent a valid date, the string "??-???-??" is
2028 returned instead.
2029
2030 Note that this function is maintained mainly for backward
2031 compatibility, and that its use is not recommended.
2032
2033 · "$string = Date_to_Text($year,$month,$day[,$lang]);"
2034
2035 This function returns a string containing a textual representation of
2036 the given date of the form "www dd-Mmm-yyyy", where "www" are the
2037 first three letters of the name of the day of week in the given or
2038 currently selected language, or a special abbreviation, if special
2039 abbreviations have been defined for the given or currently selected
2040 language (see further below for details about the multi-language
2041 support of this package), "dd" is the day (one or two digits), "Mmm"
2042 are the first three letters of the name of the month in the given or
2043 currently selected language, and "yyyy" is the number of the year in
2044 full length.
2045
2046 If the given input values do not constitute a valid date, a fatal
2047 "not a valid date" error occurs.
2048
2049 (See the section "RECIPES" near the end of this document for a code
2050 snippet for how to print dates in any format you like.)
2051
2052 · "$string = Date_to_Text_Long($year,$month,$day[,$lang]);"
2053
2054 This function returns a string containing a textual representation of
2055 the given date roughly of the form "Wwwwww, dd Mmmmmm yyyy", where
2056 "Wwwwww" is the name of the day of week in the given or currently
2057 selected language (see further below for details about the multi-
2058 language support of this package), "dd" is the day (one or two
2059 digits), "Mmmmmm" is the name of the month in the given or currently
2060 selected language, and "yyyy" is the number of the year in full
2061 length.
2062
2063 The exact format of the output string depends on the given or
2064 currently selected language. In the original distribution of this
2065 package, these formats are defined as follows:
2066
2067 1 English : "Wwwwww, Mmmmmm ddth yyyy"
2068 2 French : "Wwwwww dd mmmmmm yyyy"
2069 3 German : "Wwwwww, den dd. Mmmmmm yyyy"
2070 4 Spanish : "Wwwwww, dd de mmmmmm de yyyy"
2071 5 Portuguese : "Wwwwww, dia dd de mmmmmm de yyyy"
2072 6 Dutch : "Wwwwww, dd mmmmmm yyyy"
2073 7 Italian : "Wwwwww, dd Mmmmmm yyyy"
2074 8 Norwegian : "wwwwww, dd. mmmmmm yyyy"
2075 9 Swedish : "wwwwww, dd mmmmmm yyyy"
2076 10 Danish : "wwwwww, dd. mmmmmm yyyy"
2077 11 Finnish : "wwwwww, dd. mmmmmmta yyyy"
2078 12 Hungarian : "dd. Mmmmmm yyyy., wwwwww"
2079 13 Polish : "Wwwwww, dd Mmmmmm yyyy"
2080 14 Romanian : "Wwwwww dd Mmmmmm yyyy"
2081
2082 (You can change these formats in the file "Pcalc.pm" before
2083 installing this module in order to suit your personal preferences.)
2084
2085 If the given input values do not constitute a valid date, a fatal
2086 "not a valid date" error occurs.
2087
2088 In order to capitalize the day of week at the beginning of the string
2089 in Norwegian, use
2090 ""ucfirst(Date_to_Text_Long($year,$month,$day,8));"".
2091
2092 (See the section "RECIPES" near the end of this document for an
2093 example on how to print dates in any format you like.)
2094
2095 · "$string = English_Ordinal($number);"
2096
2097 This function returns a string containing the (english) abbreviation
2098 of the ordinal number for the given (cardinal) number "$number".
2099
2100 I.e.,
2101
2102 0 => '0th' 10 => '10th' 20 => '20th'
2103 1 => '1st' 11 => '11th' 21 => '21st'
2104 2 => '2nd' 12 => '12th' 22 => '22nd'
2105 3 => '3rd' 13 => '13th' 23 => '23rd'
2106 4 => '4th' 14 => '14th' 24 => '24th'
2107 5 => '5th' 15 => '15th' 25 => '25th'
2108 6 => '6th' 16 => '16th' 26 => '26th'
2109 7 => '7th' 17 => '17th' 27 => '27th'
2110 8 => '8th' 18 => '18th' 28 => '28th'
2111 9 => '9th' 19 => '19th' 29 => '29th'
2112
2113 etc.
2114
2115 · "$string = Calendar($year,$month[,$orthodox[,$lang]]);"
2116
2117 This function returns a calendar of the given month in the given year
2118 (somewhat similar to the UNIX ""cal"" command), in the given or
2119 currently selected language (see further below for details about the
2120 multi-language support of this package).
2121
2122 Example:
2123
2124 print Calendar(1998,5);
2125
2126 This will print:
2127
2128 May 1998
2129 Mon Tue Wed Thu Fri Sat Sun
2130 1 2 3
2131 4 5 6 7 8 9 10
2132 11 12 13 14 15 16 17
2133 18 19 20 21 22 23 24
2134 25 26 27 28 29 30 31
2135
2136 If the optional boolean parameter "$orthodox" is given and true, the
2137 calendar starts on Sunday instead of Monday.
2138
2139 · "$string = Month_to_Text($month[,$lang]);"
2140
2141 This function returns the name of the given month in the given or
2142 currently selected language (see further below for details about the
2143 multi-language support of this package).
2144
2145 If the given month lies outside of the valid range from "1" to "12",
2146 a fatal "month out of range" error will occur.
2147
2148 · "$string = Day_of_Week_to_Text($dow[,$lang]);"
2149
2150 This function returns the name of the given day of week in the given
2151 or currently selected language (see further below for details about
2152 the multi-language support of this package).
2153
2154 If the given day of week lies outside of the valid range from "1" to
2155 "7", a fatal "day of week out of range" error will occur.
2156
2157 · "$string = Day_of_Week_Abbreviation($dow[,$lang]);"
2158
2159 This function returns the special abbreviation of the name of the
2160 given day of week, IF such special abbreviations have been defined
2161 for the given or currently selected language (see further below for
2162 details about the multi-language support of this package).
2163
2164 (In the original distribution of this package, this was only true for
2165 Portuguese. Starting with version 5.1, abbreviations for Polish have
2166 also been introduced. Starting with version 5.7, the abbreviations
2167 for Portuguese have been disabled. So Polish is currently the only
2168 language to define such special abbreviations.)
2169
2170 If not, the first three letters of the name of the day of week in the
2171 given or currently selected language are returned instead.
2172
2173 If the given day of week lies outside of the valid range from "1" to
2174 "7", a fatal "day of week out of range" error will occur.
2175
2176 Currently, this table of special abbreviations is only used by the
2177 functions ""Date_to_Text()"" and ""Calendar()"", internally.
2178
2179 · "$string = Language_to_Text($lang);"
2180
2181 This function returns the name of any language supported by this
2182 package when the internal number representing that language is given
2183 as input.
2184
2185 The original distribution supports the following fourteen languages:
2186
2187 1 ==> English (default)
2188 2 ==> Français (French)
2189 3 ==> Deutsch (German)
2190 4 ==> Español (Spanish)
2191 5 ==> Português (Portuguese)
2192 6 ==> Nederlands (Dutch)
2193 7 ==> Italiano (Italian)
2194 8 ==> Norsk (Norwegian)
2195 9 ==> Svenska (Swedish)
2196 10 ==> Dansk (Danish)
2197 11 ==> suomi (Finnish)
2198 12 ==> Magyar (Hungarian)
2199 13 ==> polski (Polish)
2200 14 ==> Romaneste (Romanian)
2201
2202 See the section "How to install additional languages" in the file
2203 "INSTALL.txt" in this distribution for how to add more languages to
2204 this package.
2205
2206 See the description of the function ""Languages()"" further below to
2207 determine how many languages are actually available in a given
2208 installation of this package.
2209
2210 · "$lang = Language();"
2211
2212 · "Language($lang); # DEPRECATED"
2213
2214 · "$oldlang = Language($newlang); # DEPRECATED"
2215
2216 This function can be used to determine which language is currently
2217 selected, and to change the selected language (this latter use is
2218 deprecated, because this global setting may cause conflicts between
2219 threads or modules running concurrently).
2220
2221 Thereby, each language has a unique internal number.
2222
2223 The original distribution contains the following fourteen languages:
2224
2225 1 ==> English (default)
2226 2 ==> Français (French)
2227 3 ==> Deutsch (German)
2228 4 ==> Español (Spanish)
2229 5 ==> Português (Portuguese)
2230 6 ==> Nederlands (Dutch)
2231 7 ==> Italiano (Italian)
2232 8 ==> Norsk (Norwegian)
2233 9 ==> Svenska (Swedish)
2234 10 ==> Dansk (Danish)
2235 11 ==> suomi (Finnish)
2236 12 ==> Magyar (Hungarian)
2237 13 ==> polski (Polish)
2238 14 ==> Romaneste (Romanian)
2239
2240 See the section "How to install additional languages" in the file
2241 "INSTALL.txt" in this distribution for how to add more languages to
2242 this package.
2243
2244 See the description of the function ""Languages()"" further below to
2245 determine how many languages are actually available in a given
2246 installation of this package.
2247
2248 BEWARE that in order for your programs to be portable, you should
2249 NEVER actually use the internal number of a language in this package
2250 EXPLICITLY, because the same number could mean different languages on
2251 different systems, depending on what languages have been added to any
2252 given installation of this package.
2253
2254 Therefore, you should always use a statement such as
2255
2256 Language(Decode_Language("Name_of_Language")); # DEPRECATED
2257
2258 or
2259
2260 DateCalc_Function(@parameters,Decode_Language("Name_of_Language")); # RECOMMENDED
2261
2262 to select the desired language, and
2263
2264 $language = Language_to_Text(Language());
2265
2266 or
2267
2268 $old_language = Language_to_Text(Language("Name_of_new_Language")); # DEPRECATED
2269
2270 to determine the (previously) selected language.
2271
2272 If the so chosen language is not available in the current
2273 installation, this will result in an appropriate error message,
2274 instead of silently using the wrong (a random) language (which just
2275 happens to have the same internal number in the other installation).
2276
2277 BEWARE that when using the function ""Language()"", the selected
2278 language is a global setting, shared by all threads or modules you
2279 might be running concurrently, thus possibly causing conflicts
2280 between them.
2281
2282 In order to avoid these conflicts, you should NEVER use the function
2283 ""Language()"", but should ALWAYS pass a language number (as returned
2284 by the function ""Decode_Language()"") to the functions which are
2285 language-dependent, which are:
2286
2287 "Decode_Month()", "Decode_Day_of_Week()", "Compressed_to_Text()",
2288 "Date_to_Text()", "Date_to_Text_Long()", "Calendar()",
2289 "Month_to_Text()", "Day_of_Week_to_Text()",
2290 "Day_of_Week_Abbreviation()", "Decode_Date_EU()", "Decode_Date_US()",
2291 "Decode_Date_EU2()", "Decode_Date_US2()", "Parse_Date()".
2292
2293 Note that when you pass an invalid number, such as e.g. zero, or no
2294 language parameter at all, these functions will revert to their
2295 behaviour in the versions of this module prior to 6.0, which means
2296 that the global setting (as set by ""Language()"") becomes active
2297 again (only in case of an invalid or missing language parameter!).
2298
2299 · "$max_lang = Languages();"
2300
2301 This function returns the (maximum) number of languages which are
2302 currently available in your installation of this package.
2303
2304 (This may vary from installation to installation.)
2305
2306 See the section "How to install additional languages" in the file
2307 "INSTALL.txt" in this distribution for how to add more languages to
2308 this package.
2309
2310 In the original distribution of this package there are fourteen
2311 built-in languages, therefore the value returned by this function
2312 will be "14" if no other languages have been added to your particular
2313 installation.
2314
2315 · "if (($year,$month,$day) = Decode_Date_EU2($string[,$lang))"
2316
2317 This function is the more "Perlish" equivalent of the function
2318 ""Decode_Date_EU()"" (translated from C), included here merely as an
2319 example to demonstrate how easy it is to write your own routine in
2320 Perl (using regular expressions) adapted to your own special needs,
2321 should the necessity arise, and intended primarily as a basis for
2322 your own development.
2323
2324 In one particular case this more "Perlish" version is actually
2325 slightly more permissive than its equivalent (translated from C), as
2326 far as the class of permitted intervening (i.e., delimiting)
2327 characters is concerned.
2328
2329 (Can you tell the subtle, almost insignificant difference by looking
2330 at the code? Or by experimenting? Hint: Try the string "a3b1c64d"
2331 with both functions.)
2332
2333 · "if (($year,$month,$day) = Decode_Date_US2($string[,$lang))"
2334
2335 This function is the more "Perlish" equivalent of the function
2336 ""Decode_Date_US()"" (translated from C), included here merely as an
2337 example to demonstrate how easy it is to write your own routine in
2338 Perl (using regular expressions) adapted to your own special needs,
2339 should the necessity arise, and intended primarily as a basis for
2340 your own development.
2341
2342 In one particular case this more "Perlish" version is actually
2343 slightly more permissive than its equivalent (translated from C).
2344
2345 (Hint: This is the same difference as with the ""Decode_Date_EU()""
2346 and ""Decode_Date_EU2()"" pair of functions.)
2347
2348 In a different case, the version translated from C is a little bit
2349 more permissive than its Perl equivalent.
2350
2351 (Can you tell the difference by looking at the code? Or by
2352 experimenting? Hint: Try the string "(1/364)" with both functions.)
2353
2354 · "if (($year,$month,$day) = Parse_Date($string[,$lang))"
2355
2356 This function is useful for parsing dates as returned by the UNIX
2357 ""date"" command or as found in the headers of e-mail (in order to
2358 determine the date at which some e-mail has been sent or received,
2359 for instance).
2360
2361 Example #1:
2362
2363 ($year,$month,$day) = Parse_Date(`/bin/date`);
2364
2365 Example #2:
2366
2367 while (<MAIL>)
2368 {
2369 if (/^From \S/)
2370 {
2371 ($year,$month,$day) = Parse_Date($_);
2372 ...
2373 }
2374 ...
2375 }
2376
2377 The function returns an empty list if it can't extract a valid date
2378 from the input string.
2379
2380 · "$lower = ISO_LC($string);"
2381
2382 Returns a copy of the given string where all letters of the
2383 ISO-Latin-1 character set have been replaced by their lower case
2384 equivalents.
2385
2386 Similar to Perl's built-in function ""lc()"" (see "lc" in
2387 perlfunc(1)) but for the whole ISO-Latin-1 character set, not just
2388 plain ASCII.
2389
2390 · "$upper = ISO_UC($string);"
2391
2392 Returns a copy of the given string where all letters of the
2393 ISO-Latin-1 character set have been replaced by their upper case
2394 equivalents.
2395
2396 Similar to Perl's built-in function ""uc()"" (see "uc" in
2397 perlfunc(1)) but for the whole ISO-Latin-1 character set, not just
2398 plain ASCII.
2399
2400 · "$string = Date::Pcalc::Version();"
2401
2402 This function returns a string with the (numeric) version number of
2403 the file "Pcalc.pm" at the core of this package.
2404
2405 Note that under all normal circumstances, this version number should
2406 be identical with the one found in the Perl variable
2407 "$Date::Pcalc::VERSION" (the version number of the "Pcalc.pm" file).
2408
2409 Since this function is not exported, you always have to qualify it
2410 explicitly, i.e., ""Date::Pcalc::Version()"".
2411
2412 This is to avoid possible name space conflicts with version functions
2413 from other modules.
2414
2416 1) How do I compare two dates?
2417
2418 Solution #1:
2419
2420 use Date::Pcalc qw( Date_to_Days );
2421
2422 if (Date_to_Days($year1,$month1,$day1) <
2423 Date_to_Days($year2,$month2,$day2))
2424
2425 if (Date_to_Days($year1,$month1,$day1) <=
2426 Date_to_Days($year2,$month2,$day2))
2427
2428 if (Date_to_Days($year1,$month1,$day1) >
2429 Date_to_Days($year2,$month2,$day2))
2430
2431 if (Date_to_Days($year1,$month1,$day1) >=
2432 Date_to_Days($year2,$month2,$day2))
2433
2434 if (Date_to_Days($year1,$month1,$day1) ==
2435 Date_to_Days($year2,$month2,$day2))
2436
2437 if (Date_to_Days($year1,$month1,$day1) !=
2438 Date_to_Days($year2,$month2,$day2))
2439
2440 $cmp = (Date_to_Days($year1,$month1,$day1) <=>
2441 Date_to_Days($year2,$month2,$day2));
2442
2443 Solution #2:
2444
2445 use Date::Pcalc qw( Delta_Days );
2446
2447 if (Delta_Days($year1,$month1,$day1,
2448 $year2,$month2,$day2) > 0)
2449
2450 if (Delta_Days($year1,$month1,$day1,
2451 $year2,$month2,$day2) >= 0)
2452
2453 if (Delta_Days($year1,$month1,$day1,
2454 $year2,$month2,$day2) < 0)
2455
2456 if (Delta_Days($year1,$month1,$day1,
2457 $year2,$month2,$day2) <= 0)
2458
2459 if (Delta_Days($year1,$month1,$day1,
2460 $year2,$month2,$day2) == 0)
2461
2462 if (Delta_Days($year1,$month1,$day1,
2463 $year2,$month2,$day2) != 0)
2464
2465 2) How do I check whether a given date lies within a certain range of
2466 dates?
2467
2468 use Date::Pcalc qw( Date_to_Days );
2469
2470 $lower = Date_to_Days($year1,$month1,$day1);
2471 $upper = Date_to_Days($year2,$month2,$day2);
2472
2473 $date = Date_to_Days($year,$month,$day);
2474
2475 if (($date >= $lower) && ($date <= $upper))
2476 {
2477 # ok
2478 }
2479 else
2480 {
2481 # not ok
2482 }
2483
2484 3) How do I compare two dates with times? How do I check whether two
2485 dates and times lie more or less than a given time interval apart?
2486
2487 Solution #1:
2488
2489 use Date::Pcalc qw( Add_Delta_DHMS Date_to_Days );
2490
2491 @date1 = (2002,8,31,23,59,1);
2492 @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2493
2494 #@date1 = (2002,8,31,22,59,1);
2495 #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2496
2497 # Omit the next line if you just want to compare the two dates
2498 # (and change @date3 and @d3 to @date1 and @d1, respectively):
2499
2500 @date3 = Add_Delta_DHMS(@date1, 0,12,0,0); # ==> is the difference within 12 hours?
2501
2502 @d2 = ( Date_to_Days(@date2[0..2]), ($date2[3]*60+$date2[4])*60+$date2[5] );
2503 @d3 = ( Date_to_Days(@date3[0..2]), ($date3[3]*60+$date3[4])*60+$date3[5] );
2504
2505 @diff = ( $d2[0]-$d3[0], $d2[1]-$d3[1] );
2506
2507 if ($diff[0] > 0 and $diff[1] < 0) { $diff[0]--; $diff[1] += 86400; }
2508 if ($diff[0] < 0 and $diff[1] > 0) { $diff[0]++; $diff[1] -= 86400; }
2509
2510 if (($diff[0] || $diff[1]) >= 0) { print "More than 12 hours.\n"; }
2511 else { print "Less than 12 hours.\n"; }
2512
2513 Solution #2:
2514
2515 This solution is only feasible if your dates are guaranteed to lie
2516 within the range given by your system's epoch and overflow date and
2517 time!
2518
2519 Unix: 1-Jan-1970 00:00:00 to 19-Jan-2038 03:14:07
2520 MacOS: 1-Jan-1904 00:00:00 to 6-Feb-2040 06:28:15
2521
2522 use Date::Pcalc qw( Date_to_Time );
2523
2524 @date1 = (2002,8,31,23,59,1);
2525 @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2526
2527 #@date1 = (2002,8,31,22,59,1);
2528 #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2529
2530 $d1 = Date_to_Time(@date1);
2531 $d2 = Date_to_Time(@date2);
2532
2533 if ($d1 <= $d2) { print "The two dates are in chronological order.\n"; }
2534 else { print "The two dates are in reversed order.\n"; }
2535
2536 if ($d1 + 12*60*60 <= $d2) { print "More than 12 hours.\n"; }
2537 else { print "Less than 12 hours.\n"; }
2538
2539 4) How do I verify whether someone has a certain age?
2540
2541 use Date::Pcalc qw( Decode_Date_EU Today leap_year Delta_Days );
2542
2543 $date = <STDIN>; # get birthday
2544
2545 ($year1,$month1,$day1) = Decode_Date_EU($date);
2546
2547 ($year2,$month2,$day2) = Today();
2548
2549 if (($day1 == 29) && ($month1 == 2) && !leap_year($year2))
2550 { $day1--; }
2551
2552 if ( (($year2 - $year1) > 18) ||
2553 ( (($year2 - $year1) == 18) &&
2554 (Delta_Days($year2,$month1,$day1, $year2,$month2,$day2) >= 0) ) )
2555 {
2556 print "Ok - you are over 18.\n";
2557 }
2558 else
2559 {
2560 print "Sorry - you aren't 18 yet!\n";
2561 }
2562
2563 Or, alternatively (substituting the last "if" statement above):
2564
2565 if (($year1+18 <=> $year2 || $month1 <=> $month2 || $day1 <=> $day2) <= 0)
2566 { print "Ok - you are over 18.\n"; }
2567 else
2568 { print "Sorry - you aren't 18 yet!\n"; }
2569
2570 5) How do I calculate the number of the week of month the current date
2571 lies in?
2572
2573 For example:
2574
2575 April 1998
2576 Mon Tue Wed Thu Fri Sat Sun
2577 1 2 3 4 5 = week #1
2578 6 7 8 9 10 11 12 = week #2
2579 13 14 15 16 17 18 19 = week #3
2580 20 21 22 23 24 25 26 = week #4
2581 27 28 29 30 = week #5
2582
2583 Solution:
2584
2585 use Date::Pcalc qw( Today Day_of_Week );
2586
2587 ($year,$month,$day) = Today();
2588
2589 $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;
2590
2591 6) How do I calculate whether a given date is the 1st, 2nd, 3rd, 4th
2592 or 5th of that day of week in the given month?
2593
2594 For example:
2595
2596 October 2000
2597 Mon Tue Wed Thu Fri Sat Sun
2598 1
2599 2 3 4 5 6 7 8
2600 9 10 11 12 13 14 15
2601 16 17 18 19 20 21 22
2602 23 24 25 26 27 28 29
2603 30 31
2604
2605 Is Sunday, the 15th of October 2000, the 1st, 2nd, 3rd, 4th or 5th
2606 Sunday of that month?
2607
2608 Solution:
2609
2610 use Date::Pcalc qw( Day_of_Week Delta_Days
2611 Nth_Weekday_of_Month_Year
2612 Date_to_Text_Long English_Ordinal
2613 Day_of_Week_to_Text Month_to_Text );
2614
2615 ($year,$month,$day) = (2000,10,15);
2616
2617 $dow = Day_of_Week($year,$month,$day);
2618
2619 $n = int( Delta_Days(
2620 Nth_Weekday_of_Month_Year($year,$month,$dow,1),
2621 $year,$month,$day)
2622 / 7) + 1;
2623
2624 printf("%s is the %s %s in %s %d.\n",
2625 Date_to_Text_Long($year,$month,$day),
2626 English_Ordinal($n),
2627 Day_of_Week_to_Text($dow),
2628 Month_to_Text($month),
2629 $year);
2630
2631 This prints:
2632
2633 Sunday, October 15th 2000 is the 3rd Sunday in October 2000.
2634
2635 7) How do I calculate the date of the Wednesday of the same week as
2636 the current date?
2637
2638 Solution #1:
2639
2640 use Date::Pcalc qw( Today Day_of_Week Add_Delta_Days );
2641
2642 $searching_dow = 3; # 3 = Wednesday
2643
2644 @today = Today();
2645
2646 $current_dow = Day_of_Week(@today);
2647
2648 @date = Add_Delta_Days(@today, $searching_dow - $current_dow);
2649
2650 Solution #2:
2651
2652 use Date::Pcalc qw( Today Add_Delta_Days
2653 Monday_of_Week Week_of_Year );
2654
2655 $searching_dow = 3; # 3 = Wednesday
2656
2657 @today = Today();
2658
2659 @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
2660 $searching_dow - 1 );
2661
2662 Solution #3:
2663
2664 use Date::Pcalc qw( Standard_to_Business Today
2665 Business_to_Standard );
2666
2667 @business = Standard_to_Business(Today());
2668
2669 $business[2] = 3; # 3 = Wednesday
2670
2671 @date = Business_to_Standard(@business);
2672
2673 8) How can I add a week offset to a business date (including across
2674 year boundaries)?
2675
2676 use Date::Pcalc qw( Business_to_Standard Add_Delta_Days
2677 Standard_to_Business );
2678
2679 @temp = Business_to_Standard($year,$week,$dow);
2680
2681 @temp = Add_Delta_Days(@temp, $week_offset * 7);
2682
2683 ($year,$week,$dow) = Standard_to_Business(@temp);
2684
2685 9) How do I calculate the last and the next Saturday for any given
2686 date?
2687
2688 use Date::Pcalc qw( Today Day_of_Week Add_Delta_Days
2689 Day_of_Week_to_Text Date_to_Text );
2690
2691 $searching_dow = 6; # 6 = Saturday
2692
2693 @today = Today();
2694
2695 $current_dow = Day_of_Week(@today);
2696
2697 if ($searching_dow == $current_dow)
2698 {
2699 @prev = Add_Delta_Days(@today,-7);
2700 @next = Add_Delta_Days(@today,+7);
2701 }
2702 else
2703 {
2704 if ($searching_dow > $current_dow)
2705 {
2706 @next = Add_Delta_Days(@today,
2707 $searching_dow - $current_dow);
2708 @prev = Add_Delta_Days(@next,-7);
2709 }
2710 else
2711 {
2712 @prev = Add_Delta_Days(@today,
2713 $searching_dow - $current_dow);
2714 @next = Add_Delta_Days(@prev,+7);
2715 }
2716 }
2717
2718 $dow = Day_of_Week_to_Text($searching_dow);
2719
2720 print "Today is: ", ' ' x length($dow),
2721 Date_to_Text(@today), "\n";
2722 print "Last $dow was: ", Date_to_Text(@prev), "\n";
2723 print "Next $dow will be: ", Date_to_Text(@next), "\n";
2724
2725 This will print something like:
2726
2727 Today is: Sun 12-Apr-1998
2728 Last Saturday was: Sat 11-Apr-1998
2729 Next Saturday will be: Sat 18-Apr-1998
2730
2731 10) How can I calculate the last business day (payday!) of a month?
2732
2733 Solution #1 (holidays NOT taken into account):
2734
2735 use Date::Pcalc qw( Days_in_Month Day_of_Week Add_Delta_Days );
2736
2737 $day = Days_in_Month($year,$month);
2738 $dow = Day_of_Week($year,$month,$day);
2739 if ($dow > 5)
2740 {
2741 ($year,$month,$day) =
2742 Add_Delta_Days($year,$month,$day, 5-$dow);
2743 }
2744
2745 Solution #2 (holidays taken into account):
2746
2747 This solution expects a multi-dimensional array "@holiday", which
2748 contains all holidays, as follows: ""$holiday[$year][$month][$day]
2749 = 1;"".
2750
2751 (See the description of the function ""Easter_Sunday()"" further
2752 above for how to calculate the moving (variable) christian feast
2753 days!)
2754
2755 Days which are not holidays remain undefined or should have a value
2756 of zero in this array.
2757
2758 use Date::Pcalc qw( Days_in_Month Add_Delta_Days Day_of_Week );
2759
2760 $day = Days_in_Month($year,$month);
2761 while (1)
2762 {
2763 while ($holiday[$year][$month][$day])
2764 {
2765 ($year,$month,$day) =
2766 Add_Delta_Days($year,$month,$day, -1);
2767 }
2768 $dow = Day_of_Week($year,$month,$day);
2769 if ($dow > 5)
2770 {
2771 ($year,$month,$day) =
2772 Add_Delta_Days($year,$month,$day, 5-$dow);
2773 }
2774 else { last; }
2775 }
2776
2777 Solution #3 (holidays taken into account, more comfortable, but
2778 requires Date::Pcalendar(3) and Date::Pcalc::Object(3)):
2779
2780 use Date::Pcalc::Object qw( Today Add_Delta_YM Date_to_Text_Long );
2781 use Date::Pcalendar::Profiles qw($Profiles);
2782 use Date::Pcalendar;
2783
2784 $calendar = Date::Pcalendar->new( $Profiles->{'DE-BW'} );
2785
2786 @today = Today();
2787 @nextmonth = Add_Delta_YM(@today[0,1],1, 0,1);
2788
2789 $workaround = $calendar->add_delta_workdays(@nextmonth,+1);
2790 $payday = $calendar->add_delta_workdays($workaround,-2);
2791
2792 print "Pay day = ", Date_to_Text_Long($payday->date()), "\n";
2793
2794 The "workaround" is necessary due to a bug in the method
2795 "add_delta_workdays()" when adding a negative number of workdays.
2796
2797 11) How do I convert a MS Visual Basic "DATETIME" value into its date
2798 and time constituents?
2799
2800 use Date::Pcalc qw( Add_Delta_DHMS Date_to_Text );
2801
2802 $datetime = "35883.121653";
2803
2804 ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);
2805
2806 ($year,$month,$day, $hour,$min,$sec) =
2807 Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);
2808
2809 printf("The given date is %s %02d:%02d:%02d\n",
2810 Date_to_Text($year,$month,$day), $hour, $min, $sec);
2811
2812 This prints:
2813
2814 The given date is Tue 31-Mar-1998 12:16:53
2815
2816 Since I do not have or use Visual Basic, I can't guarantee that the
2817 number format assumed here is really the one used by Visual Basic -
2818 but you get the general idea. ":-)"
2819
2820 Moreover, consider the following:
2821
2822 Morten Sickel <Morten.Sickel@nrpa.no> wrote:
2823
2824 I discovered a bug in Excel (2000): Excel thinks that 1900 was a
2825 leap year. Users should use 31-Dec-1899 as the date to add an Excel
2826 date value to in order to get the correct date.
2827
2828 I found out on the web that this bug originated in Lotus 123, which
2829 made 29-Feb-1900 an "industrial standard". MS chose to keep the bug
2830 in order to be compatible with Lotus 123. But they have not
2831 mentioned anything about it in the help files.
2832
2833 12) How can I send a reminder to members of a group on the day before a
2834 meeting which occurs every first Friday of a month?
2835
2836 use Date::Pcalc qw( Today Date_to_Days Add_Delta_YMD
2837 Nth_Weekday_of_Month_Year );
2838
2839 ($year,$month,$day) = Today();
2840
2841 $tomorrow = Date_to_Days($year,$month,$day) + 1;
2842
2843 $dow = 5; # 5 = Friday
2844 $n = 1; # 1 = First of that day of week
2845
2846 $meeting_this_month = Date_to_Days(
2847 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2848
2849 ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);
2850
2851 $meeting_next_month = Date_to_Days(
2852 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2853
2854 if (($tomorrow == $meeting_this_month) ||
2855 ($tomorrow == $meeting_next_month))
2856 {
2857 # Send reminder e-mail!
2858 }
2859
2860 13) How can I print a date in a different format than provided by the
2861 functions ""Date_to_Text()"", ""Date_to_Text_Long()"" or
2862 ""Compressed_to_Text()""?
2863
2864 use Date::Pcalc qw( Today Day_of_Week_to_Text
2865 Day_of_Week Month_to_Text
2866 English_Ordinal );
2867
2868 ($year,$month,$day) = Today();
2869
2870 For example with leading zeros for the day: "Fri 03-Jan-1964"
2871
2872 printf("%.3s %02d-%.3s-%d\n",
2873 Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
2874 $day,
2875 Month_to_Text($month),
2876 $year);
2877
2878 For example in U.S. american format: "April 12th, 1998"
2879
2880 $string = sprintf("%s %s, %d",
2881 Month_to_Text($month),
2882 English_Ordinal($day),
2883 $year);
2884
2885 For example in one of the possible formats as specified by
2886 ISOÂ 8601:
2887
2888 @date = ($year,$month,$day,$hour,$min,$sec);
2889 $date = sprintf("%d-%02d-%02d %02d:%02d:%02d", @date);
2890
2891 (See also "printf" in perlfunc(1) and/or "sprintf" in perlfunc(1)!)
2892
2893 14) How can I iterate through a range of dates?
2894
2895 use Date::Pcalc qw( Delta_Days Add_Delta_Days );
2896
2897 @start = (1999,5,27);
2898 @stop = (1999,6,1);
2899
2900 $j = Delta_Days(@start,@stop);
2901
2902 for ( $i = 0; $i <= $j; $i++ )
2903 {
2904 @date = Add_Delta_Days(@start,$i);
2905 printf("%4d/%02d/%02d\n", @date);
2906 }
2907
2908 Note that the loop can be improved; see also the recipe below.
2909
2910 15) How can I create a (Perl) list of dates in a certain range?
2911
2912 use Date::Pcalc qw( Delta_Days Add_Delta_Days Date_to_Text );
2913
2914 sub date_range
2915 {
2916 my(@date) = (@_)[0,1,2];
2917 my(@list);
2918 my($i);
2919
2920 $i = Delta_Days(@_);
2921 while ($i-- >= 0)
2922 {
2923 push( @list, [ @date ] );
2924 @date = Add_Delta_Days(@date, 1) if ($i >= 0);
2925 }
2926 return(@list);
2927 }
2928
2929 @range = &date_range(1999,11,3, 1999,12,24); # in chronological order
2930
2931 foreach $date (@range)
2932 {
2933 print Date_to_Text(@{$date}), "\n";
2934 }
2935
2936 Note that you probably shouldn't use this one, because it is much
2937 more efficient to iterate through all the dates (as shown in the
2938 recipe immediately above) than to construct such an array and then
2939 to loop through it. Also, it is much more space-efficient not to
2940 create this array.
2941
2942 16) How can I calculate the difference in days between dates, but
2943 without counting Saturdays and Sundays?
2944
2945 sub Delta_Business_Days
2946 {
2947 my(@date1) = (@_)[0,1,2];
2948 my(@date2) = (@_)[3,4,5];
2949 my($minus,$result,$dow1,$dow2,$diff,$temp);
2950
2951 $minus = 0;
2952 $result = Delta_Days(@date1,@date2);
2953 if ($result != 0)
2954 {
2955 if ($result < 0)
2956 {
2957 $minus = 1;
2958 $result = -$result;
2959 $dow1 = Day_of_Week(@date2);
2960 $dow2 = Day_of_Week(@date1);
2961 }
2962 else
2963 {
2964 $dow1 = Day_of_Week(@date1);
2965 $dow2 = Day_of_Week(@date2);
2966 }
2967 $diff = $dow2 - $dow1;
2968 $temp = $result;
2969 if ($diff != 0)
2970 {
2971 if ($diff < 0)
2972 {
2973 $diff += 7;
2974 }
2975 $temp -= $diff;
2976 $dow1 += $diff;
2977 if ($dow1 > 6)
2978 {
2979 $result--;
2980 if ($dow1 > 7)
2981 {
2982 $result--;
2983 }
2984 }
2985 }
2986 if ($temp != 0)
2987 {
2988 $temp /= 7;
2989 $result -= ($temp << 1);
2990 }
2991 }
2992 if ($minus) { return -$result; }
2993 else { return $result; }
2994 }
2995
2996 This solution is probably of little practical value, however,
2997 because it doesn't take legal holidays into account.
2998
2999 See Date::Pcalendar(3) for how to do that.
3000
3001 17) How can I "normalize" the output of the "Delta_YMDHMS()" (or
3002 "Delta_YMD()") function so that it contains only positive values?
3003
3004 I.e., how can I show a difference in date (and time) in a more
3005 human-readable form, for example in order to show how much time
3006 until (or since) the expiration of something (e.g. an account, a
3007 domain, a credit card, etc.) is left (has passed)?
3008
3009 Correct solution: Use the functions "N_Delta_YMDHMS()" and
3010 "N_Delta_YMD()" instead!
3011
3012 The following gives a rudimentary sketch of a (much inferior)
3013 solution, which is maintained here only for historical reasons of
3014 this module:
3015
3016 a) Delta_YMDHMS():
3017
3018 #!perl
3019 use strict;
3020 use Date::Pcalc qw(Today_and_Now Delta_YMDHMS Add_Delta_YMDHMS Delta_DHMS Date_to_Text);
3021
3022 my $today = [Today_and_Now()];
3023 my $target = [2005,1,1,0,0,0];
3024
3025 my $sign = "until";
3026 my $delta = Normalize_Delta_YMDHMS($today,$target);
3027 if ($delta->[0] < 0)
3028 {
3029 $sign = "since";
3030 $delta = Normalize_Delta_YMDHMS($target,$today);
3031 }
3032 printf("Today is %s %02d:%02d:%02d\n", Date_to_Text(@{$today}[0..2]), @{$today}[3..5]);
3033 printf
3034 (
3035 "%d year%s, %d month%s, %d day%s, %d hour%s, %d minute%s, %d second%s %s %s %02d:%02d:%02d\n",
3036 $delta->[0], (($delta->[0]==1)?'':'s'),
3037 $delta->[1], (($delta->[1]==1)?'':'s'),
3038 $delta->[2], (($delta->[2]==1)?'':'s'),
3039 $delta->[3], (($delta->[3]==1)?'':'s'),
3040 $delta->[4], (($delta->[4]==1)?'':'s'),
3041 $delta->[5], (($delta->[5]==1)?'':'s'),
3042 $sign,
3043 Date_to_Text(@{$target}[0..2]),
3044 @{$target}[3..5]
3045 );
3046
3047 sub Normalize_Delta_YMDHMS
3048 {
3049 my($date1,$date2) = @_;
3050 my(@delta);
3051
3052 @delta = Delta_YMDHMS(@$date1,@$date2);
3053 while ($delta[1] < 0 or
3054 $delta[2] < 0 or
3055 $delta[3] < 0 or
3056 $delta[4] < 0 or
3057 $delta[5] < 0)
3058 {
3059 if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3060 if ($delta[2] < 0)
3061 {
3062 $delta[1]--;
3063 @delta[2..5] = (0,0,0,0);
3064 @delta[2..5] = Delta_DHMS(Add_Delta_YMDHMS(@$date1,@delta),@$date2);
3065 }
3066 if ($delta[3] < 0) { $delta[2]--; $delta[3] += 24; }
3067 if ($delta[4] < 0) { $delta[3]--; $delta[4] += 60; }
3068 if ($delta[5] < 0) { $delta[4]--; $delta[5] += 60; }
3069 }
3070 return \@delta;
3071 }
3072
3073 b) Delta_YMD():
3074
3075 #!perl
3076 use strict;
3077 use Date::Pcalc qw(Today Delta_YMD Add_Delta_YM Delta_Days Date_to_Text);
3078
3079 my($sign,$delta);
3080 my $today = [Today()];
3081 my $target = [2005,1,1];
3082
3083 if (Delta_Days(@$today,@$target) < 0)
3084 {
3085 $sign = "since";
3086 $delta = Normalize_Delta_YMD($target,$today);
3087 }
3088 else
3089 {
3090 $sign = "until";
3091 $delta = Normalize_Delta_YMD($today,$target);
3092 }
3093 print "Today is ", Date_to_Text(@$today), "\n";
3094 printf
3095 (
3096 "%d year%s, %d month%s, %d day%s %s %s\n",
3097 $delta->[0], (($delta->[0]==1)?'':'s'),
3098 $delta->[1], (($delta->[1]==1)?'':'s'),
3099 $delta->[2], (($delta->[2]==1)?'':'s'),
3100 $sign,
3101 Date_to_Text(@$target)
3102 );
3103
3104 sub Normalize_Delta_YMD
3105 {
3106 my($date1,$date2) = @_;
3107 my(@delta);
3108
3109 @delta = Delta_YMD(@$date1,@$date2);
3110 while ($delta[1] < 0 or $delta[2] < 0)
3111 {
3112 if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3113 if ($delta[2] < 0)
3114 {
3115 $delta[1]--;
3116 $delta[2] = Delta_Days(Add_Delta_YM(@$date1,@delta[0,1]),@$date2);
3117 }
3118 }
3119 return \@delta;
3120 }
3121
3122 Note that for normalizing just a time vector, you can use the
3123 built-in function "Normalize_DHMS()". However, this will yield
3124 either all positive OR all negative values, NOT all positive values
3125 as above.
3126
3128 Date::Calc(3), Date::Calc::Util(3), Date::Pcalc::Object(3),
3129 Date::Pcalendar(3), Date::Pcalendar::Year(3),
3130 Date::Pcalendar::Profiles(3).
3131
3132 "The Calendar FAQ":
3133 http://www.tondering.dk/claus/calendar.html
3134 by Claus Tondering <claus@tondering.dk>
3135
3137 When you are using the (deprecated) function "Language()", the language
3138 setting is stored in a global variable.
3139
3140 This may cause conflicts between threads or modules running
3141 concurrently.
3142
3143 Therefore, in order to avoid such conflicts, NEVER use the function
3144 "Language()", but ALWAYS pass a language parameter to the functions
3145 which are language-dependent.
3146
3148 This man page documents "Date::Pcalc" version 6.1.
3149
3151 Steffen Beyer
3152 mailto:STBEY@cpan.org
3153 http://www.engelschall.com/u/sb/download/
3154
3156 Copyright (c) 1995 - 2009 by Steffen Beyer. All rights reserved.
3157
3159 This package is free software; you can redistribute it and/or modify it
3160 under the same terms as Perl itself, i.e., under the terms of the
3161 "Artistic License" or the "GNU General Public License".
3162
3163 Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
3164 distribution for details!
3165
3167 This package is distributed in the hope that it will be useful, but
3168 WITHOUT ANY WARRANTY; without even the implied warranty of
3169 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3170
3171 See the "GNU General Public License" for more details.
3172
3174 Hey! The above document had some coding errors, which are explained
3175 below:
3176
3177 Around line 1777:
3178 Non-ASCII character seen before =encoding in 'Français'. Assuming
3179 CP1252
3180
3181
3182
3183perl v5.32.0 2020-07-28 Pcalc(3)