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