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