1Date::Calc(3) User Contributed Perl Documentation Date::Calc(3)
2
3
4
6 Date::Calc - Gregorian calendar date calculations
7
9 Keep it small, fast and simple
10
12 This package consists of a C library and a Perl module (which uses the
13 C library, internally) for all kinds of date calculations based on the
14 Gregorian calendar (the one used in all western countries today),
15 thereby complying with all relevant norms and standards:
16 ISO/RÂ 2015-1971, DINÂ 1355 and, to some extent, ISOÂ 8601 (where
17 applicable).
18
19 (See also http://www.engelschall.com/u/sb/download/Date-Calc/DIN1355/
20 for a scan of part of the "DINÂ 1355" document (in German)).
21
22 The module of course handles year numbers of 2000 and above correctly
23 ("Year 2000" or "Y2K" compliance) -- actually all year numbers from 1
24 to the largest positive integer representable on your system (which is
25 at least 32767) can be dealt with.
26
27 This is not true, however, for the import/export functions in this
28 package which are an interface to the internal POSIX date and time
29 functions of your system, which can only cover dates in the following
30 ranges:
31
32 01-Jan-1970 00:00:00 GMT .. 19-Jan-2038 03:14:07 GMT [Unix etc.]
33 01-Jan-1904 00:00:00 LT .. 06-Feb-2040 06:28:15 LT [MacOS Classic]
34 (LT = local time)
35
36 Note that this package projects the Gregorian calendar back until the
37 year 1Â A.D. -- even though the Gregorian calendar was only adopted in
38 1582, mostly by the Catholic European countries, in obedience to the
39 corresponding decree of Pope Gregory XIII in that year.
40
41 Some (mainly protestant) countries continued to use the Julian calendar
42 (used until then) until as late as the beginning of the 20th century.
43
44 Finally, note that this package is not intended to do everything you
45 could ever imagine automagically for you; it is rather intended to
46 serve as a toolbox (in the best of UNIX spirit and traditions) which
47 should, however, always get you where you want to go.
48
49 See the section "RECIPES" at the bottom of this document for solutions
50 to common problems!
51
52 If nevertheless you can't figure out how to solve a particular problem,
53 please let me know! (See e-mail address at the end of this document.)
54
56 use Date::Calc qw(
57 Days_in_Year
58 Days_in_Month
59 Weeks_in_Year
60 leap_year
61 check_date
62 check_time
63 check_business_date
64 Day_of_Year
65 Date_to_Days
66 Day_of_Week
67 Week_Number
68 Week_of_Year
69 Monday_of_Week
70 Nth_Weekday_of_Month_Year
71 Standard_to_Business
72 Business_to_Standard
73 Delta_Days
74 Delta_DHMS
75 Delta_YMD
76 Delta_YMDHMS
77 N_Delta_YMD
78 N_Delta_YMDHMS
79 Normalize_DHMS
80 Add_Delta_Days
81 Add_Delta_DHMS
82 Add_Delta_YM
83 Add_Delta_YMD
84 Add_Delta_YMDHMS
85 Add_N_Delta_YMD
86 Add_N_Delta_YMDHMS
87 System_Clock
88 Today
89 Now
90 Today_and_Now
91 This_Year
92 Gmtime
93 Localtime
94 Mktime
95 Timezone
96 Date_to_Time
97 Time_to_Date
98 Easter_Sunday
99 Decode_Month
100 Decode_Day_of_Week
101 Decode_Language
102 Decode_Date_EU
103 Decode_Date_US
104 Fixed_Window
105 Moving_Window
106 Compress
107 Uncompress
108 check_compressed
109 Compressed_to_Text
110 Date_to_Text
111 Date_to_Text_Long
112 English_Ordinal
113 Calendar
114 Month_to_Text
115 Day_of_Week_to_Text
116 Day_of_Week_Abbreviation
117 Language_to_Text
118 Language
119 Languages
120 Decode_Date_EU2
121 Decode_Date_US2
122 Parse_Date
123 ISO_LC
124 ISO_UC
125 );
126
127 use Date::Calc qw(:all);
128
129 Days_in_Year
130 $days = Days_in_Year($year,$month);
131
132 Days_in_Month
133 $days = Days_in_Month($year,$month);
134
135 Weeks_in_Year
136 $weeks = Weeks_in_Year($year);
137
138 leap_year
139 if (leap_year($year))
140
141 check_date
142 if (check_date($year,$month,$day))
143
144 check_time
145 if (check_time($hour,$min,$sec))
146
147 check_business_date
148 if (check_business_date($year,$week,$dow))
149
150 Day_of_Year
151 $doy = Day_of_Year($year,$month,$day);
152
153 Date_to_Days
154 $days = Date_to_Days($year,$month,$day);
155
156 Day_of_Week
157 $dow = Day_of_Week($year,$month,$day);
158
159 Week_Number
160 $week = Week_Number($year,$month,$day); # DEPRECATED
161
162 Week_of_Year
163 ($week,$year) = Week_of_Year($year,$month,$day); # RECOMMENDED
164 $week = Week_of_Year($year,$month,$day); # DANGEROUS
165
166 Monday_of_Week
167 ($year,$month,$day) = Monday_of_Week($week,$year);
168
169 Nth_Weekday_of_Month_Year
170 if (($year,$month,$day) =
171 Nth_Weekday_of_Month_Year($year,$month,$dow,$n))
172
173 Standard_to_Business
174 ($year,$week,$dow) =
175 Standard_to_Business($year,$month,$day);
176
177 Business_to_Standard
178 ($year,$month,$day) =
179 Business_to_Standard($year,$week,$dow);
180
181 Delta_Days
182 $Dd = Delta_Days($year1,$month1,$day1,
183 $year2,$month2,$day2);
184
185 Delta_DHMS
186 ($Dd,$Dh,$Dm,$Ds) =
187 Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
188 $year2,$month2,$day2, $hour2,$min2,$sec2);
189
190 Delta_YMD
191 ($Dy,$Dm,$Dd) =
192 Delta_YMD($year1,$month1,$day1,
193 $year2,$month2,$day2);
194
195 Delta_YMDHMS
196 ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) =
197 Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
198 $year2,$month2,$day2, $hour2,$min2,$sec2);
199
200 N_Delta_YMD
201 ($Dy,$Dm,$Dd) =
202 N_Delta_YMD($year1,$month1,$day1,
203 $year2,$month2,$day2);
204
205 N_Delta_YMDHMS
206 ($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
207 N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
208 $year2,$month2,$day2, $hour2,$min2,$sec2);
209
210 Normalize_DHMS
211 ($Dd,$Dh,$Dm,$Ds) =
212 Normalize_DHMS($Dd,$Dh,$Dm,$Ds);
213
214 Add_Delta_Days
215 ($year,$month,$day) =
216 Add_Delta_Days($year,$month,$day,
217 $Dd);
218
219 Add_Delta_DHMS
220 ($year,$month,$day, $hour,$min,$sec) =
221 Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec,
222 $Dd,$Dh,$Dm,$Ds);
223
224 Add_Delta_YM
225 ($year,$month,$day) =
226 Add_Delta_YM($year,$month,$day,
227 $Dy,$Dm);
228
229 Add_Delta_YMD
230 ($year,$month,$day) =
231 Add_Delta_YMD($year,$month,$day,
232 $Dy,$Dm,$Dd);
233
234 Add_Delta_YMDHMS
235 ($year,$month,$day, $hour,$min,$sec) =
236 Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
237 $D_y,$D_m,$D_d, $Dh,$Dm,$Ds);
238
239 Add_N_Delta_YMD
240 ($year,$month,$day) =
241 Add_N_Delta_YMD($year,$month,$day,
242 $Dy,$Dm,$Dd);
243
244 Add_N_Delta_YMDHMS
245 ($year,$month,$day, $hour,$min,$sec) =
246 Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
247 $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);
248
249 System_Clock
250 ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
251 System_Clock([$gmt]);
252
253 Today
254 ($year,$month,$day) = Today([$gmt]);
255
256 Now
257 ($hour,$min,$sec) = Now([$gmt]);
258
259 Today_and_Now
260 ($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);
261
262 This_Year
263 $year = This_Year([$gmt]);
264
265 Gmtime
266 ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
267 Gmtime([time]);
268
269 Localtime
270 ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
271 Localtime([time]);
272
273 Mktime
274 $time = Mktime($year,$month,$day, $hour,$min,$sec);
275
276 Timezone
277 ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);
278
279 Date_to_Time
280 $time = Date_to_Time($year,$month,$day, $hour,$min,$sec);
281
282 Time_to_Date
283 ($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
284
285 Easter_Sunday
286 ($year,$month,$day) = Easter_Sunday($year);
287
288 Decode_Month
289 if ($month = Decode_Month($string[,$lang]))
290
291 Decode_Day_of_Week
292 if ($dow = Decode_Day_of_Week($string[,$lang]))
293
294 Decode_Language
295 if ($lang = Decode_Language($string))
296
297 Decode_Date_EU
298 if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))
299
300 Decode_Date_US
301 if (($year,$month,$day) = Decode_Date_US($string[,$lang]))
302
303 Fixed_Window
304 $year = Fixed_Window($yy);
305
306 Moving_Window
307 $year = Moving_Window($yy);
308
309 Compress
310 $date = Compress($year,$month,$day);
311
312 Uncompress
313 if (($century,$year,$month,$day) = Uncompress($date))
314
315 check_compressed
316 if (check_compressed($date))
317
318 Compressed_to_Text
319 $string = Compressed_to_Text($date[,$lang]);
320
321 Date_to_Text
322 $string = Date_to_Text($year,$month,$day[,$lang]);
323
324 Date_to_Text_Long
325 $string = Date_to_Text_Long($year,$month,$day[,$lang]);
326
327 English_Ordinal
328 $string = English_Ordinal($number);
329
330 Calendar
331 $string = Calendar($year,$month[,$orthodox[,$lang]]);
332
333 Month_to_Text
334 $string = Month_to_Text($month[,$lang]);
335
336 Day_of_Week_to_Text
337 $string = Day_of_Week_to_Text($dow[,$lang]);
338
339 Day_of_Week_Abbreviation
340 $string = Day_of_Week_Abbreviation($dow[,$lang]);
341
342 Language_to_Text
343 $string = Language_to_Text($lang);
344
345 Language
346 $lang = Language();
347 Language($lang); # DEPRECATED
348 $oldlang = Language($newlang); # DEPRECATED
349
350 Languages
351 $max_lang = Languages();
352
353 Decode_Date_EU2
354 if (($year,$month,$day) = Decode_Date_EU2($string[,$lang]))
355
356 Decode_Date_US2
357 if (($year,$month,$day) = Decode_Date_US2($string[,$lang]))
358
359 Parse_Date
360 if (($year,$month,$day) = Parse_Date($string[,$lang]))
361
362 ISO_LC
363 $lower = ISO_LC($string);
364
365 ISO_UC
366 $upper = ISO_UC($string);
367
368 Version
369 $string = Date::Calc::Version();
370
372 (See the section "RECIPES" at the bottom of this document for solutions
373 to common problems!)
374
375 • "Year 2000" ("Y2K") compliance
376
377 The upper limit for any year number in this module is only given by
378 the size of the largest positive integer that can be represented in a
379 variable of the C type "int" on your system, which is at least 32767,
380 according to the ANSI C standard (exceptions see below).
381
382 In order to simplify calculations, this module projects the gregorian
383 calendar back until the year 1Â A.D. -- i.e., back BEYOND the year
384 1582 when this calendar was first decreed by the Catholic Pope
385 Gregory XIII!
386
387 Therefore, BE SURE TO ALWAYS SPECIFY "1998" WHEN YOU MEAN "1998", for
388 instance, and DO NOT WRITE "98" INSTEAD, because this will in fact
389 perform a calculation based on the year "98" A.D. and NOT "1998"!
390
391 An exception from this rule are the functions which contain the word
392 "compress" in their names (which can only handle years between 1970
393 and 2069 and also accept the abbreviations "00" to "99"), and the
394 functions whose names begin with "Decode_Date_" (which translate year
395 numbers below 100 using a technique known as "moving window").
396
397 If you want to convert a two-digit year number into a full-fledged,
398 four-digit (at least for some years to come ";-)") year number, use
399 the two functions "Fixed_Window()" and "Moving_Window()" (see their
400 description further below).
401
402 Note also that the following import/export functions (which are
403 interfaces to the POSIX functions "time()", "gmtime()", "localtime()"
404 and "mktime()" or (the last two) substitutes for the BSD function
405 "timegm()" and the POSIX function "gmtime()") have a very limited
406 range of representable dates (in contrast to all other functions in
407 this package, which cover virtually any date including and after
408 January 1st 1 A.D.):
409
410 System_Clock()
411 Today()
412 Now()
413 Today_and_Now()
414 This_Year()
415 Gmtime()
416 Localtime()
417 Mktime()
418 Timezone()
419 Date_to_Time()
420 Time_to_Date()
421
422 These functions can only deal with dates in the range from
423 01-Jan-1970Â 00:00:00Â GMT to 19-Jan-2038Â 03:14:07Â GMT (the latter
424 limit is only authoritative on 32Â bit systems, however, and can (in
425 principle, through a few code changes) be extended somewhat ":-)" on
426 64Â bit systems).
427
428 On MacOS Classic, the valid range of dates is between (both included)
429 01-Jan-1904Â 00:00:00 (local time) to 06-Feb-2040Â 06:28:15 (local
430 time).
431
432 Note further that the function "Easter_Sunday()" can only be used for
433 years in the range 1583 to 2299.
434
435 • POSIX functions
436
437 Note that the following functions
438
439 Gmtime()
440 Localtime()
441 Mktime()
442 Timezone()
443
444 are actually wrappers around or based upon the corresponding POSIX
445 functions "time()", "gmtime()", "localtime()" and "mktime()".
446
447 As such, they depend on local settings of the underlying machine such
448 as e.g. the system clock, the time zone and the locale.
449
450 Their results can therefore sometimes be unexpected or counter-
451 intuitive.
452
453 Therefore, no support can be provided for these functions.
454
455 They are supplied "as is", purely for the sake of interoperability.
456
457 Use at your own risk. (You have been warned!)
458
459 • First index
460
461 ALL ranges in this module start with "1", NOT "0"!
462
463 I.e., the day of month, day of week, day of year, month of year, week
464 of year, first valid year number and language ALL start counting at
465 one, NOT zero!
466
467 The only exception is the function ""Week_Number()"", which may in
468 fact return "0" when the given date actually lies in the last week of
469 the PREVIOUS year, and of course the numbers for hours (0..23),
470 minutes (0..59) and seconds (0..59).
471
472 • Function naming conventions
473
474 Function names completely in lower case indicate a boolean return
475 value.
476
477 • Boolean values
478
479 Boolean values returned from functions in this module are always a
480 numeric zero ("0") for "false" and a numeric one ("1") for "true".
481
482 • Exception handling
483
484 The functions in this module will usually die with a corresponding
485 error message if their input parameters, intermediate results or
486 output values are out of range.
487
488 The following functions handle errors differently:
489
490 - check_date()
491 - check_time()
492 - check_business_date()
493 - check_compressed()
494
495 (which return a "false" return value when the given input does not
496 represent a valid date or time),
497
498 - Nth_Weekday_of_Month_Year()
499
500 (which returns an empty list if the requested 5th day of week does
501 not exist),
502
503 - Decode_Month()
504 - Decode_Day_of_Week()
505 - Decode_Language()
506 - Fixed_Window()
507 - Moving_Window()
508 - Compress()
509
510 (which return "0" upon failure or invalid input), and
511
512 - Decode_Date_EU()
513 - Decode_Date_US()
514 - Decode_Date_EU2()
515 - Decode_Date_US2()
516 - Parse_Date()
517 - Uncompress()
518
519 (which return an empty list upon failure or invalid input).
520
521 Note that you can always catch an exception thrown by any of the
522 functions in this module and handle it yourself by enclosing the
523 function call in an ""eval"" with curly brackets and checking the
524 special variable "$@" (see "eval" in perlfunc(1) for details).
525
527 • "use Date::Calc qw( Days_in_Year Days_in_Month ... );"
528
529 • "use Date::Calc qw(:all);"
530
531 You can either specify the functions you want to import explicitly by
532 enumerating them between the parentheses of the ""qw()"" operator, or
533 you can use the "":all"" tag instead to import ALL available
534 functions.
535
536 • "$days = Days_in_Year($year,$month);"
537
538 This function returns the sum of the number of days in the months
539 starting with January up to and including "$month" in the given year
540 "$year".
541
542 I.e., ""Days_in_Year(1998,1)"" returns "31", ""Days_in_Year(1998,2)""
543 returns "59", ""Days_in_Year(1998,3)"" returns "90", and so on.
544
545 Note that ""Days_in_Year($year,12)"" returns the number of days in
546 the given year "$year", i.e., either "365" or "366".
547
548 • "$days = Days_in_Month($year,$month);"
549
550 This function returns the number of days in the given month "$month"
551 of the given year "$year".
552
553 The year must always be supplied, even though it is only needed when
554 the month is February, in order to determine whether it is a leap
555 year or not.
556
557 I.e., ""Days_in_Month(1998,1)"" returns "31",
558 ""Days_in_Month(1998,2)"" returns "28", ""Days_in_Month(2000,2)""
559 returns "29", ""Days_in_Month(1998,3)"" returns "31", and so on.
560
561 • "$weeks = Weeks_in_Year($year);"
562
563 This function returns the number of weeks in the given year "$year",
564 i.e., either "52" or "53".
565
566 • "if (leap_year($year))"
567
568 This function returns "true" ("1") if the given year "$year" is a
569 leap year and "false" ("0") otherwise.
570
571 • "if (check_date($year,$month,$day))"
572
573 This function returns "true" ("1") if the given three numerical
574 values "$year", "$month" and "$day" constitute a valid date, and
575 "false" ("0") otherwise.
576
577 • "if (check_time($hour,$min,$sec))"
578
579 This function returns "true" ("1") if the given three numerical
580 values "$hour", "$min" and "$sec" constitute a valid time ("0 <=
581 $hour < 24", "0 <= $min < 60" and "0 <= $sec < 60"), and "false"
582 ("0") otherwise.
583
584 • "if (check_business_date($year,$week,$dow))"
585
586 This function returns "true" ("1") if the given three numerical
587 values "$year", "$week" and "$dow" constitute a valid date in
588 business format, and "false" ("0") otherwise.
589
590 Beware that this function does NOT compute whether a given date is a
591 business day (i.e., Monday to Friday)!
592
593 To do so, use ""(Day_of_Week($year,$month,$day) < 6)"" instead.
594
595 • "$doy = Day_of_Year($year,$month,$day);"
596
597 This function returns the (relative) number of the day of the given
598 date in the given year.
599
600 E.g., ""Day_of_Year($year,1,1)"" returns "1",
601 ""Day_of_Year($year,2,1)"" returns "32", and
602 ""Day_of_Year($year,12,31)"" returns either "365" or "366".
603
604 The day of year is sometimes also referred to as the Julian day (or
605 date), although it has nothing to do with the Julian calendar, the
606 calendar which was used before the Gregorian calendar.
607
608 In order to convert the number returned by this function back into a
609 date, use the function ""Add_Delta_Days()"" (described further
610 below), as follows:
611
612 $doy = Day_of_Year($year,$month,$day);
613 ($year,$month,$day) = Add_Delta_Days($year,1,1, $doy - 1);
614
615 • "$days = Date_to_Days($year,$month,$day);"
616
617 This function returns the (absolute) number of the day of the given
618 date, where counting starts at the 1st of January of the year 1Â A.D.
619
620 I.e., ""Date_to_Days(1,1,1)"" returns "1", ""Date_to_Days(1,12,31)""
621 returns "365", ""Date_to_Days(2,1,1)"" returns "366",
622 ""Date_to_Days(1998,5,1)"" returns "729510", and so on.
623
624 This is sometimes also referred to (not quite correctly) as the
625 Julian date (or day). This may cause confusion, because also the
626 number of the day in a year (from 1 to 365 or 366) is frequently
627 called the "Julian day".
628
629 More confusing still, this has nothing to do with the Julian
630 calendar, which was used BEFORE the Gregorian calendar.
631
632 The Julian calendar was named after famous Julius Caesar, who had
633 instituted it in Roman times. The Julian calendar is less precise
634 than the Gregorian calendar because it has too many leap years
635 compared to the true mean length of a year (but the Gregorian
636 calendar also still has one day too much every 5000 years). Anyway,
637 the Julian calendar was better than what existed before, because
638 rulers had often changed the calendar used until then in arbitrary
639 ways, in order to lengthen their own reign, for instance.
640
641 In order to convert the number returned by this function back into a
642 date, use the function ""Add_Delta_Days()"" (described further
643 below), as follows:
644
645 $days = Date_to_Days($year,$month,$day);
646 ($year,$month,$day) = Add_Delta_Days(1,1,1, $days - 1);
647
648 • "$dow = Day_of_Week($year,$month,$day);"
649
650 This function returns the number of the day of week of the given
651 date.
652
653 The function returns "1" for Monday, "2" for Tuesday and so on until
654 "7" for Sunday.
655
656 Note that in the Hebrew calendar (on which the Christian calendar is
657 based), the week starts with Sunday and ends with the Sabbath or
658 Saturday (where according to the Genesis (as described in the Bible)
659 the Lord rested from creating the world).
660
661 In medieval times, Catholic Popes have decreed the Sunday to be the
662 official day of rest, in order to dissociate the Christian from the
663 Hebrew belief.
664
665 It appears that this actually happened with the Emperor Constantin,
666 who converted to Christianity but still worshipped the Sun god and
667 therefore moved the Christian sabbath to the day of the Sun.
668
669 Nowadays, the Sunday AND the Saturday are commonly considered (and
670 used as) days of rest, usually referred to as the "week-end".
671
672 Consistent with this practice, current norms and standards (such as
673 ISO/RÂ 2015-1971, DINÂ 1355 and ISOÂ 8601) define the Monday as the
674 first day of the week.
675
676 • "$week = Week_Number($year,$month,$day);"
677
678 This function returns the number of the week the given date lies in.
679
680 If the given date lies in the LAST week of the PREVIOUS year, "0" is
681 returned.
682
683 If the given date lies in the FIRST week of the NEXT year,
684 ""Weeks_in_Year($year) + 1"" is returned.
685
686 • "($week,$year) = Week_of_Year($year,$month,$day);"
687
688 This function returns the number of the week the given date lies in,
689 as well as the year that week belongs to.
690
691 I.e., if the given date lies in the LAST week of the PREVIOUS year,
692 ""(Weeks_in_Year($year-1), $year-1)"" is returned.
693
694 If the given date lies in the FIRST week of the NEXT year, ""(1,
695 $year+1)"" is returned.
696
697 Otherwise, ""(Week_Number($year,$month,$day), $year)"" is returned.
698
699 • "$week = Week_of_Year($year,$month,$day);"
700
701 In scalar context, this function returns just the week number. This
702 allows you to write ""$week = Week_of_Year($year,$month,$day);""
703 instead of ""($week) = Week_of_Year($year,$month,$day);"" (note the
704 parentheses around "$week").
705
706 If the given date lies in the LAST week of the PREVIOUS year,
707 ""Weeks_in_Year($year-1)"" is returned.
708
709 If the given date lies in the FIRST week of the NEXT year, "1" is
710 returned.
711
712 Otherwise the return value is identical with that of
713 ""Week_Number($year,$month,$day)"".
714
715 BEWARE that using this function in scalar context is a DANGEROUS
716 feature, because without knowing which year the week belongs to, you
717 might inadvertently assume the wrong one!
718
719 If for instance you are iterating through an interval of dates, you
720 might assume that the week always belongs to the same year as the
721 given date, which unfortunately is WRONG in some cases!
722
723 In many years, the 31st of December for instance belongs to week
724 number one of the FOLLOWING year. Assuming that the year is the same
725 as your date (31st of December, in this example), sends you back to
726 the first week of the CURRENT year - the Monday of which, by the way,
727 in case of bad luck, might actually lie in the year BEFORE the
728 current year!
729
730 This actually happens in 2002, for example.
731
732 So you always need to provide the correct corresponding year number
733 by other means, keeping track of it yourself.
734
735 In case you do not understand this, never mind, but then simply DO
736 NOT USE this function in scalar context!
737
738 • "($year,$month,$day) = Monday_of_Week($week,$year);"
739
740 This function returns the date of the first day of the given week,
741 i.e., the Monday.
742
743 "$year" must be greater than or equal to "1", and "$week" must lie in
744 the range "1" to ""Weeks_in_Year($year)"".
745
746 Note that you can write ""($year,$month,$day) =
747 Monday_of_Week(Week_of_Year($year,$month,$day));"" in order to
748 calculate the date of the Monday of the same week as the given date.
749
750 If you want to calculate any other day of week in the same week as a
751 given date, use
752
753 @date = Add_Delta_Days(Monday_of_Week(Week_of_Year(@date)),$offset);
754
755 where "$offset = 1" for Tuesday, 2 for Wednesday etc.
756
757 • "if (($year,$month,$day) =
758 Nth_Weekday_of_Month_Year($year,$month,$dow,$n))"
759
760 This function calculates the date of the "$n"th day of week "$dow" in
761 the given month "$month" and year "$year"; such as, for example, the
762 3rd Thursday of a given month and year.
763
764 This can be used to send a notification mail to the members of a
765 group which meets regularly on every 3rd Thursday of a month, for
766 instance.
767
768 (See the section "RECIPES" near the end of this document for a code
769 snippet to actually do so.)
770
771 "$year" must be greater than or equal to "1", "$month" must lie in
772 the range "1" to "12", "$dow" must lie in the range "1" to "7" and
773 "$n" must lie in the range "1" to "5", or a fatal error (with
774 appropriate error message) occurs.
775
776 The function returns an empty list when the 5th of a given day of
777 week does not exist in the given month and year.
778
779 • "($year,$week,$dow) = Standard_to_Business($year,$month,$day);"
780
781 This function converts a given date from standard notation (year,
782 month, day (of month)) to business notation (year, week, day of
783 week).
784
785 • "($year,$month,$day) = Business_to_Standard($year,$week,$dow);"
786
787 This function converts a given date from business notation (year,
788 week, day of week) to standard notation (year, month, day (of
789 month)).
790
791 • "$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);"
792
793 This function returns the difference in days between the two given
794 dates.
795
796 The result is positive if the two dates are in chronological order,
797 i.e., if date #1 comes chronologically BEFORE date #2, and negative
798 if the order of the two dates is reversed.
799
800 The result is zero if the two dates are identical.
801
802 • "($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1,
803 $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"
804
805 This function returns the difference in days, hours, minutes and
806 seconds between the two given dates with times.
807
808 All four return values will be positive if the two dates are in
809 chronological order, i.e., if date #1 comes chronologically BEFORE
810 date #2, and negative (in all four return values!) if the order of
811 the two dates is reversed.
812
813 This is so that the two functions ""Delta_DHMS()"" and
814 ""Add_Delta_DHMS()"" (description see further below) are
815 complementary, i.e., mutually inverse:
816
817 Add_Delta_DHMS(@date1,@time1, Delta_DHMS(@date1,@time1, @date2,@time2))
818
819 yields ""(@date2,@time2)"" again, whereas
820
821 Add_Delta_DHMS(@date2,@time2,
822 map(-$_, Delta_DHMS(@date1,@time1, @date2,@time2)))
823
824 yields ""(@date1,@time1)"", and
825
826 Delta_DHMS(@date1,@time1, Add_Delta_DHMS(@date1,@time1, @delta))
827
828 yields "@delta" again.
829
830 The result is zero (in all four return values) if the two dates and
831 times are identical.
832
833 • "($Dy,$Dm,$Dd) = Delta_YMD($year1,$month1,$day1,
834 $year2,$month2,$day2);"
835
836 This function returns the vector
837
838 ( $year2 - $year1, $month2 - $month1, $day2 - $day1 )
839
840 This is called the "one-by-one" semantics.
841
842 Adding the result of this function to the first date always yields
843 the second date again, and adding the negative result (where the
844 signs of all elements of the result vector have been flipped) to the
845 second date gives the first date. See also the description of the
846 function "Add_Delta_YMD()" further below.
847
848 Example:
849
850 (6,2,-30) == Delta_YMD(1996,1,31, 2002,3,1]);
851
852 [1996,1,31] + ( 6, 2,-30) = [2002,3, 1]
853 [2002,3, 1] + (-6,-2, 30) = [1996,1,31]
854
855 An error occurs if any of the two given dates is invalid.
856
857 • "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) = Delta_YMDHMS($year1,$month1,$day1,
858 $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"
859
860 This function is based on the function "Delta_YMD()" above but
861 additionally calculates the time difference. When a carry over from
862 the time difference occurs, the value of "$D_d" is adjusted
863 accordingly, thus giving the correct total date/time difference.
864
865 Arguments are expected to be in chronological order to yield a
866 (usually) positive result.
867
868 In any case, adding the result of this function to the first
869 date/time value ("$year1,$month1,$day1," "$hour1,$min1,$sec1") always
870 gives the second date/time value ("$year2,$month2,$day2,"
871 "$hour2,$min2,$sec2") again, and adding the negative result (with the
872 signs of all elements of the result vector flipped) to the second
873 date/time value gives the first date/time value.
874
875 See the function "Add_Delta_YMDHMS()" further below for adding a
876 date/time value and a date/time difference.
877
878 An error occurs if any of the given two date/time values is invalid.
879
880 • "($Dy,$Dm,$Dd) = N_Delta_YMD($year1,$month1,$day1,
881 $year2,$month2,$day2);"
882
883 This function returns the difference between the two given dates in a
884 more intuitive way (as far as possible - more on that see a bit
885 further below) than the function "Delta_YMD()" described above.
886
887 The "N" which precedes its name is meant to signify "new" or
888 "normalized".
889
890 This function is loosely based on recipe #17 b) (see the section
891 "RECIPES" below near the end of this document).
892
893 However, the code of recipe #17 b) actually does not treat positive
894 and negative values symmetrically and consistently.
895
896 This new routine does.
897
898 The return values of this function are guaranteed to all have the
899 same sign (or to be zero). This is why this function is called
900 "normalized".
901
902 Moreover, the results are guaranteed to be "minimal", in the sense
903 that "|$Dm| < 12" and "|$Dd| < 31" (which is equivalent to $Dm lying
904 in the range "[-11..+11]" and $Dd lying in the range "[-30..+30]").
905
906 When the results are applied (i.e., added) to the first given date in
907 a left-to-right order, the second given date is guaranteed to be
908 obtained, provided that intermediary results are truncated, as done
909 by the function "Add_Delta_YM()" (see further below), i.e., that
910 invalid intermediate dates such as e.g. [2009,2,31] will
911 automatically be transformed into [2009,2,28] (and not "wrapped" into
912 the next month, e.g. to [2009,3,3]).
913
914 This is called the "left-to-right with truncation" semantics.
915
916 Note that reversing the order of the given dates and reversing the
917 sign of each of the result values will not always add up.
918
919 Consider the dates [2008,2,29] and [2009,2,1]: their difference is
920 (0,11,3) ([2008,2,29] plus 11 months is [2009,1,29], which plus 3
921 days is [2009,2,1]), but the difference between [2009,2,1] and
922 [2008,2,29] is (0,-11,-1), and not (0,-11,-3) ([2009,2,1] minus 11
923 months is [2008,3,1], which minus one day is [2008,2,29]).
924
925 Another example: The difference between [1996,2,29] and [1997,2,28]
926 is (1,0,0) (observe the truncation of the invalid date [1997,2,29] to
927 [1997,2,28] here!), whereas the difference between [1997,2,28] and
928 [1996,2,29] is (0,-11,-28) ([1997,2,28] minus 11 months is
929 [1996,3,28], which minus 28 days is not [1996,3,0] but of course
930 [1996,2,29]).
931
932 "Benign" examples such as for instance the difference between
933 [1964,1,3] and [2009,9,10] are completely symmetrical: The difference
934 in this example is (45,8,7), whereas the difference between
935 [2009,9,10] and [1964,1,3] is (-45,-8,-7), as would normally be
936 expected. In this example, the result is also the same as the one
937 returned by "Delta_YMD()".
938
939 All these counter-intuitive effects are due to the fact that months
940 (and due to leap years, also years) do not correspond to a fixed
941 number of days, so the semantics of "plus one month" or "plus one
942 year" are in fact undefined.
943
944 The present function is an attempt to provide a definition which is
945 intuitive most of the time, and at least consistent the rest of the
946 time.
947
948 Other definitions are of course possible, but most often lead to
949 contradictions (e.g., the results and the given first date do not add
950 up to the second given date).
951
952 See the file "datecalc.pl" in the "examples" subdirectory of this
953 distribution for a way to play around with this function, or go to
954 http://www.engelschall.com/u/sb/datecalc/ for the online version.
955
956 An error occurs if any of the two given dates is invalid, or if any
957 intermediate result leads to an invalid date (this does not apply to
958 truncation, however, as explained above).
959
960 • "($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
961 N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
962 $year2,$month2,$day2, $hour2,$min2,$sec2);"
963
964 This function essentially does the same as the function
965 "N_Delta_YMD()" described immediately above, except that also the
966 difference in hours, minutes and seconds is taken into account.
967
968 This function is loosely based on recipe #17 a) (see the section
969 "RECIPES" below near the end of this document).
970
971 However, the code of recipe #17 a) actually does not treat positive
972 and negative values symmetrically and consistently.
973
974 This new routine does.
975
976 The return values of this function (including the time differences)
977 are guaranteed to all have the same sign (or to be zero). This is the
978 reason for the "N" that precedes the name of this function, which is
979 intended to mean "normalized" (or "new").
980
981 Moreover, the results are guaranteed to be "minimal", in the sense
982 that "|$D_m| < 12", "|$D_d| < 31", "|$Dhh| < 24", "|$Dmm| < 60" and
983 "|$Dss| < 60" (which is equivalent to $D_m lying in the range
984 "[-11..+11]", $D_d lying in the range "[-30..+30]", $Dhh lying in the
985 range "[-23..+23]", and $Dmm and $Dss both lying in the range
986 "[-59..+59]").
987
988 • "($Dd,$Dh,$Dm,$Ds) = Normalize_DHMS($Dd,$Dh,$Dm,$Ds);"
989
990 This function takes four arbitrary values for days, hours, minutes
991 and seconds (which may have different signs) and renormalizes them so
992 that the values for hours, minutes and seconds will lie in the ranges
993 "[-23..23]", "[-59..59]" and "[-59..59]", respectively, and so that
994 all four values have the same sign (or are zero).
995
996 The given values are left untouched, i.e., unchanged.
997
998 • "($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);"
999
1000 This function has two principal uses:
1001
1002 First, it can be used to calculate a new date, given an initial date
1003 and an offset (which may be positive or negative) in days, in order
1004 to answer questions like "today plus 90 days -- which date gives
1005 that?".
1006
1007 (In order to add a weeks offset, simply multiply the weeks offset
1008 with "7" and use that as your days offset.)
1009
1010 Second, it can be used to convert the canonical representation of a
1011 date, i.e., the number of that day (where counting starts at the 1st
1012 of January in 1Â A.D.), back into a date given as year, month and
1013 day.
1014
1015 Because counting starts at "1", you will actually have to subtract
1016 "1" from the canonical date in order to get back the original date:
1017
1018 $canonical = Date_to_Days($year,$month,$day);
1019
1020 ($year,$month,$day) = Add_Delta_Days(1,1,1, $canonical - 1);
1021
1022 Moreover, this function is the inverse of the function
1023 ""Delta_Days()"":
1024
1025 Add_Delta_Days(@date1, Delta_Days(@date1, @date2))
1026
1027 yields "@date2" again, whereas
1028
1029 Add_Delta_Days(@date2, -Delta_Days(@date1, @date2))
1030
1031 yields "@date1", and
1032
1033 Delta_Days(@date1, Add_Delta_Days(@date1, $delta))
1034
1035 yields "$delta" again.
1036
1037 • "($year,$month,$day, $hour,$min,$sec) =
1038 Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);"
1039
1040 This function serves to add a days, hours, minutes and seconds offset
1041 to a given date and time, in order to answer questions like "today
1042 and now plus 7 days but minus 5 hours and then plus 30 minutes, what
1043 date and time gives that?":
1044
1045 ($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), +7,-5,+30,0);
1046
1047 • "($year,$month,$day) = Add_Delta_YM($year,$month,$day, $Dy,$Dm);"
1048
1049 This function can be used to add a year and/or month offset to a
1050 given date.
1051
1052 In contrast to the function described immediately below
1053 (""Add_Delta_YMD()""), this function does no "wrapping" into the next
1054 month if the day happens to lie outside the valid range for the
1055 resulting year and month (after adding the year and month offsets).
1056 Instead, it simply truncates the day to the last possible day of the
1057 resulting month.
1058
1059 Examples:
1060
1061 Adding an offset of 0 years, 1 month to the date [1999,1,31] would
1062 result in the (invalid) date [1999,2,31]. The function replaces this
1063 result by the (valid) date [1999,2,28].
1064
1065 Adding an offset of 1 year, 1 month to the same date [1999,1,31] as
1066 above would result in the (still invalid) date [2000,2,31]. The
1067 function replaces this result by the valid date [2000,2,29] (because
1068 2000 is a leap year).
1069
1070 Note that the year and month offsets can be negative, and that they
1071 can have different signs.
1072
1073 If you want to additionally add a days offset, use the function
1074 ""Add_Delta_Days()"" before or after calling ""Add_Delta_YM()"":
1075
1076 @date2 = Add_Delta_Days( Add_Delta_YM(@date1, $Dy,$Dm), $Dd );
1077 @date2 = Add_Delta_YM( Add_Delta_Days(@date1, $Dd), $Dy,$Dm );
1078
1079 Note that your result may depend on the order in which you call these
1080 two functions!
1081
1082 Consider the date [1999,2,28] and the offsets 0 years, 1 month and 1
1083 day:
1084
1085 [1999,2,28] plus one month is [1999,3,28], plus one day is
1086 [1999,3,29]. [1999,2,28] plus one day is [1999,3,1], plus one month
1087 is [1999,4,1].
1088
1089 (Which is also the reason why the ""Add_Delta_YM()"" function does
1090 not allow to add a days offset, because this would actually require
1091 TWO functions: One for adding the days offset BEFORE and one for
1092 adding it AFTER applying the year/month offsets.)
1093
1094 An error occurs if the initial date is not valid.
1095
1096 Note that ""Add_Delta_YM( Add_Delta_YM(@date, $Dy,$Dm), -$Dy,-$Dm
1097 );"" will not, in general, return the original date "@date" (consider
1098 the examples given above!).
1099
1100 • "($year,$month,$day) = Add_Delta_YMD($year,$month,$day,
1101 $Dy,$Dm,$Dd);"
1102
1103 This function serves to add a years, months and days offset to a
1104 given date.
1105
1106 (In order to add a weeks offset, simply multiply the weeks offset
1107 with "7" and add this number to your days offset.)
1108
1109 Note that the three offsets for years, months and days are applied
1110 independently from each other. This also allows them to have
1111 different signs.
1112
1113 The years and months offsets are applied first, and the days offset
1114 is applied last.
1115
1116 If the resulting date happens to fall on a day after the end of the
1117 resulting month, like the 32nd of April or the 30th of February, then
1118 the date is simply counted forward into the next month (possibly also
1119 into the next year) by the number of excessive days (e.g., the 32nd
1120 of April will become the 2nd of May).
1121
1122 BEWARE that this behaviour differs from that of previous versions of
1123 this module! In previous versions, the day was simply truncated to
1124 the maximum number of days in the resulting month.
1125
1126 If you want the previous behaviour, use the new function
1127 ""Add_Delta_YM()"" (described immediately above) plus the function
1128 ""Add_Delta_Days()"" instead.
1129
1130 BEWARE also that because a year and a month offset is not equivalent
1131 to a fixed number of days, the transformation performed by this
1132 function is NOT ALWAYS REVERSIBLE!
1133
1134 This is in contrast to the functions ""Add_Delta_Days()"" and
1135 ""Add_Delta_DHMS()"", which are fully and truly reversible (with the
1136 help of the functions ""Delta_Days()"" and ""Delta_DHMS()"", for
1137 instance).
1138
1139 Note that for this same reason,
1140
1141 @date = Add_Delta_YMD(
1142 Add_Delta_YMD(@date, $Dy,$Dm,$Dd), -$Dy,-$Dm,-$Dd);
1143
1144 will in general NOT return the initial date "@date", even though
1145
1146 @date2 = Add_Delta_YMD( @date1, Delta_YMD(@date1, @date2) );
1147
1148 will always return the second date "@date2", and
1149
1150 @date1 = Add_Delta_YMD( @date2, map(-$_, Delta_YMD(@date1, @date2)) );
1151
1152 which is the same as
1153
1154 @date1 = Add_Delta_YMD( @date2, Delta_YMD(@date2, @date1) );
1155
1156 will always return the first date "@date1".
1157
1158 Examples:
1159
1160 [1996,1,31] + ( 6, 1,-2) = [2002,3,1]
1161 [2002,3, 1] + (-6,-1, 2) = [1996,2,3] # EXPECTED: [1996,1,31]
1162
1163 (6,2,-30) == Delta_YMD(1996,1,31, 2002,3,1);
1164
1165 [1996,1,31] + ( 6, 2,-30) = [2002,3, 1]
1166 [2002,3, 1] + (-6,-2, 30) = [1996,1,31] # OK
1167
1168 (6,1,-2) == Delta_YMD(1996,2,3, 2002,3,1);
1169
1170 [1996,2,3] + ( 6, 1,-2) = [2002,3,1]
1171 [2002,3,1] + (-6,-1, 2) = [1996,2,3] # OK
1172
1173 Note that this is NOT a program bug but NECESSARILY so, because of
1174 the variable lengths of years and months, and hence because of the
1175 ambiguity of the difference between two dates in terms of years,
1176 months and days, i.e., the fact that the difference between two dates
1177 can be expressed in more than one way:
1178
1179 [1996,1,31] + (6,1, -2) = [2002,3,1]
1180 [1996,1,31] + (6,2,-30) = [2002,3,1]
1181
1182 • "($year,$month,$day, $hour,$min,$sec) =
1183 Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec, $D_y,$D_m,$D_d,
1184 $Dh,$Dm,$Ds);"
1185
1186 Same as the function above, except that a time offset may be given in
1187 addition to the year, month and day offset.
1188
1189 • "($year,$month,$day) = Add_N_Delta_YMD($year,$month,$day,
1190 $Dy,$Dm,$Dd);"
1191
1192 This function is actually a shortcut for applying the function
1193 "Add_Delta_YM()" first, followed by the function "Add_Delta_Days()",
1194 i.e., this function does exactly the same as
1195
1196 ($year,$month,$day) = Add_Delta_Days( Add_Delta_YM($year,$month,$day,$Dy,$Dm), $Dd );
1197
1198 Beware that, if necessary, the function "Add_Delta_YM()" truncates
1199 the resulting day of the month to the largest allowable value for
1200 that month, i.e., the (invalid) result [2009,2,31] is automatically
1201 transformed into [2009,2,28].
1202
1203 For more details on this truncation, see the description of the
1204 function "Add_Delta_YM()" further above.
1205
1206 This function is meant to be complementary with the function
1207 "N_Delta_YMD()" described further above.
1208
1209 This means that it is guaranteed that the result returned by
1210
1211 Add_N_Delta_YMD( @date1, N_Delta_YMD(@date1, @date2) );
1212
1213 is always identical with the given date "@date2".
1214
1215 Note however that unlike with function "Add_Delta_YMD()", the reverse
1216 is not true here, i.e.,
1217
1218 ($Dy,$Dm,$Dd) = N_Delta_YMD(@date1,@date2);
1219 @date = Add_N_Delta_YMD(@date2, -$Dy,-$Dm,-$Dd);
1220
1221 will NOT always return the initial date "@date1".
1222
1223 Example:
1224
1225 (0,11,3) == N_Delta_YMD(2008,2,29, 2009,2,1);
1226
1227 [2008,2,29] + (0, 11, 3) = [2009,2, 1]
1228 [2009,2, 1] + (0,-11,-3) = [2008,2,27] # EXPECTED: [2008,2,29]
1229
1230 • "($year,$month,$day, $hour,$min,$sec) =
1231 Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
1232 $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);"
1233
1234 This function essentially does the same as the function
1235 "Add_N_Delta_YMD()" described immediately above, except that also the
1236 difference in hours, minutes and seconds is taken into account.
1237
1238 • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1239 System_Clock([$gmt]);"
1240
1241 If your operating system supports the corresponding system calls
1242 (""time()"" and ""localtime()"" or ""gmtime()""), this function will
1243 return the information provided by your system clock, i.e., the
1244 current date and time, the number of the day of year, the number of
1245 the day of week and a flag signaling whether daylight savings time is
1246 currently in effect or not.
1247
1248 The ranges of values returned (and their meanings) are as follows:
1249
1250 $year : 1970..2038 (or more) [Unix etc.]
1251 $year : 1904..2040 [MacOS Classic]
1252
1253 $month : 1..12
1254 $day : 1..31
1255 $hour : 0..23
1256 $min : 0..59
1257 $sec : 0..59 (0..61 on some systems)
1258 $doy : 1..366
1259 $dow : 1..7
1260 $dst : -1..1
1261
1262 "$doy" is the day of year, sometimes also referred to as the "julian
1263 date", which starts at "1" and goes up to the number of days in that
1264 year.
1265
1266 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1267 so on until "7" for Sunday.
1268
1269 The daylight savings time flag ("$dst") will be ""-1"" if this
1270 information is not available on your system, "0" for no daylight
1271 savings time (i.e., winter time) and "1" when daylight savings time
1272 is in effect.
1273
1274 If your operating system does not provide the necessary system calls,
1275 calling this function will result in a fatal "not available on this
1276 system" error message.
1277
1278 If you want to handle this exception yourself, use ""eval"" as
1279 follows:
1280
1281 eval { ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1282 System_Clock(); };
1283
1284 if ($@)
1285 {
1286 # Handle missing system clock
1287 # (For instance, ask user to enter this information manually)
1288 }
1289
1290 Note that curlies ("{" and "}") are used here to delimit the
1291 statement to be "eval"ed (which is the way to catch exceptions in
1292 Perl), and not quotes (which is a way to evaluate Perl expressions at
1293 runtime).
1294
1295 If the optional (boolean) input parameter "$gmt" is given, a "true"
1296 value ("1") will cause ""gmtime()"" to be used instead of
1297 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1298 or UTC) instead of local time.
1299
1300 • "($year,$month,$day) = Today([$gmt]);"
1301
1302 This function returns a subset of the values returned by the function
1303 ""System_Clock()"" (see above for details), namely the current year,
1304 month and day.
1305
1306 A fatal "not available on this system" error message will appear if
1307 the corresponding system calls are not supported by your current
1308 operating system.
1309
1310 If the optional (boolean) input parameter "$gmt" is given, a "true"
1311 value ("1") will cause ""gmtime()"" to be used instead of
1312 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1313 or UTC) instead of local time.
1314
1315 • "($hour,$min,$sec) = Now([$gmt]);"
1316
1317 This function returns a subset of the values returned by the function
1318 ""System_Clock()"" (see above for details), namely the current time
1319 (hours, minutes and full seconds).
1320
1321 A fatal "not available on this system" error message will appear if
1322 the corresponding system calls are not supported by your current
1323 operating system.
1324
1325 If the optional (boolean) input parameter "$gmt" is given, a "true"
1326 value ("1") will cause ""gmtime()"" to be used instead of
1327 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1328 or UTC) instead of local time.
1329
1330 • "($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);"
1331
1332 This function returns a subset of the values returned by the function
1333 ""System_Clock()"" (see above for details), namely the current date
1334 (year, month, day) and time (hours, minutes and full seconds).
1335
1336 A fatal "not available on this system" error message will appear if
1337 the corresponding system calls are not supported by your current
1338 operating system.
1339
1340 If the optional (boolean) input parameter "$gmt" is given, a "true"
1341 value ("1") will cause ""gmtime()"" to be used instead of
1342 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1343 or UTC) instead of local time.
1344
1345 • "$year = This_Year([$gmt]);"
1346
1347 This function returns the current year, according to local time.
1348
1349 A fatal "not available on this system" error message will appear if
1350 the corresponding system calls are not supported by your current
1351 operating system.
1352
1353 If the optional (boolean) input parameter "$gmt" is given, a "true"
1354 value ("1") will cause ""gmtime()"" to be used instead of
1355 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
1356 or UTC) instead of local time. However, this will only make a
1357 difference within a few hours around New Year (unless you are on a
1358 Pacific island, where this can be almost 24 hours).
1359
1360 • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1361 Gmtime([time]);"
1362
1363 This is Date::Calc's equivalent of Perl's built-in "gmtime()"
1364 function. See also "gmtime" in perlfunc(1).
1365
1366 With the optional argument "time" (i.e., seconds since the epoch),
1367 this function will return the corresponding values for that
1368 particular time (instead of the current time when this parameter is
1369 omitted).
1370
1371 The ranges of values returned (and their meanings) are as follows:
1372
1373 $year : 1970..2038 (or more) [Unix etc.]
1374 $year : 1904..2040 [MacOS Classic]
1375
1376 $month : 1..12
1377 $day : 1..31
1378 $hour : 0..23
1379 $min : 0..59
1380 $sec : 0..59
1381 $doy : 1..366
1382 $dow : 1..7
1383 $dst : -1..1
1384
1385 "$doy" is the day of year, sometimes also referred to as the "julian
1386 date", which starts at "1" and goes up to the number of days in that
1387 year.
1388
1389 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1390 so on until "7" for Sunday.
1391
1392 The daylight savings time flag ("$dst") will be ""-1"" if this
1393 information is not available on your system, "0" for no daylight
1394 savings time (i.e., winter time) and "1" when daylight savings time
1395 is in effect.
1396
1397 A fatal "time out of range" error will occur if the given time value
1398 is out of range "[0..(~0>>1)]".
1399
1400 If the time value is omitted, the "time()" function is called
1401 instead, internally.
1402
1403 • "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
1404 Localtime([time]);"
1405
1406 This is Date::Calc's equivalent of Perl's built-in "localtime()"
1407 function. See also "localtime" in perlfunc(1).
1408
1409 The ranges of values returned (and their meanings) are as follows:
1410
1411 $year : 1970..2038 (or more) [Unix etc.]
1412 $year : 1904..2040 [MacOS Classic]
1413
1414 $month : 1..12
1415 $day : 1..31
1416 $hour : 0..23
1417 $min : 0..59
1418 $sec : 0..59
1419 $doy : 1..366
1420 $dow : 1..7
1421 $dst : -1..1
1422
1423 "$doy" is the day of year, sometimes also referred to as the "julian
1424 date", which starts at "1" and goes up to the number of days in that
1425 year.
1426
1427 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
1428 so on until "7" for Sunday.
1429
1430 The daylight savings time flag ("$dst") will be ""-1"" if this
1431 information is not available on your system, "0" for no daylight
1432 savings time (i.e., winter time) and "1" when daylight savings time
1433 is in effect.
1434
1435 A fatal "time out of range" error will occur if the given time value
1436 is out of range "[0..(~0>>1)]".
1437
1438 If the time value is omitted, the "time()" function is called
1439 instead, internally.
1440
1441 • "$time = Mktime($year,$month,$day, $hour,$min,$sec);"
1442
1443 This function converts a date into a time value, i.e., into the
1444 number of seconds since whatever moment in time your system considers
1445 to be the "epoch". On Unix and most other systems this is the number
1446 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1447 this is the number of seconds since January 1st 1904 at midnight
1448 (local time).
1449
1450 The function is similar to the "POSIX::mktime()" function (see
1451 "mktime" in POSIX(1) for more details), but in contrast to the
1452 latter, it expects dates in the usual ranges used throughout this
1453 module: The year 2001 stays year 2001, and months are numbered from 1
1454 to 12.
1455
1456 A fatal "date out of range" error will occur if the given date cannot
1457 be expressed in terms of seconds since the epoch (this happens for
1458 instance when the date lies before the epoch, or if it is later than
1459 19-Jan-2038Â 03:14:07Â GMT on 32Â bit Unix systems, or later than
1460 06-Feb-2040Â 06:28:15 (local time) on a Macintosh with MacOS
1461 Classic).
1462
1463 Just like the "POSIX::mktime()" function, this function uses the
1464 "mktime()" system call, internally.
1465
1466 This means that the given date and time is considered to be in local
1467 time, and that the value returned by this function will depend on
1468 your machine's local settings such as the time zone, whether daylight
1469 savings time is (or was, at the time) in effect, and the system clock
1470 itself.
1471
1472 BEWARE that "mktime()" does not always return the same time value as
1473 fed into "localtime()", when you feed the output of "localtime()"
1474 back into "mktime()", on some systems!
1475
1476 I.e., ""Mktime((Localtime($time))[0..5])"" will not always return the
1477 same value as given in "$time"!
1478
1479 • "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);"
1480
1481 This function returns the difference between ""localtime(time)"" and
1482 ""gmtime(time)"", which is the timezone offset in effect for the
1483 current location and the given ""time"".
1484
1485 This offset is positive if you are located to the east of Greenwich,
1486 and is usually negative (except during daylight savings time, in some
1487 locations) if you are located to the west of Greenwich.
1488
1489 Note that this offset is influenced by all of the relevant system
1490 settings and parameters on your machine; such as locales, environment
1491 variables (e.g. ""TZ"") and the system clock itself. See the relevant
1492 documentation on your system for more details.
1493
1494 If the ""time"" is omitted, the ""time()"" function will be called
1495 automatically, internally (similar to the built-in functions
1496 ""localtime()"" and ""gmtime()"" in Perl).
1497
1498 A fatal "time out of range" error will occur if the given time value
1499 is out of range "[0..(~0>>1)]".
1500
1501 The last item of the returned list is a flag which indicates whether
1502 daylight savings time is currently in effect. This flag is negative
1503 (-1) if this information is not available on your system. It is zero
1504 (0) when daylight savings time is off, and positive (+1) when
1505 daylight savings time is on.
1506
1507 Thus you can check very quickly whether daylight savings time is
1508 currently in effect by evaluating this function in scalar context (in
1509 scalar context, Perl returns the last item of a list):
1510
1511 if (scalar Timezone > 0) { # yes, daylight savings time
1512
1513 However, a slightly more efficient way would be this:
1514
1515 if (scalar System_Clock > 0) { # yes, daylight savings time
1516
1517 • "$time = Date_to_Time($year,$month,$day, $hour,$min,$sec);"
1518
1519 This function is a replacement for the BSD function "timegm()" (which
1520 is not available on all Unix systems), which converts a given date
1521 and time into a time value, i.e., into the number of seconds since
1522 whatever moment in time your system considers to be the "epoch". On
1523 Unix and most other systems this is the number of seconds since
1524 January 1st 1970 at midnight (GMT). On MacOS Classic this is the
1525 number of seconds since January 1st 1904 at midnight (local time).
1526
1527 Under Unix, the date and time are considered to be in UTC ("Universal
1528 Time Coordinated", and so is the resulting time value.
1529
1530 UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1531 UTC has leap seconds (in order to account for small variations in the
1532 rotation of the earth, for instance), whereas GMT does not.
1533
1534 Under MacOS Classic, however, both input and output are considered to
1535 be in local time.
1536
1537 The ranges of year and month follow the same rules as throughout the
1538 rest of this module (and not the contorted rules of its Unix
1539 equivalent), i.e., the year "2001" stays "2001" and the month ranges
1540 from 1 to 12.
1541
1542 A fatal "date out of range" error will occur if the given date cannot
1543 be expressed in terms of seconds since the epoch (this happens for
1544 instance when the date lies before the epoch, or if it is later than
1545 19-Jan-2038Â 03:14:07Â GMT on 32Â bit Unix systems, or later than
1546 06-Feb-2040Â 06:28:15 (local time) on a Macintosh with MacOS
1547 Classic).
1548
1549 This function should be very fast, because it is implemented in a
1550 very straightforward manner and doesn't use any internal system
1551 calls.
1552
1553 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1554 guaranteed to be complementary, i.e., that
1555 ""Date_to_Time(Time_to_Date($time))"" and
1556 ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1557 will always return the initial values.
1558
1559 • "($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);"
1560
1561 This function is an alternative to the POSIX "gmtime()" function (and
1562 its built-in Perl equivalent), which converts a given time value into
1563 the corresponding date and time. The given time value must be the
1564 number of seconds since whatever moment in time your system considers
1565 to be the "epoch". On Unix and most other systems this is the number
1566 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
1567 this is the number of seconds since January 1st 1904 at midnight
1568 (local time).
1569
1570 Under Unix, the given time value is considered to be in UTC
1571 ("Universal Time Coordinated", and so is the resulting date and time.
1572
1573 UTC is almost the same as GMT (or "Greenwich Mean Time"), except that
1574 UTC has leap seconds (in order to account for small variations in the
1575 rotation of the earth, for instance), whereas GMT does not.
1576
1577 Under MacOS Classic, however, both input and output are considered to
1578 be in local time.
1579
1580 If the input value ""time"" is omitted, the ""time()"" function will
1581 be called automatically, internally (similar to the built-in
1582 functions ""localtime()"" and ""gmtime()"" in Perl).
1583
1584 A fatal "time out of range" error will occur if the given time value
1585 is negative.
1586
1587 This function should be very fast, because it is implemented in a
1588 very straightforward manner and doesn't use any internal system calls
1589 (except for "time()", if the input value is omitted).
1590
1591 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
1592 guaranteed to be complementary, i.e., that
1593 ""Date_to_Time(Time_to_Date($time))"" and
1594 ""Time_to_Date(Date_to_Time($year,$month,$day, $hour,$min,$sec))""
1595 will always return the initial values.
1596
1597 • "($year,$month,$day) = Easter_Sunday($year);"
1598
1599 This function calculates the date of Easter Sunday for all years in
1600 the range from 1583 to 2299 (all other year numbers will result in a
1601 fatal "year out of range" error message) using the method known as
1602 the "Gaussian Rule".
1603
1604 Some related christian feast days which depend on the date of Easter
1605 Sunday:
1606
1607 Carnival Monday / Rosenmontag / Veille du Mardi Gras = -48 days
1608 Mardi Gras / Karnevalsdienstag / Mardi Gras = -47 days
1609 Ash Wednesday / Aschermittwoch / Mercredi des Cendres = -46 days
1610 Palm Sunday / Palmsonntag / Dimanche des Rameaux = -7 days
1611 Easter Friday / Karfreitag / Vendredi Saint = -2 days
1612 Easter Saturday / Ostersamstag / Samedi de Paques = -1 day
1613 Easter Monday / Ostermontag / Lundi de Paques = +1 day
1614 Ascension of Christ / Christi Himmelfahrt / Ascension = +39 days
1615 Whitsunday / Pfingstsonntag / Dimanche de Pentecote = +49 days
1616 Whitmonday / Pfingstmontag / Lundi de Pentecote = +50 days
1617 Feast of Corpus Christi / Fronleichnam / Fete-Dieu = +60 days
1618
1619 Use the offsets shown above to calculate the date of the
1620 corresponding feast day as follows:
1621
1622 ($year,$month,$day) = Add_Delta_Days(Easter_Sunday($year), $offset));
1623
1624 • "if ($month = Decode_Month($string[,$lang]))"
1625
1626 This function takes a string as its argument, which should contain
1627 the name of a month in the given or currently selected language (see
1628 further below for details about the multi-language support of this
1629 package), or any uniquely identifying abbreviation of a month's name
1630 (i.e., the first few letters), and returns the corresponding number
1631 (1..12) upon a successful match, or "0" otherwise (therefore, the
1632 return value can also be used as the conditional expression in an
1633 "if" statement).
1634
1635 Note that the input string may not contain any other characters which
1636 do not pertain to the month's name, especially no leading or trailing
1637 whitespace.
1638
1639 Note also that matching is performed in a case-insensitive manner
1640 (this may depend on the "locale" setting on your current system,
1641 though!)
1642
1643 With "1" ("English") as the given language, the following examples
1644 will all return the value "9":
1645
1646 $month = Decode_Month("s",1);
1647 $month = Decode_Month("Sep",1);
1648 $month = Decode_Month("septemb",1);
1649 $month = Decode_Month("September",1);
1650
1651 • "if ($dow = Decode_Day_of_Week($string[,$lang]))"
1652
1653 This function takes a string as its argument, which should contain
1654 the name of a day of week in the given or currently selected language
1655 (see further below for details about the multi-language support of
1656 this package), or any uniquely identifying abbreviation of the name
1657 of a day of week (i.e., the first few letters), and returns the
1658 corresponding number (1..7) upon a successful match, or "0" otherwise
1659 (therefore, the return value can also be used as the conditional
1660 expression in an "if" statement).
1661
1662 Note that the input string may not contain any other characters which
1663 do not pertain to the name of the day of week, especially no leading
1664 or trailing whitespace.
1665
1666 Note also that matching is performed in a case-insensitive manner
1667 (this may depend on the "locale" setting on your current system,
1668 though!)
1669
1670 With "1" ("English") as the given language, the following examples
1671 will all return the value "3":
1672
1673 $dow = Decode_Day_of_Week("w",1);
1674 $dow = Decode_Day_of_Week("Wed",1);
1675 $dow = Decode_Day_of_Week("wednes",1);
1676 $dow = Decode_Day_of_Week("Wednesday",1);
1677
1678 • "if ($lang = Decode_Language($string))"
1679
1680 This function takes a string as its argument, which should contain
1681 the name of one of the languages supported by this package (IN THIS
1682 VERY LANGUAGE ITSELF), or any uniquely identifying abbreviation of
1683 the name of a language (i.e., the first few letters), and returns its
1684 corresponding internal number (1..14 in the original distribution)
1685 upon a successful match, or "0" otherwise (therefore, the return
1686 value can also be used as the conditional expression in an "if"
1687 statement).
1688
1689 Note that the input string may not contain any other characters which
1690 do not pertain to the name of a language, especially no leading or
1691 trailing whitespace.
1692
1693 Note also that matching is performed in a case-insensitive manner
1694 (this may depend on the "locale" setting on your current system,
1695 though!)
1696
1697 The original distribution supports the following fourteen languages:
1698
1699 English ==> 1 (default)
1700 Français (French) ==> 2
1701 Deutsch (German) ==> 3
1702 Español (Spanish) ==> 4
1703 Português (Portuguese) ==> 5
1704 Nederlands (Dutch) ==> 6
1705 Italiano (Italian) ==> 7
1706 Norsk (Norwegian) ==> 8
1707 Svenska (Swedish) ==> 9
1708 Dansk (Danish) ==> 10
1709 suomi (Finnish) ==> 11
1710 Magyar (Hungarian) ==> 12
1711 polski (Polish) ==> 13
1712 Romaneste (Romanian) ==> 14
1713
1714 See the section "How to install additional languages" in the file
1715 "INSTALL.txt" in this distribution for how to add more languages to
1716 this package.
1717
1718 In the original distribution (no other languages installed), the
1719 following examples will all return the value "3":
1720
1721 $lang = Decode_Language("d");
1722 $lang = Decode_Language("de");
1723 $lang = Decode_Language("Deutsch");
1724
1725 Note that you may not be able to enter the special international
1726 characters in some of the languages' names over the keyboard directly
1727 on some systems.
1728
1729 This should never be a problem, though; just enter an abbreviation of
1730 the name of the language consisting of the first few letters up to
1731 the character before the first special international character.
1732
1733 • "if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))"
1734
1735 This function scans a given string and tries to parse any date which
1736 might be embedded in it.
1737
1738 The function returns an empty list if it can't successfully extract a
1739 valid date from its input string, or else it returns the date found.
1740
1741 The function accepts almost any format, as long as the date is given
1742 in the european order (hence its name) day-month-year.
1743
1744 Thereby, zero or more NON-NUMERIC characters may PRECEDE the day and
1745 FOLLOW the year.
1746
1747 Moreover, zero or more NON-ALPHANUMERIC characters are permitted
1748 BETWEEN these three items (i.e., between day and month and between
1749 month and year).
1750
1751 The month may be given either numerically (i.e., a number from "1" to
1752 "12"), or alphanumerically, i.e., as the name of the month in the
1753 given or currently selected language, or any uniquely identifying
1754 abbreviation thereof.
1755
1756 (See further below for details about the multi-language support of
1757 this package!)
1758
1759 If the year is given as one or two digits only (i.e., if the year is
1760 less than 100), it is mapped to a "window" of +/- 50 years around the
1761 current year, as described by the "Moving_Window()" function (see
1762 further below).
1763
1764 If the day, month and year are all given numerically but WITHOUT any
1765 delimiting characters between them, this string of digits will be
1766 mapped to the day, month and year as follows:
1767
1768 Length: Mapping:
1769 3 dmy
1770 4 dmyy
1771 5 dmmyy
1772 6 ddmmyy
1773 7 dmmyyyy
1774 8 ddmmyyyy
1775
1776 (Where "d" stands for "day", "m" stands for "month" and "y" stands
1777 for "year".)
1778
1779 All other strings consisting purely of digits (without any
1780 intervening delimiters) are rejected, i.e., not recognized.
1781
1782 Examples:
1783
1784 "3.1.64"
1785 "3 1 64"
1786 "03.01.64"
1787 "03/01/64"
1788 "3. Jan 1964"
1789 "Birthday: 3. Jan '64 in Backnang/Germany"
1790 "03-Jan-64"
1791 "3.Jan1964"
1792 "3Jan64"
1793 "030164"
1794 "3ja64"
1795 "3164"
1796
1797 Experiment! (See the corresponding example applications in the
1798 "examples" subdirectory of this distribution in order to do so.)
1799
1800 • "if (($year,$month,$day) = Decode_Date_US($string[,$lang]))"
1801
1802 This function scans a given string and tries to parse any date which
1803 might be embedded in it.
1804
1805 The function returns an empty list if it can't successfully extract a
1806 valid date from its input string, or else it returns the date found.
1807
1808 The function accepts almost any format, as long as the date is given
1809 in the U.S. american order (hence its name) month-day-year.
1810
1811 Thereby, zero or more NON-ALPHANUMERIC characters may PRECEDE and
1812 FOLLOW the month (i.e., precede the month and separate it from the
1813 day which follows behind).
1814
1815 Moreover, zero or more NON-NUMERIC characters are permitted BETWEEN
1816 the day and the year, as well as AFTER the year.
1817
1818 The month may be given either numerically (i.e., a number from "1" to
1819 "12"), or alphanumerically, i.e., as the name of the month in the
1820 given or currently selected language, or any uniquely identifying
1821 abbreviation thereof.
1822
1823 (See further below for details about the multi-language support of
1824 this package!)
1825
1826 If the year is given as one or two digits only (i.e., if the year is
1827 less than 100), it is mapped to a "window" of +/- 50 years around the
1828 current year, as described by the "Moving_Window()" function (see
1829 further below).
1830
1831 If the month, day and year are all given numerically but WITHOUT any
1832 delimiting characters between them, this string of digits will be
1833 mapped to the month, day and year as follows:
1834
1835 Length: Mapping:
1836 3 mdy
1837 4 mdyy
1838 5 mddyy
1839 6 mmddyy
1840 7 mddyyyy
1841 8 mmddyyyy
1842
1843 (Where "m" stands for "month", "d" stands for "day" and "y" stands
1844 for "year".)
1845
1846 All other strings consisting purely of digits (without any
1847 intervening delimiters) are rejected, i.e., not recognized.
1848
1849 If only the day and the year form a contiguous string of digits, they
1850 will be mapped as follows:
1851
1852 Length: Mapping:
1853 2 dy
1854 3 dyy
1855 4 ddyy
1856 5 dyyyy
1857 6 ddyyyy
1858
1859 (Where "d" stands for "day" and "y" stands for "year".)
1860
1861 Examples:
1862
1863 "1 3 64"
1864 "01/03/64"
1865 "Jan 3 '64"
1866 "Jan 3 1964"
1867 "===> January 3rd 1964 (birthday)"
1868 "Jan31964"
1869 "Jan364"
1870 "ja364"
1871 "1364"
1872
1873 Experiment! (See the corresponding example applications in the
1874 "examples" subdirectory of this distribution in order to do so.)
1875
1876 • "$year = Fixed_Window($yy);"
1877
1878 This function applies a "fixed window" strategy to two-digit year
1879 numbers in order to convert them into four-digit year numbers.
1880
1881 All other year numbers are passed through unchanged, except for
1882 negative year numbers, which cause the function to return zero ("0")
1883 instead.
1884
1885 Two-digit year numbers ""yy"" below 70 are converted to ""20yy"",
1886 whereas year numbers equal to or greater than 70 (but less than 100)
1887 are converted to ""19yy"".
1888
1889 In the original distribution of this package, the base century is set
1890 to "1900" and the base year to "70" (which is a standard on UNIX
1891 systems), but these constants (also called the "epoch") can actually
1892 be chosen at will (in the files "DateCalc.c" and "DateCalc.h") at
1893 compile time of this module.
1894
1895 • "$year = Moving_Window($yy);"
1896
1897 This function applies a "moving window" strategy to two-digit year
1898 numbers in order to convert them into four-digit year numbers,
1899 provided the necessary system calls (system clock) are available.
1900 Otherwise the function falls back to the "fixed window" strategy
1901 described in the function above.
1902
1903 All other year numbers are passed through unchanged, except for
1904 negative year numbers, which cause the function to return zero ("0")
1905 instead.
1906
1907 Two-digit year numbers are mapped according to a "window" of 50 years
1908 in both directions (past and future) around the current year.
1909
1910 That is, two-digit year numbers are first mapped to the same century
1911 as the current year. If the resulting year is smaller than the
1912 current year minus 50, then one more century is added to the result.
1913 If the resulting year is equal to or greater than the current year
1914 plus 50, then a century is subtracted from the result.
1915
1916 • "$date = Compress($year,$month,$day);"
1917
1918 WARNING: This function is legacy code, its use is deprecated!
1919
1920 This function encodes a date in 16 bits, which is the value being
1921 returned.
1922
1923 The encoding scheme is as follows:
1924
1925 Bit number: FEDCBA9 8765 43210
1926 Contents: yyyyyyy mmmm ddddd
1927
1928 (Where the "yyyyyyy" contain the number of the year, "mmmm" the
1929 number of the month and "ddddd" the number of the day.)
1930
1931 The function returns "0" if the given input values do not represent a
1932 valid date. Therefore, the return value of this function can also be
1933 used as the conditional expression in an "if" statement, in order to
1934 check whether the given input values constitute a valid date).
1935
1936 Through this special encoding scheme, it is possible to COMPARE
1937 compressed dates for equality and order (less than/greater than)
1938 WITHOUT any previous DECODING!
1939
1940 Note however that contiguous dates do NOT necessarily have contiguous
1941 compressed representations!
1942
1943 I.e., incrementing the compressed representation of a date MAY OR MAY
1944 NOT yield a valid new date!
1945
1946 Note also that this function can only handle dates within one
1947 century.
1948
1949 This century can be chosen at will (at compile time of this module)
1950 by defining a base century and year (also called the "epoch"). In the
1951 original distribution of this package, the base century is set to
1952 "1900" and the base year to "70" (which is standard on UNIX systems).
1953
1954 This allows this function to handle dates from "1970" up to "2069".
1955
1956 If the given year is equal to, say, "95", this package will
1957 automatically assume that you really meant "1995" instead. However,
1958 if you specify a year number which is SMALLER than 70, like "64", for
1959 instance, this package will assume that you really meant "2064".
1960
1961 You are not confined to two-digit (abbreviated) year numbers, though.
1962
1963 The function also accepts "full-length" year numbers, provided that
1964 they lie in the supported range (i.e., from "1970" to "2069", in the
1965 original configuration of this package).
1966
1967 Note that this function is maintained mainly for backward
1968 compatibility, and that its use is not recommended.
1969
1970 • "if (($century,$year,$month,$day) = Uncompress($date))"
1971
1972 WARNING: This function is legacy code, its use is deprecated!
1973
1974 This function decodes dates that were encoded previously using the
1975 function ""Compress()"".
1976
1977 It returns the century, year, month and day of the date encoded in
1978 "$date" if "$date" represents a valid date, or an empty list
1979 otherwise.
1980
1981 The year returned in "$year" is actually a two-digit year number
1982 (i.e., the year number taken modulo 100), and only the expression
1983 ""$century + $year"" yields the "full-length" year number (for
1984 example, "1900 + 95 = 1995").
1985
1986 Note that this function is maintained mainly for backward
1987 compatibility, and that its use is not recommended.
1988
1989 • "if (check_compressed($date))"
1990
1991 WARNING: This function is legacy code, its use is deprecated!
1992
1993 This function returns "true" ("1") if the given input value
1994 constitutes a valid compressed date, and "false" ("0") otherwise.
1995
1996 Note that this function is maintained mainly for backward
1997 compatibility, and that its use is not recommended.
1998
1999 • "$string = Compressed_to_Text($date[,$lang]);"
2000
2001 WARNING: This function is legacy code, its use is deprecated!
2002
2003 This function returns a string of fixed length (always 9 characters
2004 long) containing a textual representation of the compressed date
2005 encoded in "$date".
2006
2007 This string has the form "dd-Mmm-yy", where "dd" is the two-digit
2008 number of the day, "Mmm" are the first three letters of the name of
2009 the month in the given or currently selected language (see further
2010 below for details about the multi-language support of this package),
2011 and "yy" is the two-digit year number (i.e., the year number taken
2012 modulo 100).
2013
2014 If "$date" does not represent a valid date, the string "??-???-??" is
2015 returned instead.
2016
2017 Note that this function is maintained mainly for backward
2018 compatibility, and that its use is not recommended.
2019
2020 • "$string = Date_to_Text($year,$month,$day[,$lang]);"
2021
2022 This function returns a string containing a textual representation of
2023 the given date of the form "www dd-Mmm-yyyy", where "www" are the
2024 first three letters of the name of the day of week in the given or
2025 currently selected language, or a special abbreviation, if special
2026 abbreviations have been defined for the given or currently selected
2027 language (see further below for details about the multi-language
2028 support of this package), "dd" is the day (one or two digits), "Mmm"
2029 are the first three letters of the name of the month in the given or
2030 currently selected language, and "yyyy" is the number of the year in
2031 full length.
2032
2033 If the given input values do not constitute a valid date, a fatal
2034 "not a valid date" error occurs.
2035
2036 (See the section "RECIPES" near the end of this document for a code
2037 snippet for how to print dates in any format you like.)
2038
2039 • "$string = Date_to_Text_Long($year,$month,$day[,$lang]);"
2040
2041 This function returns a string containing a textual representation of
2042 the given date roughly of the form "Wwwwww, dd Mmmmmm yyyy", where
2043 "Wwwwww" is the name of the day of week in the given or currently
2044 selected language (see further below for details about the multi-
2045 language support of this package), "dd" is the day (one or two
2046 digits), "Mmmmmm" is the name of the month in the given or currently
2047 selected language, and "yyyy" is the number of the year in full
2048 length.
2049
2050 The exact format of the output string depends on the given or
2051 currently selected language. In the original distribution of this
2052 package, these formats are defined as follows:
2053
2054 1 English : "Wwwwww, Mmmmmm ddth yyyy"
2055 2 French : "Wwwwww dd mmmmmm yyyy"
2056 3 German : "Wwwwww, den dd. Mmmmmm yyyy"
2057 4 Spanish : "Wwwwww, dd de mmmmmm de yyyy"
2058 5 Portuguese : "Wwwwww, dia dd de mmmmmm de yyyy"
2059 6 Dutch : "Wwwwww, dd mmmmmm yyyy"
2060 7 Italian : "Wwwwww, dd Mmmmmm yyyy"
2061 8 Norwegian : "wwwwww, dd. mmmmmm yyyy"
2062 9 Swedish : "wwwwww, dd mmmmmm yyyy"
2063 10 Danish : "wwwwww, dd. mmmmmm yyyy"
2064 11 Finnish : "wwwwww, dd. mmmmmmta yyyy"
2065 12 Hungarian : "dd. Mmmmmm yyyy., wwwwww"
2066 13 Polish : "Wwwwww, dd Mmmmmm yyyy"
2067 14 Romanian : "Wwwwww dd Mmmmmm yyyy"
2068
2069 (You can change these formats in the file "DateCalc.c" before
2070 building this module in order to suit your personal preferences.)
2071
2072 If the given input values do not constitute a valid date, a fatal
2073 "not a valid date" error occurs.
2074
2075 In order to capitalize the day of week at the beginning of the string
2076 in Norwegian, use
2077 ""ucfirst(Date_to_Text_Long($year,$month,$day,8));"".
2078
2079 (See the section "RECIPES" near the end of this document for an
2080 example on how to print dates in any format you like.)
2081
2082 • "$string = English_Ordinal($number);"
2083
2084 This function returns a string containing the (english) abbreviation
2085 of the ordinal number for the given (cardinal) number "$number".
2086
2087 I.e.,
2088
2089 0 => '0th' 10 => '10th' 20 => '20th'
2090 1 => '1st' 11 => '11th' 21 => '21st'
2091 2 => '2nd' 12 => '12th' 22 => '22nd'
2092 3 => '3rd' 13 => '13th' 23 => '23rd'
2093 4 => '4th' 14 => '14th' 24 => '24th'
2094 5 => '5th' 15 => '15th' 25 => '25th'
2095 6 => '6th' 16 => '16th' 26 => '26th'
2096 7 => '7th' 17 => '17th' 27 => '27th'
2097 8 => '8th' 18 => '18th' 28 => '28th'
2098 9 => '9th' 19 => '19th' 29 => '29th'
2099
2100 etc.
2101
2102 • "$string = Calendar($year,$month[,$orthodox[,$lang]]);"
2103
2104 This function returns a calendar of the given month in the given year
2105 (somewhat similar to the UNIX ""cal"" command), in the given or
2106 currently selected language (see further below for details about the
2107 multi-language support of this package).
2108
2109 Example:
2110
2111 print Calendar(1998,5);
2112
2113 This will print:
2114
2115 May 1998
2116 Mon Tue Wed Thu Fri Sat Sun
2117 1 2 3
2118 4 5 6 7 8 9 10
2119 11 12 13 14 15 16 17
2120 18 19 20 21 22 23 24
2121 25 26 27 28 29 30 31
2122
2123 If the optional boolean parameter "$orthodox" is given and true, the
2124 calendar starts on Sunday instead of Monday.
2125
2126 • "$string = Month_to_Text($month[,$lang]);"
2127
2128 This function returns the name of the given month in the given or
2129 currently selected language (see further below for details about the
2130 multi-language support of this package).
2131
2132 If the given month lies outside of the valid range from "1" to "12",
2133 a fatal "month out of range" error will occur.
2134
2135 • "$string = Day_of_Week_to_Text($dow[,$lang]);"
2136
2137 This function returns the name of the given day of week in the given
2138 or currently selected language (see further below for details about
2139 the multi-language support of this package).
2140
2141 If the given day of week lies outside of the valid range from "1" to
2142 "7", a fatal "day of week out of range" error will occur.
2143
2144 • "$string = Day_of_Week_Abbreviation($dow[,$lang]);"
2145
2146 This function returns the special abbreviation of the name of the
2147 given day of week, IF such special abbreviations have been defined
2148 for the given or currently selected language (see further below for
2149 details about the multi-language support of this package).
2150
2151 (In the original distribution of this package, this was only true for
2152 Portuguese. Starting with version 5.1, abbreviations for Polish have
2153 also been introduced. Starting with version 5.7, the abbreviations
2154 for Portuguese have been disabled. So Polish is currently the only
2155 language to define such special abbreviations.)
2156
2157 If not, the first three letters of the name of the day of week in the
2158 given or currently selected language are returned instead.
2159
2160 If the given day of week lies outside of the valid range from "1" to
2161 "7", a fatal "day of week out of range" error will occur.
2162
2163 Currently, this table of special abbreviations is only used by the
2164 functions ""Date_to_Text()"" and ""Calendar()"", internally.
2165
2166 • "$string = Language_to_Text($lang);"
2167
2168 This function returns the name of any language supported by this
2169 package when the internal number representing that language is given
2170 as input.
2171
2172 The original distribution supports the following fourteen languages:
2173
2174 1 ==> English (default)
2175 2 ==> Français (French)
2176 3 ==> Deutsch (German)
2177 4 ==> Español (Spanish)
2178 5 ==> Português (Portuguese)
2179 6 ==> Nederlands (Dutch)
2180 7 ==> Italiano (Italian)
2181 8 ==> Norsk (Norwegian)
2182 9 ==> Svenska (Swedish)
2183 10 ==> Dansk (Danish)
2184 11 ==> suomi (Finnish)
2185 12 ==> Magyar (Hungarian)
2186 13 ==> polski (Polish)
2187 14 ==> Romaneste (Romanian)
2188
2189 See the section "How to install additional languages" in the file
2190 "INSTALL.txt" in this distribution for how to add more languages to
2191 this package.
2192
2193 See the description of the function ""Languages()"" further below to
2194 determine how many languages are actually available in a given
2195 installation of this package.
2196
2197 • "$lang = Language();"
2198
2199 • "Language($lang); # DEPRECATED"
2200
2201 • "$oldlang = Language($newlang); # DEPRECATED"
2202
2203 This function can be used to determine which language is currently
2204 selected, and to change the selected language (this latter use is
2205 deprecated, because this global setting may cause conflicts between
2206 threads or modules running concurrently).
2207
2208 Thereby, each language has a unique internal number.
2209
2210 The original distribution contains the following fourteen languages:
2211
2212 1 ==> English (default)
2213 2 ==> Français (French)
2214 3 ==> Deutsch (German)
2215 4 ==> Español (Spanish)
2216 5 ==> Português (Portuguese)
2217 6 ==> Nederlands (Dutch)
2218 7 ==> Italiano (Italian)
2219 8 ==> Norsk (Norwegian)
2220 9 ==> Svenska (Swedish)
2221 10 ==> Dansk (Danish)
2222 11 ==> suomi (Finnish)
2223 12 ==> Magyar (Hungarian)
2224 13 ==> polski (Polish)
2225 14 ==> Romaneste (Romanian)
2226
2227 See the section "How to install additional languages" in the file
2228 "INSTALL.txt" in this distribution for how to add more languages to
2229 this package.
2230
2231 See the description of the function ""Languages()"" further below to
2232 determine how many languages are actually available in a given
2233 installation of this package.
2234
2235 BEWARE that in order for your programs to be portable, you should
2236 NEVER actually use the internal number of a language in this package
2237 EXPLICITLY, because the same number could mean different languages on
2238 different systems, depending on what languages have been added to any
2239 given installation of this package.
2240
2241 Therefore, you should always use a statement such as
2242
2243 Language(Decode_Language("Name_of_Language")); # DEPRECATED
2244
2245 or
2246
2247 DateCalc_Function(@parameters,Decode_Language("Name_of_Language")); # RECOMMENDED
2248
2249 to select the desired language, and
2250
2251 $language = Language_to_Text(Language());
2252
2253 or
2254
2255 $old_language = Language_to_Text(Language("Name_of_new_Language")); # DEPRECATED
2256
2257 to determine the (previously) selected language.
2258
2259 If the so chosen language is not available in the current
2260 installation, this will result in an appropriate error message,
2261 instead of silently using the wrong (a random) language (which just
2262 happens to have the same internal number in the other installation).
2263
2264 BEWARE that when using the function ""Language()"", the selected
2265 language is a global setting, shared by all threads or modules you
2266 might be running concurrently, thus possibly causing conflicts
2267 between them.
2268
2269 In order to avoid these conflicts, you should NEVER use the function
2270 ""Language()"", but should ALWAYS pass a language number (as returned
2271 by the function ""Decode_Language()"") to the functions which are
2272 language-dependent, which are:
2273
2274 "Decode_Month()", "Decode_Day_of_Week()", "Compressed_to_Text()",
2275 "Date_to_Text()", "Date_to_Text_Long()", "Calendar()",
2276 "Month_to_Text()", "Day_of_Week_to_Text()",
2277 "Day_of_Week_Abbreviation()", "Decode_Date_EU()", "Decode_Date_US()",
2278 "Decode_Date_EU2()", "Decode_Date_US2()", "Parse_Date()".
2279
2280 Note that when you pass an invalid number, such as e.g. zero, or no
2281 language parameter at all, these functions will revert to their
2282 behaviour in the versions of this module prior to 6.0, which means
2283 that the global setting (as set by ""Language()"") becomes active
2284 again (only in case of an invalid or missing language parameter!).
2285
2286 In the C library "DateCalc.c", where omitting a parameter is not an
2287 option, passing a zero for the language is therefore the recommended
2288 way to guarantee backward compatibility.
2289
2290 • "$max_lang = Languages();"
2291
2292 This function returns the (maximum) number of languages which are
2293 currently available in your installation of this package.
2294
2295 (This may vary from installation to installation.)
2296
2297 See the section "How to install additional languages" in the file
2298 "INSTALL.txt" in this distribution for how to add more languages to
2299 this package.
2300
2301 In the original distribution of this package there are fourteen
2302 built-in languages, therefore the value returned by this function
2303 will be "14" if no other languages have been added to your particular
2304 installation.
2305
2306 • "if (($year,$month,$day) = Decode_Date_EU2($string[,$lang))"
2307
2308 This function is the Perl equivalent of the function
2309 ""Decode_Date_EU()"" (implemented in C), included here merely as an
2310 example to demonstrate how easy it is to write your own routine in
2311 Perl (using regular expressions) adapted to your own special needs,
2312 should the necessity arise, and intended primarily as a basis for
2313 your own development.
2314
2315 In one particular case this Perl version is actually slightly more
2316 permissive than its C equivalent, as far as the class of permitted
2317 intervening (i.e., delimiting) characters is concerned.
2318
2319 (Can you tell the subtle, almost insignificant difference by looking
2320 at the code? Or by experimenting? Hint: Try the string "a3b1c64d"
2321 with both functions.)
2322
2323 • "if (($year,$month,$day) = Decode_Date_US2($string[,$lang))"
2324
2325 This function is the Perl equivalent of the function
2326 ""Decode_Date_US()"" (implemented in C), included here merely as an
2327 example to demonstrate how easy it is to write your own routine in
2328 Perl (using regular expressions) adapted to your own special needs,
2329 should the necessity arise, and intended primarily as a basis for
2330 your own development.
2331
2332 In one particular case this Perl version is actually slightly more
2333 permissive than its C equivalent.
2334
2335 (Hint: This is the same difference as with the ""Decode_Date_EU()""
2336 and ""Decode_Date_EU2()"" pair of functions.)
2337
2338 In a different case, the C version is a little bit more permissive
2339 than its Perl equivalent.
2340
2341 (Can you tell the difference by looking at the code? Or by
2342 experimenting? Hint: Try the string "(1/364)" with both functions.)
2343
2344 • "if (($year,$month,$day) = Parse_Date($string[,$lang))"
2345
2346 This function is useful for parsing dates as returned by the UNIX
2347 ""date"" command or as found in the headers of e-mail (in order to
2348 determine the date at which some e-mail has been sent or received,
2349 for instance).
2350
2351 Example #1:
2352
2353 ($year,$month,$day) = Parse_Date(`/bin/date`);
2354
2355 Example #2:
2356
2357 while (<MAIL>)
2358 {
2359 if (/^From \S/)
2360 {
2361 ($year,$month,$day) = Parse_Date($_);
2362 ...
2363 }
2364 ...
2365 }
2366
2367 The function returns an empty list if it can't extract a valid date
2368 from the input string.
2369
2370 • "$lower = ISO_LC($string);"
2371
2372 Returns a copy of the given string where all letters of the
2373 ISO-Latin-1 character set have been replaced by their lower case
2374 equivalents.
2375
2376 Similar to Perl's built-in function ""lc()"" (see "lc" in
2377 perlfunc(1)) but for the whole ISO-Latin-1 character set, not just
2378 plain ASCII.
2379
2380 • "$upper = ISO_UC($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 upper case
2384 equivalents.
2385
2386 Similar to Perl's built-in function ""uc()"" (see "uc" in
2387 perlfunc(1)) but for the whole ISO-Latin-1 character set, not just
2388 plain ASCII.
2389
2390 • "$string = Date::Calc::Version();"
2391
2392 This function returns a string with the (numeric) version number of
2393 the CÂ library ("DateCalc.c") at the core of this package (which is
2394 also (automatically) the version number of the "Calc.xs" file).
2395
2396 Note that under all normal circumstances, this version number should
2397 be identical with the one found in the Perl variable
2398 "$Date::Calc::VERSION" (the version number of the "Calc.pm" file).
2399
2400 Since this function is not exported, you always have to qualify it
2401 explicitly, i.e., ""Date::Calc::Version()"".
2402
2403 This is to avoid possible name space conflicts with version functions
2404 from other modules.
2405
2407 1) How do I compare two dates?
2408
2409 Solution #1:
2410
2411 use Date::Calc qw( Date_to_Days );
2412
2413 if (Date_to_Days($year1,$month1,$day1) <
2414 Date_to_Days($year2,$month2,$day2))
2415
2416 if (Date_to_Days($year1,$month1,$day1) <=
2417 Date_to_Days($year2,$month2,$day2))
2418
2419 if (Date_to_Days($year1,$month1,$day1) >
2420 Date_to_Days($year2,$month2,$day2))
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 $cmp = (Date_to_Days($year1,$month1,$day1) <=>
2432 Date_to_Days($year2,$month2,$day2));
2433
2434 Solution #2:
2435
2436 use Date::Calc qw( Delta_Days );
2437
2438 if (Delta_Days($year1,$month1,$day1,
2439 $year2,$month2,$day2) > 0)
2440
2441 if (Delta_Days($year1,$month1,$day1,
2442 $year2,$month2,$day2) >= 0)
2443
2444 if (Delta_Days($year1,$month1,$day1,
2445 $year2,$month2,$day2) < 0)
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 2) How do I check whether a given date lies within a certain range of
2457 dates?
2458
2459 use Date::Calc qw( Date_to_Days );
2460
2461 $lower = Date_to_Days($year1,$month1,$day1);
2462 $upper = Date_to_Days($year2,$month2,$day2);
2463
2464 $date = Date_to_Days($year,$month,$day);
2465
2466 if (($date >= $lower) && ($date <= $upper))
2467 {
2468 # ok
2469 }
2470 else
2471 {
2472 # not ok
2473 }
2474
2475 3) How do I compare two dates with times? How do I check whether two
2476 dates and times lie more or less than a given time interval apart?
2477
2478 Solution #1:
2479
2480 use Date::Calc qw( Add_Delta_DHMS Date_to_Days );
2481
2482 @date1 = (2002,8,31,23,59,1);
2483 @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2484
2485 #@date1 = (2002,8,31,22,59,1);
2486 #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2487
2488 # Omit the next line if you just want to compare the two dates
2489 # (and change @date3 and @d3 to @date1 and @d1, respectively):
2490
2491 @date3 = Add_Delta_DHMS(@date1, 0,12,0,0); # ==> is the difference within 12 hours?
2492
2493 @d2 = ( Date_to_Days(@date2[0..2]), ($date2[3]*60+$date2[4])*60+$date2[5] );
2494 @d3 = ( Date_to_Days(@date3[0..2]), ($date3[3]*60+$date3[4])*60+$date3[5] );
2495
2496 @diff = ( $d2[0]-$d3[0], $d2[1]-$d3[1] );
2497
2498 if ($diff[0] > 0 and $diff[1] < 0) { $diff[0]--; $diff[1] += 86400; }
2499 if ($diff[0] < 0 and $diff[1] > 0) { $diff[0]++; $diff[1] -= 86400; }
2500
2501 if (($diff[0] || $diff[1]) >= 0) { print "More than 12 hours.\n"; }
2502 else { print "Less than 12 hours.\n"; }
2503
2504 Solution #2:
2505
2506 This solution is only feasible if your dates are guaranteed to lie
2507 within the range given by your system's epoch and overflow date and
2508 time!
2509
2510 Unix: 1-Jan-1970 00:00:00 to 19-Jan-2038 03:14:07
2511 MacOS: 1-Jan-1904 00:00:00 to 6-Feb-2040 06:28:15
2512
2513 use Date::Calc qw( Date_to_Time );
2514
2515 @date1 = (2002,8,31,23,59,1);
2516 @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours
2517
2518 #@date1 = (2002,8,31,22,59,1);
2519 #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours
2520
2521 $d1 = Date_to_Time(@date1);
2522 $d2 = Date_to_Time(@date2);
2523
2524 if ($d1 <= $d2) { print "The two dates are in chronological order.\n"; }
2525 else { print "The two dates are in reversed order.\n"; }
2526
2527 if ($d1 + 12*60*60 <= $d2) { print "More than 12 hours.\n"; }
2528 else { print "Less than 12 hours.\n"; }
2529
2530 4) How do I verify whether someone has a certain age?
2531
2532 use Date::Calc qw( Decode_Date_EU Today leap_year Delta_Days );
2533
2534 $date = <STDIN>; # get birthday
2535
2536 ($year1,$month1,$day1) = Decode_Date_EU($date);
2537
2538 ($year2,$month2,$day2) = Today();
2539
2540 if (($day1 == 29) && ($month1 == 2) && !leap_year($year2))
2541 { $day1--; }
2542
2543 if ( (($year2 - $year1) > 18) ||
2544 ( (($year2 - $year1) == 18) &&
2545 (Delta_Days($year2,$month1,$day1, $year2,$month2,$day2) >= 0) ) )
2546 {
2547 print "Ok - you are over 18.\n";
2548 }
2549 else
2550 {
2551 print "Sorry - you aren't 18 yet!\n";
2552 }
2553
2554 Or, alternatively (substituting the last "if" statement above):
2555
2556 if (($year1+18 <=> $year2 || $month1 <=> $month2 || $day1 <=> $day2) <= 0)
2557 { print "Ok - you are over 18.\n"; }
2558 else
2559 { print "Sorry - you aren't 18 yet!\n"; }
2560
2561 5) How do I calculate the number of the week of month the current date
2562 lies in?
2563
2564 For example:
2565
2566 April 1998
2567 Mon Tue Wed Thu Fri Sat Sun
2568 1 2 3 4 5 = week #1
2569 6 7 8 9 10 11 12 = week #2
2570 13 14 15 16 17 18 19 = week #3
2571 20 21 22 23 24 25 26 = week #4
2572 27 28 29 30 = week #5
2573
2574 Solution:
2575
2576 use Date::Calc qw( Today Day_of_Week );
2577
2578 ($year,$month,$day) = Today();
2579
2580 $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;
2581
2582 6) How do I calculate whether a given date is the 1st, 2nd, 3rd, 4th
2583 or 5th of that day of week in the given month?
2584
2585 For example:
2586
2587 October 2000
2588 Mon Tue Wed Thu Fri Sat Sun
2589 1
2590 2 3 4 5 6 7 8
2591 9 10 11 12 13 14 15
2592 16 17 18 19 20 21 22
2593 23 24 25 26 27 28 29
2594 30 31
2595
2596 Is Sunday, the 15th of October 2000, the 1st, 2nd, 3rd, 4th or 5th
2597 Sunday of that month?
2598
2599 Solution:
2600
2601 use Date::Calc qw( Day_of_Week Delta_Days
2602 Nth_Weekday_of_Month_Year
2603 Date_to_Text_Long English_Ordinal
2604 Day_of_Week_to_Text Month_to_Text );
2605
2606 ($year,$month,$day) = (2000,10,15);
2607
2608 $dow = Day_of_Week($year,$month,$day);
2609
2610 $n = int( Delta_Days(
2611 Nth_Weekday_of_Month_Year($year,$month,$dow,1),
2612 $year,$month,$day)
2613 / 7) + 1;
2614
2615 printf("%s is the %s %s in %s %d.\n",
2616 Date_to_Text_Long($year,$month,$day),
2617 English_Ordinal($n),
2618 Day_of_Week_to_Text($dow),
2619 Month_to_Text($month),
2620 $year);
2621
2622 This prints:
2623
2624 Sunday, October 15th 2000 is the 3rd Sunday in October 2000.
2625
2626 7) How do I calculate the date of the Wednesday of the same week as
2627 the current date?
2628
2629 Solution #1:
2630
2631 use Date::Calc qw( Today Day_of_Week Add_Delta_Days );
2632
2633 $searching_dow = 3; # 3 = Wednesday
2634
2635 @today = Today();
2636
2637 $current_dow = Day_of_Week(@today);
2638
2639 @date = Add_Delta_Days(@today, $searching_dow - $current_dow);
2640
2641 Solution #2:
2642
2643 use Date::Calc qw( Today Add_Delta_Days
2644 Monday_of_Week Week_of_Year );
2645
2646 $searching_dow = 3; # 3 = Wednesday
2647
2648 @today = Today();
2649
2650 @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
2651 $searching_dow - 1 );
2652
2653 Solution #3:
2654
2655 use Date::Calc qw( Standard_to_Business Today
2656 Business_to_Standard );
2657
2658 @business = Standard_to_Business(Today());
2659
2660 $business[2] = 3; # 3 = Wednesday
2661
2662 @date = Business_to_Standard(@business);
2663
2664 8) How can I add a week offset to a business date (including across
2665 year boundaries)?
2666
2667 use Date::Calc qw( Business_to_Standard Add_Delta_Days
2668 Standard_to_Business );
2669
2670 @temp = Business_to_Standard($year,$week,$dow);
2671
2672 @temp = Add_Delta_Days(@temp, $week_offset * 7);
2673
2674 ($year,$week,$dow) = Standard_to_Business(@temp);
2675
2676 9) How do I calculate the last and the next Saturday for any given
2677 date?
2678
2679 use Date::Calc qw( Today Day_of_Week Add_Delta_Days
2680 Day_of_Week_to_Text Date_to_Text );
2681
2682 $searching_dow = 6; # 6 = Saturday
2683
2684 @today = Today();
2685
2686 $current_dow = Day_of_Week(@today);
2687
2688 if ($searching_dow == $current_dow)
2689 {
2690 @prev = Add_Delta_Days(@today,-7);
2691 @next = Add_Delta_Days(@today,+7);
2692 }
2693 else
2694 {
2695 if ($searching_dow > $current_dow)
2696 {
2697 @next = Add_Delta_Days(@today,
2698 $searching_dow - $current_dow);
2699 @prev = Add_Delta_Days(@next,-7);
2700 }
2701 else
2702 {
2703 @prev = Add_Delta_Days(@today,
2704 $searching_dow - $current_dow);
2705 @next = Add_Delta_Days(@prev,+7);
2706 }
2707 }
2708
2709 $dow = Day_of_Week_to_Text($searching_dow);
2710
2711 print "Today is: ", ' ' x length($dow),
2712 Date_to_Text(@today), "\n";
2713 print "Last $dow was: ", Date_to_Text(@prev), "\n";
2714 print "Next $dow will be: ", Date_to_Text(@next), "\n";
2715
2716 This will print something like:
2717
2718 Today is: Sun 12-Apr-1998
2719 Last Saturday was: Sat 11-Apr-1998
2720 Next Saturday will be: Sat 18-Apr-1998
2721
2722 10) How can I calculate the last business day (payday!) of a month?
2723
2724 Solution #1 (holidays NOT taken into account):
2725
2726 use Date::Calc qw( Days_in_Month Day_of_Week Add_Delta_Days );
2727
2728 $day = Days_in_Month($year,$month);
2729 $dow = Day_of_Week($year,$month,$day);
2730 if ($dow > 5)
2731 {
2732 ($year,$month,$day) =
2733 Add_Delta_Days($year,$month,$day, 5-$dow);
2734 }
2735
2736 Solution #2 (holidays taken into account):
2737
2738 This solution expects a multi-dimensional array "@holiday", which
2739 contains all holidays, as follows: ""$holiday[$year][$month][$day]
2740 = 1;"".
2741
2742 (See the description of the function ""Easter_Sunday()"" further
2743 above for how to calculate the moving (variable) christian feast
2744 days!)
2745
2746 Days which are not holidays remain undefined or should have a value
2747 of zero in this array.
2748
2749 use Date::Calc qw( Days_in_Month Add_Delta_Days Day_of_Week );
2750
2751 $day = Days_in_Month($year,$month);
2752 while (1)
2753 {
2754 while ($holiday[$year][$month][$day])
2755 {
2756 ($year,$month,$day) =
2757 Add_Delta_Days($year,$month,$day, -1);
2758 }
2759 $dow = Day_of_Week($year,$month,$day);
2760 if ($dow > 5)
2761 {
2762 ($year,$month,$day) =
2763 Add_Delta_Days($year,$month,$day, 5-$dow);
2764 }
2765 else { last; }
2766 }
2767
2768 Solution #3 (holidays taken into account, more comfortable, but
2769 requires Date::Calendar(3) and Date::Calc::Object(3)):
2770
2771 use Date::Calc::Object qw( Today Add_Delta_YM Date_to_Text_Long );
2772 use Date::Calendar::Profiles qw($Profiles);
2773 use Date::Calendar;
2774
2775 $calendar = Date::Calendar->new( $Profiles->{'DE-BW'} );
2776
2777 @today = Today();
2778 @nextmonth = Add_Delta_YM(@today[0,1],1, 0,1);
2779
2780 $workaround = $calendar->add_delta_workdays(@nextmonth,+1);
2781 $payday = $calendar->add_delta_workdays($workaround,-2);
2782
2783 print "Pay day = ", Date_to_Text_Long($payday->date()), "\n";
2784
2785 The "workaround" is necessary due to a bug in the method
2786 "add_delta_workdays()" when adding a negative number of workdays.
2787
2788 11) How do I convert a MS Visual Basic "DATETIME" value into its date
2789 and time constituents?
2790
2791 use Date::Calc qw( Add_Delta_DHMS Date_to_Text );
2792
2793 $datetime = "35883.121653";
2794
2795 ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);
2796
2797 ($year,$month,$day, $hour,$min,$sec) =
2798 Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);
2799
2800 printf("The given date is %s %02d:%02d:%02d\n",
2801 Date_to_Text($year,$month,$day), $hour, $min, $sec);
2802
2803 This prints:
2804
2805 The given date is Tue 31-Mar-1998 12:16:53
2806
2807 Since I do not have or use Visual Basic, I can't guarantee that the
2808 number format assumed here is really the one used by Visual Basic -
2809 but you get the general idea. ":-)"
2810
2811 Moreover, consider the following:
2812
2813 Morten Sickel <Morten.Sickel@nrpa.no> wrote:
2814
2815 I discovered a bug in Excel (2000): Excel thinks that 1900 was a
2816 leap year. Users should use 31-Dec-1899 as the date to add an Excel
2817 date value to in order to get the correct date.
2818
2819 I found out on the web that this bug originated in Lotus 123, which
2820 made 29-Feb-1900 an "industrial standard". MS chose to keep the bug
2821 in order to be compatible with Lotus 123. But they have not
2822 mentioned anything about it in the help files.
2823
2824 12) How can I send a reminder to members of a group on the day before a
2825 meeting which occurs every first Friday of a month?
2826
2827 use Date::Calc qw( Today Date_to_Days Add_Delta_YMD
2828 Nth_Weekday_of_Month_Year );
2829
2830 ($year,$month,$day) = Today();
2831
2832 $tomorrow = Date_to_Days($year,$month,$day) + 1;
2833
2834 $dow = 5; # 5 = Friday
2835 $n = 1; # 1 = First of that day of week
2836
2837 $meeting_this_month = Date_to_Days(
2838 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2839
2840 ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);
2841
2842 $meeting_next_month = Date_to_Days(
2843 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );
2844
2845 if (($tomorrow == $meeting_this_month) ||
2846 ($tomorrow == $meeting_next_month))
2847 {
2848 # Send reminder e-mail!
2849 }
2850
2851 13) How can I print a date in a different format than provided by the
2852 functions ""Date_to_Text()"", ""Date_to_Text_Long()"" or
2853 ""Compressed_to_Text()""?
2854
2855 use Date::Calc qw( Today Day_of_Week_to_Text
2856 Day_of_Week Month_to_Text
2857 English_Ordinal );
2858
2859 ($year,$month,$day) = Today();
2860
2861 For example with leading zeros for the day: "Fri 03-Jan-1964"
2862
2863 printf("%.3s %02d-%.3s-%d\n",
2864 Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
2865 $day,
2866 Month_to_Text($month),
2867 $year);
2868
2869 For example in U.S. american format: "April 12th, 1998"
2870
2871 $string = sprintf("%s %s, %d",
2872 Month_to_Text($month),
2873 English_Ordinal($day),
2874 $year);
2875
2876 For example in one of the possible formats as specified by
2877 ISOÂ 8601:
2878
2879 @date = ($year,$month,$day,$hour,$min,$sec);
2880 $date = sprintf("%d-%02d-%02d %02d:%02d:%02d", @date);
2881
2882 (See also "printf" in perlfunc(1) and/or "sprintf" in perlfunc(1)!)
2883
2884 14) How can I iterate through a range of dates?
2885
2886 use Date::Calc qw( Delta_Days Add_Delta_Days );
2887
2888 @start = (1999,5,27);
2889 @stop = (1999,6,1);
2890
2891 $j = Delta_Days(@start,@stop);
2892
2893 for ( $i = 0; $i <= $j; $i++ )
2894 {
2895 @date = Add_Delta_Days(@start,$i);
2896 printf("%4d/%02d/%02d\n", @date);
2897 }
2898
2899 Note that the loop can be improved; see also the recipe below.
2900
2901 15) How can I create a (Perl) list of dates in a certain range?
2902
2903 use Date::Calc qw( Delta_Days Add_Delta_Days Date_to_Text );
2904
2905 sub date_range
2906 {
2907 my(@date) = (@_)[0,1,2];
2908 my(@list);
2909 my($i);
2910
2911 $i = Delta_Days(@_);
2912 while ($i-- >= 0)
2913 {
2914 push( @list, [ @date ] );
2915 @date = Add_Delta_Days(@date, 1) if ($i >= 0);
2916 }
2917 return(@list);
2918 }
2919
2920 @range = &date_range(1999,11,3, 1999,12,24); # in chronological order
2921
2922 foreach $date (@range)
2923 {
2924 print Date_to_Text(@{$date}), "\n";
2925 }
2926
2927 Note that you probably shouldn't use this one, because it is much
2928 more efficient to iterate through all the dates (as shown in the
2929 recipe immediately above) than to construct such an array and then
2930 to loop through it. Also, it is much more space-efficient not to
2931 create this array.
2932
2933 16) How can I calculate the difference in days between dates, but
2934 without counting Saturdays and Sundays?
2935
2936 sub Delta_Business_Days
2937 {
2938 my(@date1) = (@_)[0,1,2];
2939 my(@date2) = (@_)[3,4,5];
2940 my($minus,$result,$dow1,$dow2,$diff,$temp);
2941
2942 $minus = 0;
2943 $result = Delta_Days(@date1,@date2);
2944 if ($result != 0)
2945 {
2946 if ($result < 0)
2947 {
2948 $minus = 1;
2949 $result = -$result;
2950 $dow1 = Day_of_Week(@date2);
2951 $dow2 = Day_of_Week(@date1);
2952 }
2953 else
2954 {
2955 $dow1 = Day_of_Week(@date1);
2956 $dow2 = Day_of_Week(@date2);
2957 }
2958 $diff = $dow2 - $dow1;
2959 $temp = $result;
2960 if ($diff != 0)
2961 {
2962 if ($diff < 0)
2963 {
2964 $diff += 7;
2965 }
2966 $temp -= $diff;
2967 $dow1 += $diff;
2968 if ($dow1 > 6)
2969 {
2970 $result--;
2971 if ($dow1 > 7)
2972 {
2973 $result--;
2974 }
2975 }
2976 }
2977 if ($temp != 0)
2978 {
2979 $temp /= 7;
2980 $result -= ($temp << 1);
2981 }
2982 }
2983 if ($minus) { return -$result; }
2984 else { return $result; }
2985 }
2986
2987 This solution is probably of little practical value, however,
2988 because it doesn't take legal holidays into account.
2989
2990 See Date::Calendar(3) for how to do that.
2991
2992 17) How can I "normalize" the output of the "Delta_YMDHMS()" (or
2993 "Delta_YMD()") function so that it contains only positive values?
2994
2995 I.e., how can I show a difference in date (and time) in a more
2996 human-readable form, for example in order to show how much time
2997 until (or since) the expiration of something (e.g. an account, a
2998 domain, a credit card, etc.) is left (has passed)?
2999
3000 Correct solution: Use the functions "N_Delta_YMDHMS()" and
3001 "N_Delta_YMD()" instead!
3002
3003 The following gives a rudimentary sketch of a (much inferior)
3004 solution, which is maintained here only for historical reasons of
3005 this module:
3006
3007 a) Delta_YMDHMS():
3008
3009 #!perl
3010 use strict;
3011 use Date::Calc qw(Today_and_Now Delta_YMDHMS Add_Delta_YMDHMS Delta_DHMS Date_to_Text);
3012
3013 my $today = [Today_and_Now()];
3014 my $target = [2005,1,1,0,0,0];
3015
3016 my $sign = "until";
3017 my $delta = Normalize_Delta_YMDHMS($today,$target);
3018 if ($delta->[0] < 0)
3019 {
3020 $sign = "since";
3021 $delta = Normalize_Delta_YMDHMS($target,$today);
3022 }
3023 printf("Today is %s %02d:%02d:%02d\n", Date_to_Text(@{$today}[0..2]), @{$today}[3..5]);
3024 printf
3025 (
3026 "%d year%s, %d month%s, %d day%s, %d hour%s, %d minute%s, %d second%s %s %s %02d:%02d:%02d\n",
3027 $delta->[0], (($delta->[0]==1)?'':'s'),
3028 $delta->[1], (($delta->[1]==1)?'':'s'),
3029 $delta->[2], (($delta->[2]==1)?'':'s'),
3030 $delta->[3], (($delta->[3]==1)?'':'s'),
3031 $delta->[4], (($delta->[4]==1)?'':'s'),
3032 $delta->[5], (($delta->[5]==1)?'':'s'),
3033 $sign,
3034 Date_to_Text(@{$target}[0..2]),
3035 @{$target}[3..5]
3036 );
3037
3038 sub Normalize_Delta_YMDHMS
3039 {
3040 my($date1,$date2) = @_;
3041 my(@delta);
3042
3043 @delta = Delta_YMDHMS(@$date1,@$date2);
3044 while ($delta[1] < 0 or
3045 $delta[2] < 0 or
3046 $delta[3] < 0 or
3047 $delta[4] < 0 or
3048 $delta[5] < 0)
3049 {
3050 if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3051 if ($delta[2] < 0)
3052 {
3053 $delta[1]--;
3054 @delta[2..5] = (0,0,0,0);
3055 @delta[2..5] = Delta_DHMS(Add_Delta_YMDHMS(@$date1,@delta),@$date2);
3056 }
3057 if ($delta[3] < 0) { $delta[2]--; $delta[3] += 24; }
3058 if ($delta[4] < 0) { $delta[3]--; $delta[4] += 60; }
3059 if ($delta[5] < 0) { $delta[4]--; $delta[5] += 60; }
3060 }
3061 return \@delta;
3062 }
3063
3064 b) Delta_YMD():
3065
3066 #!perl
3067 use strict;
3068 use Date::Calc qw(Today Delta_YMD Add_Delta_YM Delta_Days Date_to_Text);
3069
3070 my($sign,$delta);
3071 my $today = [Today()];
3072 my $target = [2005,1,1];
3073
3074 if (Delta_Days(@$today,@$target) < 0)
3075 {
3076 $sign = "since";
3077 $delta = Normalize_Delta_YMD($target,$today);
3078 }
3079 else
3080 {
3081 $sign = "until";
3082 $delta = Normalize_Delta_YMD($today,$target);
3083 }
3084 print "Today is ", Date_to_Text(@$today), "\n";
3085 printf
3086 (
3087 "%d year%s, %d month%s, %d day%s %s %s\n",
3088 $delta->[0], (($delta->[0]==1)?'':'s'),
3089 $delta->[1], (($delta->[1]==1)?'':'s'),
3090 $delta->[2], (($delta->[2]==1)?'':'s'),
3091 $sign,
3092 Date_to_Text(@$target)
3093 );
3094
3095 sub Normalize_Delta_YMD
3096 {
3097 my($date1,$date2) = @_;
3098 my(@delta);
3099
3100 @delta = Delta_YMD(@$date1,@$date2);
3101 while ($delta[1] < 0 or $delta[2] < 0)
3102 {
3103 if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
3104 if ($delta[2] < 0)
3105 {
3106 $delta[1]--;
3107 $delta[2] = Delta_Days(Add_Delta_YM(@$date1,@delta[0,1]),@$date2);
3108 }
3109 }
3110 return \@delta;
3111 }
3112
3113 Note that for normalizing just a time vector, you can use the
3114 built-in function "Normalize_DHMS()". However, this will yield
3115 either all positive OR all negative values, NOT all positive values
3116 as above.
3117
3119 Date::Calc::Util(3), Date::Calc::Object(3), Date::Calendar(3),
3120 Date::Calendar::Year(3), Date::Calendar::Profiles(3).
3121
3122 "The Calendar FAQ":
3123 http://www.tondering.dk/claus/calendar.html
3124 by Claus Tondering <claus@tondering.dk>
3125
3127 When you are using the (deprecated) function "Language()", the language
3128 setting is stored in a global variable.
3129
3130 This may cause conflicts between threads or modules running
3131 concurrently.
3132
3133 Therefore, in order to avoid such conflicts, NEVER use the function
3134 "Language()", but ALWAYS pass a language parameter to the functions
3135 which are language-dependent.
3136
3138 This man page documents "Date::Calc" version 6.4.
3139
3141 Steffen Beyer
3142 mailto:STBEY@cpan.org
3143 http://www.engelschall.com/u/sb/download/
3144
3146 Copyright (c) 1995 - 2015 by Steffen Beyer. All rights reserved.
3147
3149 This package is free software; you can use, modify and redistribute it
3150 under the same terms as Perl itself, i.e., at your option, under the
3151 terms either of the "Artistic License" or the "GNU General Public
3152 License".
3153
3154 The C library at the core of the module "Date::Calc::XS" can, at your
3155 discretion, also be used, modified and redistributed under the terms of
3156 the "GNU Library General Public License".
3157
3158 Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
3159 "GNU_LGPL.txt" in the "license" subdirectory of this distribution for
3160 any details!
3161
3163 This package is distributed in the hope that it will be useful, but
3164 WITHOUT ANY WARRANTY; without even the implied warranty of
3165 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3166
3167 See the "GNU General Public License" for more details.
3168
3170 Hey! The above document had some coding errors, which are explained
3171 below:
3172
3173 Around line 1761:
3174 Non-ASCII character seen before =encoding in 'Français'. Assuming
3175 CP1252
3176
3177
3178
3179perl v5.32.1 2021-01-27 Date::Calc(3)