Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Date::Calc(3)	      User Contributed Perl Documentation	 Date::Calc(3)

NAME
       Date::Calc - Gregorian calendar date calculations

MOTTO
       Keep it small, fast and simple

PREFACE
       This package consists of	a C library and	a Perl module (which uses the
       C library, internally) for all kinds of date calculations based on the
       Gregorian calendar (the one used	in all western countries today),
       thereby complying with all relevant norms and standards:
       ISO/RA 2015-1971, DINA 1355 and,	to some	extent,	ISOA 8601 (where
       applicable).

       (See also http://www.engelschall.com/u/sb/download/Date-Calc/DIN1355/
       for a scan of part of the "DINA 1355" document (in German)).

       The module of course handles year numbers of 2000 and above correctly
       ("Year 2000" or "Y2K" compliance) -- actually all year numbers from 1
       to the largest positive integer representable on	your system (which is
       at least	32767) can be dealt with.

       This is not true, however, for the import/export	functions in this
       package which are an interface to the internal POSIX date and time
       functions of your system, which can only	cover dates in the following
       ranges:

	01-Jan-1970 00:00:00 GMT .. 19-Jan-2038	03:14:07 GMT [Unix etc.]
	01-Jan-1904 00:00:00 LT	 .. 06-Feb-2040	06:28:15 LT  [MacOS Classic]
	(LT = local time)

       Note that this package projects the Gregorian calendar back until the
       year 1A A.D. -- even though the Gregorian calendar was only adopted in
       1582, mostly by the Catholic European countries,	in obedience to	the
       corresponding decree of Pope GregoryA XIII in that year.

       Some (mainly protestant)	countries continued to use the Julian calendar
       (used until then) until as late as the beginning	of the 20th century.

       Finally,	note that this package is not intended to do everything	you
       could ever imagine automagically	for you; it is rather intended to
       serve as	a toolbox (in the best of UNIX spirit and traditions) which
       should, however,	always get you where you want to go.

       See the section "RECIPES" at the	bottom of this document	for solutions
       to common problems!

       If nevertheless you can't figure	out how	to solve a particular problem,
       please let me know! (See	e-mail address at the end of this document.)

SYNOPSIS
	 use Date::Calc	qw(
	     Days_in_Year
	     Days_in_Month
	     Weeks_in_Year
	     leap_year
	     check_date
	     check_time
	     check_business_date
	     Day_of_Year
	     Date_to_Days
	     Day_of_Week
	     Week_Number
	     Week_of_Year
	     Monday_of_Week
	     Nth_Weekday_of_Month_Year
	     Standard_to_Business
	     Business_to_Standard
	     Delta_Days
	     Delta_DHMS
	     Delta_YMD
	     Delta_YMDHMS
	     N_Delta_YMD
	     N_Delta_YMDHMS
	     Normalize_DHMS
	     Add_Delta_Days
	     Add_Delta_DHMS
	     Add_Delta_YM
	     Add_Delta_YMD
	     Add_Delta_YMDHMS
	     Add_N_Delta_YMD
	     Add_N_Delta_YMDHMS
	     System_Clock
	     Today
	     Now
	     Today_and_Now
	     This_Year
	     Gmtime
	     Localtime
	     Mktime
	     Timezone
	     Date_to_Time
	     Time_to_Date
	     Easter_Sunday
	     Decode_Month
	     Decode_Day_of_Week
	     Decode_Language
	     Decode_Date_EU
	     Decode_Date_US
	     Fixed_Window
	     Moving_Window
	     Compress
	     Uncompress
	     check_compressed
	     Compressed_to_Text
	     Date_to_Text
	     Date_to_Text_Long
	     English_Ordinal
	     Calendar
	     Month_to_Text
	     Day_of_Week_to_Text
	     Day_of_Week_Abbreviation
	     Language_to_Text
	     Language
	     Languages
	     Decode_Date_EU2
	     Decode_Date_US2
	     Parse_Date
	     ISO_LC
	     ISO_UC
	 );

	 use Date::Calc	qw(:all);

	 Days_in_Year
	     $days = Days_in_Year($year,$month);

	 Days_in_Month
	     $days = Days_in_Month($year,$month);

	 Weeks_in_Year
	     $weeks = Weeks_in_Year($year);

	 leap_year
	     if	(leap_year($year))

	 check_date
	     if	(check_date($year,$month,$day))

	 check_time
	     if	(check_time($hour,$min,$sec))

	 check_business_date
	     if	(check_business_date($year,$week,$dow))

	 Day_of_Year
	     $doy = Day_of_Year($year,$month,$day);

	 Date_to_Days
	     $days = Date_to_Days($year,$month,$day);

	 Day_of_Week
	     $dow = Day_of_Week($year,$month,$day);

	 Week_Number
	     $week = Week_Number($year,$month,$day);	      #	DEPRECATED

	 Week_of_Year
	     ($week,$year) = Week_of_Year($year,$month,$day); #	RECOMMENDED
	     $week = Week_of_Year($year,$month,$day);	      #	DANGEROUS

	 Monday_of_Week
	     ($year,$month,$day) = Monday_of_Week($week,$year);

	 Nth_Weekday_of_Month_Year
	     if	(($year,$month,$day) =
	     Nth_Weekday_of_Month_Year($year,$month,$dow,$n))

	 Standard_to_Business
	     ($year,$week,$dow)	=
	     Standard_to_Business($year,$month,$day);

	 Business_to_Standard
	     ($year,$month,$day) =
	     Business_to_Standard($year,$week,$dow);

	 Delta_Days
	     $Dd = Delta_Days($year1,$month1,$day1,
			      $year2,$month2,$day2);

	 Delta_DHMS
	     ($Dd,$Dh,$Dm,$Ds) =
	     Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
			$year2,$month2,$day2, $hour2,$min2,$sec2);

	 Delta_YMD
	     ($Dy,$Dm,$Dd) =
	     Delta_YMD($year1,$month1,$day1,
		       $year2,$month2,$day2);

	 Delta_YMDHMS
	     ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) =
	     Delta_YMDHMS($year1,$month1,$day1,	$hour1,$min1,$sec1,
			  $year2,$month2,$day2,	$hour2,$min2,$sec2);

	 N_Delta_YMD
	     ($Dy,$Dm,$Dd) =
	     N_Delta_YMD($year1,$month1,$day1,
			 $year2,$month2,$day2);

	 N_Delta_YMDHMS
	     ($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
	     N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
			    $year2,$month2,$day2, $hour2,$min2,$sec2);

	 Normalize_DHMS
	     ($Dd,$Dh,$Dm,$Ds) =
	     Normalize_DHMS($Dd,$Dh,$Dm,$Ds);

	 Add_Delta_Days
	     ($year,$month,$day) =
	     Add_Delta_Days($year,$month,$day,
			    $Dd);

	 Add_Delta_DHMS
	     ($year,$month,$day, $hour,$min,$sec) =
	     Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec,
			    $Dd,$Dh,$Dm,$Ds);

	 Add_Delta_YM
	     ($year,$month,$day) =
	     Add_Delta_YM($year,$month,$day,
			  $Dy,$Dm);

	 Add_Delta_YMD
	     ($year,$month,$day) =
	     Add_Delta_YMD($year,$month,$day,
			   $Dy,$Dm,$Dd);

	 Add_Delta_YMDHMS
	     ($year,$month,$day, $hour,$min,$sec) =
	     Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
			      $D_y,$D_m,$D_d, $Dh,$Dm,$Ds);

	 Add_N_Delta_YMD
	     ($year,$month,$day) =
	     Add_N_Delta_YMD($year,$month,$day,
			     $Dy,$Dm,$Dd);

	 Add_N_Delta_YMDHMS
	     ($year,$month,$day, $hour,$min,$sec) =
	     Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
				$D_y,$D_m,$D_d,	$Dhh,$Dmm,$Dss);

	 System_Clock
	     ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	     System_Clock([$gmt]);

	 Today
	     ($year,$month,$day) = Today([$gmt]);

	 Now
	     ($hour,$min,$sec) = Now([$gmt]);

	 Today_and_Now
	     ($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);

	 This_Year
	     $year = This_Year([$gmt]);

	 Gmtime
	     ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	     Gmtime([time]);

	 Localtime
	     ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	     Localtime([time]);

	 Mktime
	     $time = Mktime($year,$month,$day, $hour,$min,$sec);

	 Timezone
	     ($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);

	 Date_to_Time
	     $time = Date_to_Time($year,$month,$day, $hour,$min,$sec);

	 Time_to_Date
	     ($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);

	 Easter_Sunday
	     ($year,$month,$day) = Easter_Sunday($year);

	 Decode_Month
	     if	($month	= Decode_Month($string[,$lang]))

	 Decode_Day_of_Week
	     if	($dow =	Decode_Day_of_Week($string[,$lang]))

	 Decode_Language
	     if	($lang = Decode_Language($string))

	 Decode_Date_EU
	     if	(($year,$month,$day) = Decode_Date_EU($string[,$lang]))

	 Decode_Date_US
	     if	(($year,$month,$day) = Decode_Date_US($string[,$lang]))

	 Fixed_Window
	     $year = Fixed_Window($yy);

	 Moving_Window
	     $year = Moving_Window($yy);

	 Compress
	     $date = Compress($year,$month,$day);

	 Uncompress
	     if	(($century,$year,$month,$day) =	Uncompress($date))

	 check_compressed
	     if	(check_compressed($date))

	 Compressed_to_Text
	     $string = Compressed_to_Text($date[,$lang]);

	 Date_to_Text
	     $string = Date_to_Text($year,$month,$day[,$lang]);

	 Date_to_Text_Long
	     $string = Date_to_Text_Long($year,$month,$day[,$lang]);

	 English_Ordinal
	     $string = English_Ordinal($number);

	 Calendar
	     $string = Calendar($year,$month[,$orthodox[,$lang]]);

	 Month_to_Text
	     $string = Month_to_Text($month[,$lang]);

	 Day_of_Week_to_Text
	     $string = Day_of_Week_to_Text($dow[,$lang]);

	 Day_of_Week_Abbreviation
	     $string = Day_of_Week_Abbreviation($dow[,$lang]);

	 Language_to_Text
	     $string = Language_to_Text($lang);

	 Language
	     $lang = Language();
	     Language($lang);		    # DEPRECATED
	     $oldlang =	Language($newlang); # DEPRECATED

	 Languages
	     $max_lang = Languages();

	 Decode_Date_EU2
	     if	(($year,$month,$day) = Decode_Date_EU2($string[,$lang]))

	 Decode_Date_US2
	     if	(($year,$month,$day) = Decode_Date_US2($string[,$lang]))

	 Parse_Date
	     if	(($year,$month,$day) = Parse_Date($string[,$lang]))

	 ISO_LC
	     $lower = ISO_LC($string);

	 ISO_UC
	     $upper = ISO_UC($string);

	 Version
	     $string = Date::Calc::Version();

IMPORTANT NOTES
       (See the	section	"RECIPES" at the bottom	of this	document for solutions
       to common problems!)

       o "Year 2000" ("Y2K") compliance

	 The upper limit for any year number in	this module is only given by
	 the size of the largest positive integer that can be represented in a
	 variable of the C type	"int" on your system, which is at least	32767,
	 according to the ANSI C standard (exceptions see below).

	 In order to simplify calculations, this module	projects the gregorian
	 calendar back until the year 1A A.D. -- i.e., back BEYOND the year
	 1582 when this	calendar was first decreed by the Catholic Pope
	 GregoryA XIII!

	 Therefore, BE SURE TO ALWAYS SPECIFY "1998" WHEN YOU MEAN "1998", for
	 instance, and DO NOT WRITE "98" INSTEAD, because this will in fact
	 perform a calculation based on	the year "98" A.D. and NOT "1998"!

	 An exception from this	rule are the functions which contain the word
	 "compress" in their names (which can only handle years	between	1970
	 and 2069 and also accept the abbreviations "00" to "99"), and the
	 functions whose names begin with "Decode_Date_" (which	translate year
	 numbers below 100 using a technique known as "moving window").

	 If you	want to	convert	a two-digit year number	into a full-fledged,
	 four-digit (at	least for some years to	come ";-)") year number, use
	 the two functions "Fixed_Window()" and	"Moving_Window()" (see their
	 description further below).

	 Note also that	the following import/export functions (which are
	 interfaces to the POSIX functions "time()", "gmtime()", "localtime()"
	 and "mktime()"	or (the	last two) substitutes for the BSD function
	 "timegm()" and	the POSIX function "gmtime()") have a very limited
	 range of representable	dates (in contrast to all other	functions in
	 this package, which cover virtually any date including	and after
	 JanuaryA 1stA 1A A.D.):

		       System_Clock()
		       Today()
		       Now()
		       Today_and_Now()
		       This_Year()
		       Gmtime()
		       Localtime()
		       Mktime()
		       Timezone()
		       Date_to_Time()
		       Time_to_Date()

	 These functions can only deal with dates in the range from
	 01-Jan-1970A 00:00:00A	GMT to 19-Jan-2038A 03:14:07A GMT (the latter
	 limit is only authoritative on	32A bit	systems, however, and can (in
	 principle, through a few code changes)	be extended somewhat ":-)" on
	 64A bit systems).

	 On MacOS Classic, the valid range of dates is between (both included)
	 01-Jan-1904A 00:00:00 (local time) to 06-Feb-2040A 06:28:15 (local
	 time).

	 Note further that the function	"Easter_Sunday()" can only be used for
	 years in the range 1583 to 2299.

       o POSIX functions

	 Note that the following functions

		       Gmtime()
		       Localtime()
		       Mktime()
		       Timezone()

	 are actually wrappers around or based upon the	corresponding POSIX
	 functions "time()", "gmtime()", "localtime()" and "mktime()".

	 As such, they depend on local settings	of the underlying machine such
	 as e.g. the system clock, the time zone and the locale.

	 Their results can therefore sometimes be unexpected or	counter-
	 intuitive.

	 Therefore, no support can be provided for these functions.

	 They are supplied "as is", purely for the sake	of interoperability.

	 Use at	your own risk. (You have been warned!)

       o First index

	 ALL ranges in this module start with "1", NOT "0"!

	 I.e., the day of month, day of	week, day of year, month of year, week
	 of year, first	valid year number and language ALL start counting at
	 one, NOT zero!

	 The only exception is the function ""Week_Number()"", which may in
	 fact return "0" when the given	date actually lies in the last week of
	 the PREVIOUS year, and	of course the numbers for hours	(0..23),
	 minutes (0..59) and seconds (0..59).

       o Function naming conventions

	 Function names	completely in lower case indicate a boolean return
	 value.

       o Boolean values

	 Boolean values	returned from functions	in this	module are always a
	 numeric zero ("0") for	"false"	and a numeric one ("1")	for "true".

       o Exception handling

	 The functions in this module will usually die with a corresponding
	 error message if their	input parameters, intermediate results or
	 output	values are out of range.

	 The following functions handle	errors differently:

	   -  check_date()
	   -  check_time()
	   -  check_business_date()
	   -  check_compressed()

	 (which	return a "false" return	value when the given input does	not
	 represent a valid date	or time),

	   -  Nth_Weekday_of_Month_Year()

	 (which	returns	an empty list if the requested 5th day of week does
	 not exist),

	   -  Decode_Month()
	   -  Decode_Day_of_Week()
	   -  Decode_Language()
	   -  Fixed_Window()
	   -  Moving_Window()
	   -  Compress()

	 (which	return "0" upon	failure	or invalid input), and

	   -  Decode_Date_EU()
	   -  Decode_Date_US()
	   -  Decode_Date_EU2()
	   -  Decode_Date_US2()
	   -  Parse_Date()
	   -  Uncompress()

	 (which	return an empty	list upon failure or invalid input).

	 Note that you can always catch	an exception thrown by any of the
	 functions in this module and handle it	yourself by enclosing the
	 function call in an ""eval"" with curly brackets and checking the
	 special variable "$@" (see "eval" in perlfunc(1) for details).

DESCRIPTION
       o "use Date::Calc qw( Days_in_Year Days_in_Month	... );"

       o "use Date::Calc qw(:all);"

	 You can either	specify	the functions you want to import explicitly by
	 enumerating them between the parentheses of the ""qw()"" operator, or
	 you can use the "":all"" tag instead to import	ALL available
	 functions.

       o "$days	= Days_in_Year($year,$month);"

	 This function returns the sum of the number of	days in	the months
	 starting with January up to and including "$month" in the given year
	 "$year".

	 I.e., ""Days_in_Year(1998,1)""	returns	"31", ""Days_in_Year(1998,2)""
	 returns "59", ""Days_in_Year(1998,3)""	returns	"90", and so on.

	 Note that ""Days_in_Year($year,12)"" returns the number of days in
	 the given year	"$year", i.e., either "365" or "366".

       o "$days	= Days_in_Month($year,$month);"

	 This function returns the number of days in the given month "$month"
	 of the	given year "$year".

	 The year must always be supplied, even	though it is only needed when
	 the month is February,	in order to determine whether it is a leap
	 year or not.

	 I.e., ""Days_in_Month(1998,1)"" returns "31",
	 ""Days_in_Month(1998,2)"" returns "28", ""Days_in_Month(2000,2)""
	 returns "29", ""Days_in_Month(1998,3)"" returns "31", and so on.

       o "$weeks = Weeks_in_Year($year);"

	 This function returns the number of weeks in the given	year "$year",
	 i.e., either "52" or "53".

       o "if (leap_year($year))"

	 This function returns "true" ("1") if the given year "$year" is a
	 leap year and "false" ("0") otherwise.

       o "if (check_date($year,$month,$day))"

	 This function returns "true" ("1") if the given three numerical
	 values	"$year", "$month" and "$day" constitute	a valid	date, and
	 "false" ("0") otherwise.

       o "if (check_time($hour,$min,$sec))"

	 This function returns "true" ("1") if the given three numerical
	 values	"$hour", "$min"	and "$sec" constitute a	valid time ("0 <=
	 $hour < 24", "0 <= $min < 60" and "0 <= $sec <	60"), and "false"
	 ("0") otherwise.

       o "if (check_business_date($year,$week,$dow))"

	 This function returns "true" ("1") if the given three numerical
	 values	"$year", "$week" and "$dow" constitute a valid date in
	 business format, and "false" ("0") otherwise.

	 Beware	that this function does	NOT compute whether a given date is a
	 business day (i.e., Monday to Friday)!

	 To do so, use ""(Day_of_Week($year,$month,$day) < 6)""	instead.

       o "$doy = Day_of_Year($year,$month,$day);"

	 This function returns the (relative) number of	the day	of the given
	 date in the given year.

	 E.g., ""Day_of_Year($year,1,1)"" returns "1",
	 ""Day_of_Year($year,2,1)"" returns "32", and
	 ""Day_of_Year($year,12,31)"" returns either "365" or "366".

	 The day of year is sometimes also referred to as the Julian day (or
	 date),	although it has	nothing	to do with the Julian calendar,	the
	 calendar which	was used before	the Gregorian calendar.

	 In order to convert the number	returned by this function back into a
	 date, use the function	""Add_Delta_Days()"" (described	further
	 below), as follows:

	   $doy	= Day_of_Year($year,$month,$day);
	   ($year,$month,$day) = Add_Delta_Days($year,1,1, $doy	- 1);

       o "$days	= Date_to_Days($year,$month,$day);"

	 This function returns the (absolute) number of	the day	of the given
	 date, where counting starts at	the 1st	of January of the year 1A A.D.

	 I.e., ""Date_to_Days(1,1,1)"" returns "1", ""Date_to_Days(1,12,31)""
	 returns "365",	""Date_to_Days(2,1,1)""	returns	"366",
	 ""Date_to_Days(1998,5,1)"" returns "729510", and so on.

	 This is sometimes also	referred to (not quite correctly) as the
	 Julian	date (or day). This may	cause confusion, because also the
	 number	of the day in a	year (from 1 to	365 or 366) is frequently
	 called	the "Julian day".

	 More confusing	still, this has	nothing	to do with the Julian
	 calendar, which was used BEFORE the Gregorian calendar.

	 The Julian calendar was named after famous Julius Caesar, who had
	 instituted it in Roman	times. The Julian calendar is less precise
	 than the Gregorian calendar because it	has too	many leap years
	 compared to the true mean length of a year (but the Gregorian
	 calendar also still has one day too much every	5000 years). Anyway,
	 the Julian calendar was better	than what existed before, because
	 rulers	had often changed the calendar used until then in arbitrary
	 ways, in order	to lengthen their own reign, for instance.

	 In order to convert the number	returned by this function back into a
	 date, use the function	""Add_Delta_Days()"" (described	further
	 below), as follows:

	   $days = Date_to_Days($year,$month,$day);
	   ($year,$month,$day) = Add_Delta_Days(1,1,1, $days - 1);

       o "$dow = Day_of_Week($year,$month,$day);"

	 This function returns the number of the day of	week of	the given
	 date.

	 The function returns "1" for Monday, "2" for Tuesday and so on	until
	 "7" for Sunday.

	 Note that in the Hebrew calendar (on which the	Christian calendar is
	 based), the week starts with Sunday and ends with the Sabbath or
	 Saturday (where according to the Genesis (as described	in the Bible)
	 the Lord rested from creating the world).

	 In medieval times, Catholic Popes have	decreed	the Sunday to be the
	 official day of rest, in order	to dissociate the Christian from the
	 Hebrew	belief.

	 It appears that this actually happened	with the Emperor Constantin,
	 who converted to Christianity but still worshipped the	Sun god	and
	 therefore moved the Christian sabbath to the day of the Sun.

	 Nowadays, the Sunday AND the Saturday are commonly considered (and
	 used as) days of rest,	usually	referred to as the "week-end".

	 Consistent with this practice,	current	norms and standards (such as
	 ISO/RA	2015-1971, DINA	1355 and ISOA 8601) define the Monday as the
	 first day of the week.

       o "$week	= Week_Number($year,$month,$day);"

	 This function returns the number of the week the given	date lies in.

	 If the	given date lies	in the LAST week of the	PREVIOUS year, "0" is
	 returned.

	 If the	given date lies	in the FIRST week of the NEXT year,
	 ""Weeks_in_Year($year)	+ 1"" is returned.

       o "($week,$year)	= Week_of_Year($year,$month,$day);"

	 This function returns the number of the week the given	date lies in,
	 as well as the	year that week belongs to.

	 I.e., if the given date lies in the LAST week of the PREVIOUS year,
	 ""(Weeks_in_Year($year-1), $year-1)"" is returned.

	 If the	given date lies	in the FIRST week of the NEXT year, ""(1,
	 $year+1)"" is returned.

	 Otherwise, ""(Week_Number($year,$month,$day), $year)""	is returned.

       o "$week	= Week_of_Year($year,$month,$day);"

	 In scalar context, this function returns just the week	number.	This
	 allows	you to write ""$week = Week_of_Year($year,$month,$day);""
	 instead of ""($week) =	Week_of_Year($year,$month,$day);"" (note the
	 parentheses around "$week").

	 If the	given date lies	in the LAST week of the	PREVIOUS year,
	 ""Weeks_in_Year($year-1)"" is returned.

	 If the	given date lies	in the FIRST week of the NEXT year, "1"	is
	 returned.

	 Otherwise the return value is identical with that of
	 ""Week_Number($year,$month,$day)"".

	 BEWARE	that using this	function in scalar context is a	DANGEROUS
	 feature, because without knowing which	year the week belongs to, you
	 might inadvertently assume the	wrong one!

	 If for	instance you are iterating through an interval of dates, you
	 might assume that the week always belongs to the same year as the
	 given date, which unfortunately is WRONG in some cases!

	 In many years,	the 31st of December for instance belongs to week
	 number	one of the FOLLOWING year. Assuming that the year is the same
	 as your date (31st of December, in this example), sends you back to
	 the first week	of the CURRENT year - the Monday of which, by the way,
	 in case of bad	luck, might actually lie in the	year BEFORE the
	 current year!

	 This actually happens in 2002,	for example.

	 So you	always need to provide the correct corresponding year number
	 by other means, keeping track of it yourself.

	 In case you do	not understand this, never mind, but then simply DO
	 NOT USE this function in scalar context!

       o "($year,$month,$day) =	Monday_of_Week($week,$year);"

	 This function returns the date	of the first day of the	given week,
	 i.e., the Monday.

	 "$year" must be greater than or equal to "1", and "$week" must	lie in
	 the range "1" to ""Weeks_in_Year($year)"".

	 Note that you can write ""($year,$month,$day) =
	 Monday_of_Week(Week_of_Year($year,$month,$day));"" in order to
	 calculate the date of the Monday of the same week as the given	date.

	 If you	want to	calculate any other day	of week	in the same week as a
	 given date, use

	   @date = Add_Delta_Days(Monday_of_Week(Week_of_Year(@date)),$offset);

	 where "$offset	= 1" for Tuesday, 2 for	Wednesday etc.

       o "if (($year,$month,$day) =
	 Nth_Weekday_of_Month_Year($year,$month,$dow,$n))"

	 This function calculates the date of the "$n"th day of	week "$dow" in
	 the given month "$month" and year "$year"; such as, for example, the
	 3rd Thursday of a given month and year.

	 This can be used to send a notification mail to the members of	a
	 group which meets regularly on	every 3rd Thursday of a	month, for
	 instance.

	 (See the section "RECIPES" near the end of this document for a	code
	 snippet to actually do	so.)

	 "$year" must be greater than or equal to "1", "$month"	must lie in
	 the range "1" to "12",	"$dow" must lie	in the range "1" to "7"	and
	 "$n" must lie in the range "1"	to "5",	or a fatal error (with
	 appropriate error message) occurs.

	 The function returns an empty list when the 5th of a given day	of
	 week does not exist in	the given month	and year.

       o "($year,$week,$dow) = Standard_to_Business($year,$month,$day);"

	 This function converts	a given	date from standard notation (year,
	 month,	day (of	month))	to business notation (year, week, day of
	 week).

       o "($year,$month,$day) =	Business_to_Standard($year,$week,$dow);"

	 This function converts	a given	date from business notation (year,
	 week, day of week) to standard	notation (year,	month, day (of
	 month)).

       o "$Dd =	Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);"

	 This function returns the difference in days between the two given
	 dates.

	 The result is positive	if the two dates are in	chronological order,
	 i.e., if date #1 comes	chronologically	BEFORE date #2,	and negative
	 if the	order of the two dates is reversed.

	 The result is zero if the two dates are identical.

       o "($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1,
	 $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"

	 This function returns the difference in days, hours, minutes and
	 seconds between the two given dates with times.

	 All four return values	will be	positive if the	two dates are in
	 chronological order, i.e., if date #1 comes chronologically BEFORE
	 date #2, and negative (in all four return values!) if the order of
	 the two dates is reversed.

	 This is so that the two functions ""Delta_DHMS()"" and
	 ""Add_Delta_DHMS()"" (description see further below) are
	 complementary,	i.e., mutually inverse:

	   Add_Delta_DHMS(@date1,@time1, Delta_DHMS(@date1,@time1, @date2,@time2))

	 yields	""(@date2,@time2)"" again, whereas

	   Add_Delta_DHMS(@date2,@time2,
	       map(-$_,	Delta_DHMS(@date1,@time1, @date2,@time2)))

	 yields	""(@date1,@time1)"", and

	   Delta_DHMS(@date1,@time1, Add_Delta_DHMS(@date1,@time1, @delta))

	 yields	"@delta" again.

	 The result is zero (in	all four return	values)	if the two dates and
	 times are identical.

       o "($Dy,$Dm,$Dd)	= Delta_YMD($year1,$month1,$day1,
	 $year2,$month2,$day2);"

	 This function returns the vector

	     ( $year2 -	$year1,	$month2	- $month1, $day2 - $day1 )

	 This is called	the "one-by-one" semantics.

	 Adding	the result of this function to the first date always yields
	 the second date again,	and adding the negative	result (where the
	 signs of all elements of the result vector have been flipped) to the
	 second	date gives the first date. See also the	description of the
	 function "Add_Delta_YMD()" further below.

	 Example:

	   (6,2,-30) ==	Delta_YMD(1996,1,31, 2002,3,1]);

	   [1996,1,31] + ( 6, 2,-30) = [2002,3,	1]
	   [2002,3, 1] + (-6,-2, 30) = [1996,1,31]

	 An error occurs if any	of the two given dates is invalid.

       o "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds)	= Delta_YMDHMS($year1,$month1,$day1,
	 $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);"

	 This function is based	on the function	"Delta_YMD()" above but
	 additionally calculates the time difference. When a carry over	from
	 the time difference occurs, the value of "$D_d" is adjusted
	 accordingly, thus giving the correct total date/time difference.

	 Arguments are expected	to be in chronological order to	yield a
	 (usually) positive result.

	 In any	case, adding the result	of this	function to the	first
	 date/time value ("$year1,$month1,$day1," "$hour1,$min1,$sec1")	always
	 gives the second date/time value ("$year2,$month2,$day2,"
	 "$hour2,$min2,$sec2") again, and adding the negative result (with the
	 signs of all elements of the result vector flipped) to	the second
	 date/time value gives the first date/time value.

	 See the function "Add_Delta_YMDHMS()" further below for adding	a
	 date/time value and a date/time difference.

	 An error occurs if any	of the given two date/time values is invalid.

       o "($Dy,$Dm,$Dd)	= N_Delta_YMD($year1,$month1,$day1,
	 $year2,$month2,$day2);"

	 This function returns the difference between the two given dates in a
	 more intuitive	way (as	far as possible	- more on that see a bit
	 further below)	than the function "Delta_YMD()"	described above.

	 The "N" which precedes	its name is meant to signify "new" or
	 "normalized".

	 This function is loosely based	on recipe #17 b) (see the section
	 "RECIPES" below near the end of this document).

	 However, the code of recipe #17 b) actually does not treat positive
	 and negative values symmetrically and consistently.

	 This new routine does.

	 The return values of this function are	guaranteed to all have the
	 same sign (or to be zero). This is why	this function is called
	 "normalized".

	 Moreover, the results are guaranteed to be "minimal", in the sense
	 that "|$Dm| < 12" and "|$Dd| <	31" (which is equivalent to $Dm	lying
	 in the	range "[-11..+11]" and $Dd lying in the	range "[-30..+30]").

	 When the results are applied (i.e., added) to the first given date in
	 a left-to-right order,	the second given date is guaranteed to be
	 obtained, provided that intermediary results are truncated, as	done
	 by the	function "Add_Delta_YM()" (see further below), i.e., that
	 invalid intermediate dates such as e.g. [2009,2,31] will
	 automatically be transformed into [2009,2,28] (and not	"wrapped" into
	 the next month, e.g. to [2009,3,3]).

	 This is called	the "left-to-right with	truncation" semantics.

	 Note that reversing the order of the given dates and reversing	the
	 sign of each of the result values will	not always add up.

	 Consider the dates [2008,2,29]	and [2009,2,1]:	their difference is
	 (0,11,3) ([2008,2,29] plus 11 months is [2009,1,29], which plus 3
	 days is [2009,2,1]), but the difference between [2009,2,1] and
	 [2008,2,29] is	(0,-11,-1), and	not (0,-11,-3) ([2009,2,1] minus 11
	 months	is [2008,3,1], which minus one day is [2008,2,29]).

	 Another example: The difference between [1996,2,29] and [1997,2,28]
	 is (1,0,0) (observe the truncation of the invalid date	[1997,2,29] to
	 [1997,2,28] here!), whereas the difference between [1997,2,28]	and
	 [1996,2,29] is	(0,-11,-28) ([1997,2,28] minus 11 months is
	 [1996,3,28], which minus 28 days is not [1996,3,0] but	of course
	 [1996,2,29]).

	 "Benign" examples such	as for instance	the difference between
	 [1964,1,3] and	[2009,9,10] are	completely symmetrical:	The difference
	 in this example is (45,8,7), whereas the difference between
	 [2009,9,10] and [1964,1,3] is (-45,-8,-7), as would normally be
	 expected. In this example, the	result is also the same	as the one
	 returned by "Delta_YMD()".

	 All these counter-intuitive effects are due to	the fact that months
	 (and due to leap years, also years) do	not correspond to a fixed
	 number	of days, so the	semantics of "plus one month" or "plus one
	 year" are in fact undefined.

	 The present function is an attempt to provide a definition which is
	 intuitive most	of the time, and at least consistent the rest of the
	 time.

	 Other definitions are of course possible, but most often lead to
	 contradictions	(e.g., the results and the given first date do not add
	 up to the second given	date).

	 See the file "datecalc.pl" in the "examples" subdirectory of this
	 distribution for a way	to play	around with this function, or go to
	 http://www.engelschall.com/u/sb/datecalc/ for the online version.

	 An error occurs if any	of the two given dates is invalid, or if any
	 intermediate result leads to an invalid date (this does not apply to
	 truncation, however, as explained above).

       o "($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) =
	 N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1,
	 $year2,$month2,$day2, $hour2,$min2,$sec2);"

	 This function essentially does	the same as the	function
	 "N_Delta_YMD()" described immediately above, except that also the
	 difference in hours, minutes and seconds is taken into	account.

	 This function is loosely based	on recipe #17 a) (see the section
	 "RECIPES" below near the end of this document).

	 However, the code of recipe #17 a) actually does not treat positive
	 and negative values symmetrically and consistently.

	 This new routine does.

	 The return values of this function (including the time	differences)
	 are guaranteed	to all have the	same sign (or to be zero). This	is the
	 reason	for the	"N" that precedes the name of this function, which is
	 intended to mean "normalized" (or "new").

	 Moreover, the results are guaranteed to be "minimal", in the sense
	 that "|$D_m| <	12", "|$D_d| < 31", "|$Dhh| < 24", "|$Dmm| < 60" and
	 "|$Dss| < 60" (which is equivalent to $D_m lying in the range
	 "[-11..+11]", $D_d lying in the range "[-30..+30]", $Dhh lying	in the
	 range "[-23..+23]", and $Dmm and $Dss both lying in the range
	 "[-59..+59]").

       o "($Dd,$Dh,$Dm,$Ds) = Normalize_DHMS($Dd,$Dh,$Dm,$Ds);"

	 This function takes four arbitrary values for days, hours, minutes
	 and seconds (which may	have different signs) and renormalizes them so
	 that the values for hours, minutes and	seconds	will lie in the	ranges
	 "[-23..23]", "[-59..59]" and "[-59..59]", respectively, and so	that
	 all four values have the same sign (or	are zero).

	 The given values are left untouched, i.e., unchanged.

       o "($year,$month,$day) =	Add_Delta_Days($year,$month,$day, $Dd);"

	 This function has two principal uses:

	 First,	it can be used to calculate a new date,	given an initial date
	 and an	offset (which may be positive or negative) in days, in order
	 to answer questions like "today plus 90 days -- which date gives
	 that?".

	 (In order to add a weeks offset, simply multiply the weeks offset
	 with "7" and use that as your days offset.)

	 Second, it can	be used	to convert the canonical representation	of a
	 date, i.e., the number	of that	day (where counting starts at the 1st
	 of January in 1A A.D.), back into a date given	as year, month and
	 day.

	 Because counting starts at "1", you will actually have	to subtract
	 "1" from the canonical	date in	order to get back the original date:

	   $canonical =	Date_to_Days($year,$month,$day);

	   ($year,$month,$day) = Add_Delta_Days(1,1,1, $canonical - 1);

	 Moreover, this	function is the	inverse	of the function
	 ""Delta_Days()"":

	   Add_Delta_Days(@date1, Delta_Days(@date1, @date2))

	 yields	"@date2" again,	whereas

	   Add_Delta_Days(@date2, -Delta_Days(@date1, @date2))

	 yields	"@date1", and

	   Delta_Days(@date1, Add_Delta_Days(@date1, $delta))

	 yields	"$delta" again.

       o "($year,$month,$day, $hour,$min,$sec) =
	 Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);"

	 This function serves to add a days, hours, minutes and	seconds	offset
	 to a given date and time, in order to answer questions	like "today
	 and now plus 7	days but minus 5 hours and then	plus 30	minutes, what
	 date and time gives that?":

	   ($y,$m,$d,$H,$M,$S) = Add_Delta_DHMS(Today_and_Now(), +7,-5,+30,0);

       o "($year,$month,$day) =	Add_Delta_YM($year,$month,$day,	$Dy,$Dm);"

	 This function can be used to add a year and/or	month offset to	a
	 given date.

	 In contrast to	the function described immediately below
	 (""Add_Delta_YMD()""),	this function does no "wrapping" into the next
	 month if the day happens to lie outside the valid range for the
	 resulting year	and month (after adding	the year and month offsets).
	 Instead, it simply truncates the day to the last possible day of the
	 resulting month.

	 Examples:

	 Adding	an offset of 0 years, 1	month to the date [1999,1,31] would
	 result	in the (invalid) date [1999,2,31]. The function	replaces this
	 result	by the (valid) date [1999,2,28].

	 Adding	an offset of 1 year, 1 month to	the same date [1999,1,31] as
	 above would result in the (still invalid) date	[2000,2,31]. The
	 function replaces this	result by the valid date [2000,2,29] (because
	 2000 is a leap	year).

	 Note that the year and	month offsets can be negative, and that	they
	 can have different signs.

	 If you	want to	additionally add a days	offset,	use the	function
	 ""Add_Delta_Days()"" before or	after calling ""Add_Delta_YM()"":

	   @date2 = Add_Delta_Days( Add_Delta_YM(@date1, $Dy,$Dm), $Dd );
	   @date2 = Add_Delta_YM( Add_Delta_Days(@date1, $Dd), $Dy,$Dm );

	 Note that your	result may depend on the order in which	you call these
	 two functions!

	 Consider the date [1999,2,28] and the offsets 0 years,	1 month	and 1
	 day:

	 [1999,2,28] plus one month is [1999,3,28], plus one day is
	 [1999,3,29]. [1999,2,28] plus one day is [1999,3,1], plus one month
	 is [1999,4,1].

	 (Which	is also	the reason why the ""Add_Delta_YM()"" function does
	 not allow to add a days offset, because this would actually require
	 TWO functions:	One for	adding the days	offset BEFORE and one for
	 adding	it AFTER applying the year/month offsets.)

	 An error occurs if the	initial	date is	not valid.

	 Note that ""Add_Delta_YM( Add_Delta_YM(@date, $Dy,$Dm), -$Dy,-$Dm
	 );"" will not,	in general, return the original	date "@date" (consider
	 the examples given above!).

       o "($year,$month,$day) =	Add_Delta_YMD($year,$month,$day,
	 $Dy,$Dm,$Dd);"

	 This function serves to add a years, months and days offset to	a
	 given date.

	 (In order to add a weeks offset, simply multiply the weeks offset
	 with "7" and add this number to your days offset.)

	 Note that the three offsets for years,	months and days	are applied
	 independently from each other.	This also allows them to have
	 different signs.

	 The years and months offsets are applied first, and the days offset
	 is applied last.

	 If the	resulting date happens to fall on a day	after the end of the
	 resulting month, like the 32nd	of April or the	30th of	February, then
	 the date is simply counted forward into the next month	(possibly also
	 into the next year) by	the number of excessive	days (e.g., the	32nd
	 of April will become the 2nd of May).

	 BEWARE	that this behaviour differs from that of previous versions of
	 this module! In previous versions, the	day was	simply truncated to
	 the maximum number of days in the resulting month.

	 If you	want the previous behaviour, use the new function
	 ""Add_Delta_YM()"" (described immediately above) plus the function
	 ""Add_Delta_Days()"" instead.

	 BEWARE	also that because a year and a month offset is not equivalent
	 to a fixed number of days, the	transformation performed by this
	 function is NOT ALWAYS	REVERSIBLE!

	 This is in contrast to	the functions ""Add_Delta_Days()"" and
	 ""Add_Delta_DHMS()"", which are fully and truly reversible (with the
	 help of the functions ""Delta_Days()""	and ""Delta_DHMS()"", for
	 instance).

	 Note that for this same reason,

	   @date = Add_Delta_YMD(
		   Add_Delta_YMD(@date,	$Dy,$Dm,$Dd), -$Dy,-$Dm,-$Dd);

	 will in general NOT return the	initial	date "@date", even though

	   @date2 = Add_Delta_YMD( @date1, Delta_YMD(@date1, @date2) );

	 will always return the	second date "@date2", and

	   @date1 = Add_Delta_YMD( @date2, map(-$_, Delta_YMD(@date1, @date2)) );

	 which is the same as

	   @date1 = Add_Delta_YMD( @date2, Delta_YMD(@date2, @date1) );

	 will always return the	first date "@date1".

	 Examples:

	   [1996,1,31] + ( 6, 1,-2) = [2002,3,1]
	   [2002,3, 1] + (-6,-1, 2) = [1996,2,3] # EXPECTED: [1996,1,31]

	   (6,2,-30) ==	Delta_YMD(1996,1,31, 2002,3,1);

	   [1996,1,31] + ( 6, 2,-30) = [2002,3,	1]
	   [2002,3, 1] + (-6,-2, 30) = [1996,1,31] # OK

	   (6,1,-2) == Delta_YMD(1996,2,3, 2002,3,1);

	   [1996,2,3] +	( 6, 1,-2) = [2002,3,1]
	   [2002,3,1] +	(-6,-1,	2) = [1996,2,3]	# OK

	 Note that this	is NOT a program bug but NECESSARILY so, because of
	 the variable lengths of years and months, and hence because of	the
	 ambiguity of the difference between two dates in terms	of years,
	 months	and days, i.e.,	the fact that the difference between two dates
	 can be	expressed in more than one way:

	   [1996,1,31] + (6,1, -2) = [2002,3,1]
	   [1996,1,31] + (6,2,-30) = [2002,3,1]

       o "($year,$month,$day, $hour,$min,$sec) =
	 Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec, $D_y,$D_m,$D_d,
	 $Dh,$Dm,$Ds);"

	 Same as the function above, except that a time	offset may be given in
	 addition to the year, month and day offset.

       o "($year,$month,$day) =	Add_N_Delta_YMD($year,$month,$day,
	 $Dy,$Dm,$Dd);"

	 This function is actually a shortcut for applying the function
	 "Add_Delta_YM()" first, followed by the function "Add_Delta_Days()",
	 i.e., this function does exactly the same as

	  ($year,$month,$day) =	Add_Delta_Days(	Add_Delta_YM($year,$month,$day,$Dy,$Dm), $Dd );

	 Beware	that, if necessary, the	function "Add_Delta_YM()" truncates
	 the resulting day of the month	to the largest allowable value for
	 that month, i.e., the (invalid) result	[2009,2,31] is automatically
	 transformed into [2009,2,28].

	 For more details on this truncation, see the description of the
	 function "Add_Delta_YM()" further above.

	 This function is meant	to be complementary with the function
	 "N_Delta_YMD()" described further above.

	 This means that it is guaranteed that the result returned by

	   Add_N_Delta_YMD( @date1, N_Delta_YMD(@date1,	@date2)	);

	 is always identical with the given date "@date2".

	 Note however that unlike with function	"Add_Delta_YMD()", the reverse
	 is not	true here, i.e.,

	   ($Dy,$Dm,$Dd) = N_Delta_YMD(@date1,@date2);
	   @date = Add_N_Delta_YMD(@date2, -$Dy,-$Dm,-$Dd);

	 will NOT always return	the initial date "@date1".

	 Example:

	   (0,11,3) == N_Delta_YMD(2008,2,29, 2009,2,1);

	   [2008,2,29] + (0, 11, 3) = [2009,2, 1]
	   [2009,2, 1] + (0,-11,-3) = [2008,2,27] # EXPECTED: [2008,2,29]

       o "($year,$month,$day, $hour,$min,$sec) =
	 Add_N_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec,
	 $D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss);"

	 This function essentially does	the same as the	function
	 "Add_N_Delta_YMD()" described immediately above, except that also the
	 difference in hours, minutes and seconds is taken into	account.

       o "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	 System_Clock([$gmt]);"

	 If your operating system supports the corresponding system calls
	 (""time()"" and ""localtime()"" or ""gmtime()""), this	function will
	 return	the information	provided by your system	clock, i.e., the
	 current date and time,	the number of the day of year, the number of
	 the day of week and a flag signaling whether daylight savings time is
	 currently in effect or	not.

	 The ranges of values returned (and their meanings) are	as follows:

		 $year	 :   1970..2038	(or more)  [Unix etc.]
		 $year	 :   1904..2040		   [MacOS Classic]

		 $month	 :   1..12
		 $day	 :   1..31
		 $hour	 :   0..23
		 $min	 :   0..59
		 $sec	 :   0..59    (0..61 on	some systems)
		 $doy	 :   1..366
		 $dow	 :   1..7
		 $dst	 :  -1..1

	 "$doy"	is the day of year, sometimes also referred to as the "julian
	 date",	which starts at	"1" and	goes up	to the number of days in that
	 year.

	 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
	 so on until "7" for Sunday.

	 The daylight savings time flag	("$dst") will be ""-1""	if this
	 information is	not available on your system, "0" for no daylight
	 savings time (i.e., winter time) and "1" when daylight	savings	time
	 is in effect.

	 If your operating system does not provide the necessary system	calls,
	 calling this function will result in a	fatal "not available on	this
	 system" error message.

	 If you	want to	handle this exception yourself,	use ""eval"" as
	 follows:

	   eval	{ ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	     System_Clock(); };

	   if ($@)
	   {
	       # Handle	missing	system clock
	       # (For instance,	ask user to enter this information manually)
	   }

	 Note that curlies ("{"	and "}") are used here to delimit the
	 statement to be "eval"ed (which is the	way to catch exceptions	in
	 Perl),	and not	quotes (which is a way to evaluate Perl	expressions at
	 runtime).

	 If the	optional (boolean) input parameter "$gmt" is given, a "true"
	 value ("1") will cause	""gmtime()"" to	be used	instead	of
	 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
	 or UTC) instead of local time.

       o "($year,$month,$day) =	Today([$gmt]);"

	 This function returns a subset	of the values returned by the function
	 ""System_Clock()"" (see above for details), namely the	current	year,
	 month and day.

	 A fatal "not available	on this	system"	error message will appear if
	 the corresponding system calls	are not	supported by your current
	 operating system.

	 If the	optional (boolean) input parameter "$gmt" is given, a "true"
	 value ("1") will cause	""gmtime()"" to	be used	instead	of
	 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
	 or UTC) instead of local time.

       o "($hour,$min,$sec) = Now([$gmt]);"

	 This function returns a subset	of the values returned by the function
	 ""System_Clock()"" (see above for details), namely the	current	time
	 (hours, minutes and full seconds).

	 A fatal "not available	on this	system"	error message will appear if
	 the corresponding system calls	are not	supported by your current
	 operating system.

	 If the	optional (boolean) input parameter "$gmt" is given, a "true"
	 value ("1") will cause	""gmtime()"" to	be used	instead	of
	 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
	 or UTC) instead of local time.

       o "($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);"

	 This function returns a subset	of the values returned by the function
	 ""System_Clock()"" (see above for details), namely the	current	date
	 (year,	month, day) and	time (hours, minutes and full seconds).

	 A fatal "not available	on this	system"	error message will appear if
	 the corresponding system calls	are not	supported by your current
	 operating system.

	 If the	optional (boolean) input parameter "$gmt" is given, a "true"
	 value ("1") will cause	""gmtime()"" to	be used	instead	of
	 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
	 or UTC) instead of local time.

       o "$year	= This_Year([$gmt]);"

	 This function returns the current year, according to local time.

	 A fatal "not available	on this	system"	error message will appear if
	 the corresponding system calls	are not	supported by your current
	 operating system.

	 If the	optional (boolean) input parameter "$gmt" is given, a "true"
	 value ("1") will cause	""gmtime()"" to	be used	instead	of
	 ""localtime()"", internally, thus returning Greenwich Mean Time (GMT,
	 or UTC) instead of local time.	However, this will only	make a
	 difference within a few hours around New Year (unless you are on a
	 Pacific island, where this can	be almost 24 hours).

       o "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	 Gmtime([time]);"

	 This is Date::Calc's equivalent of Perl's built-in "gmtime()"
	 function.  See	also "gmtime" in perlfunc(1).

	 With the optional argument "time" (i.e., seconds since	the epoch),
	 this function will return the corresponding values for	that
	 particular time (instead of the current time when this	parameter is
	 omitted).

	 The ranges of values returned (and their meanings) are	as follows:

		 $year	 :   1970..2038	(or more)  [Unix etc.]
		 $year	 :   1904..2040		   [MacOS Classic]

		 $month	 :   1..12
		 $day	 :   1..31
		 $hour	 :   0..23
		 $min	 :   0..59
		 $sec	 :   0..59
		 $doy	 :   1..366
		 $dow	 :   1..7
		 $dst	 :  -1..1

	 "$doy"	is the day of year, sometimes also referred to as the "julian
	 date",	which starts at	"1" and	goes up	to the number of days in that
	 year.

	 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
	 so on until "7" for Sunday.

	 The daylight savings time flag	("$dst") will be ""-1""	if this
	 information is	not available on your system, "0" for no daylight
	 savings time (i.e., winter time) and "1" when daylight	savings	time
	 is in effect.

	 A fatal "time out of range" error will	occur if the given time	value
	 is out	of range "[0..(~0>>1)]".

	 If the	time value is omitted, the "time()" function is	called
	 instead, internally.

       o "($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) =
	 Localtime([time]);"

	 This is Date::Calc's equivalent of Perl's built-in "localtime()"
	 function.  See	also "localtime" in perlfunc(1).

	 The ranges of values returned (and their meanings) are	as follows:

		 $year	 :   1970..2038	(or more)  [Unix etc.]
		 $year	 :   1904..2040		   [MacOS Classic]

		 $month	 :   1..12
		 $day	 :   1..31
		 $hour	 :   0..23
		 $min	 :   0..59
		 $sec	 :   0..59
		 $doy	 :   1..366
		 $dow	 :   1..7
		 $dst	 :  -1..1

	 "$doy"	is the day of year, sometimes also referred to as the "julian
	 date",	which starts at	"1" and	goes up	to the number of days in that
	 year.

	 The day of week ("$dow") will be "1" for Monday, "2" for Tuesday and
	 so on until "7" for Sunday.

	 The daylight savings time flag	("$dst") will be ""-1""	if this
	 information is	not available on your system, "0" for no daylight
	 savings time (i.e., winter time) and "1" when daylight	savings	time
	 is in effect.

	 A fatal "time out of range" error will	occur if the given time	value
	 is out	of range "[0..(~0>>1)]".

	 If the	time value is omitted, the "time()" function is	called
	 instead, internally.

       o "$time	= Mktime($year,$month,$day, $hour,$min,$sec);"

	 This function converts	a date into a time value, i.e.,	into the
	 number	of seconds since whatever moment in time your system considers
	 to be the "epoch". On Unix and	most other systems this	is the number
	 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
	 this is the number of seconds since January 1st 1904 at midnight
	 (local	time).

	 The function is similar to the	"POSIX::mktime()" function (see
	 "mktime" in POSIX(1) for more details), but in	contrast to the
	 latter, it expects dates in the usual ranges used throughout this
	 module: The year 2001 stays year 2001,	and months are numbered	from 1
	 to 12.

	 A fatal "date out of range" error will	occur if the given date	cannot
	 be expressed in terms of seconds since	the epoch (this	happens	for
	 instance when the date	lies before the	epoch, or if it	is later than
	 19-Jan-2038A 03:14:07A	GMT on 32A bit Unix systems, or	later than
	 06-Feb-2040A 06:28:15 (local time) on a Macintosh with	MacOS
	 Classic).

	 Just like the "POSIX::mktime()" function, this	function uses the
	 "mktime()" system call, internally.

	 This means that the given date	and time is considered to be in	local
	 time, and that	the value returned by this function will depend	on
	 your machine's	local settings such as the time	zone, whether daylight
	 savings time is (or was, at the time) in effect, and the system clock
	 itself.

	 BEWARE	that "mktime()"	does not always	return the same	time value as
	 fed into "localtime()", when you feed the output of "localtime()"
	 back into "mktime()", on some systems!

	 I.e., ""Mktime((Localtime($time))[0..5])"" will not always return the
	 same value as given in	"$time"!

       o "($D_y,$D_m,$D_d, $Dh,$Dm,$Ds,	$dst) =	Timezone([time]);"

	 This function returns the difference between ""localtime(time)"" and
	 ""gmtime(time)"", which is the	timezone offset	in effect for the
	 current location and the given	""time"".

	 This offset is	positive if you	are located to the east	of Greenwich,
	 and is	usually	negative (except during	daylight savings time, in some
	 locations) if you are located to the west of Greenwich.

	 Note that this	offset is influenced by	all of the relevant system
	 settings and parameters on your machine; such as locales, environment
	 variables (e.g. ""TZ"") and the system	clock itself. See the relevant
	 documentation on your system for more details.

	 If the	""time"" is omitted, the ""time()"" function will be called
	 automatically,	internally (similar to the built-in functions
	 ""localtime()"" and ""gmtime()"" in Perl).

	 A fatal "time out of range" error will	occur if the given time	value
	 is out	of range "[0..(~0>>1)]".

	 The last item of the returned list is a flag which indicates whether
	 daylight savings time is currently in effect. This flag is negative
	 (-1) if this information is not available on your system. It is zero
	 (0) when daylight savings time	is off,	and positive (+1) when
	 daylight savings time is on.

	 Thus you can check very quickly whether daylight savings time is
	 currently in effect by	evaluating this	function in scalar context (in
	 scalar	context, Perl returns the last item of a list):

	   if (scalar Timezone > 0) { #	yes, daylight savings time

	 However, a slightly more efficient way	would be this:

	   if (scalar System_Clock > 0)	{ # yes, daylight savings time

       o "$time	= Date_to_Time($year,$month,$day, $hour,$min,$sec);"

	 This function is a replacement	for the	BSD function "timegm()"	(which
	 is not	available on all Unix systems),	which converts a given date
	 and time into a time value, i.e., into	the number of seconds since
	 whatever moment in time your system considers to be the "epoch". On
	 Unix and most other systems this is the number	of seconds since
	 January 1st 1970 at midnight (GMT). On	MacOS Classic this is the
	 number	of seconds since January 1st 1904 at midnight (local time).

	 Under Unix, the date and time are considered to be in UTC ("Universal
	 Time Coordinated", and	so is the resulting time value.

	 UTC is	almost the same	as GMT (or "Greenwich Mean Time"), except that
	 UTC has leap seconds (in order	to account for small variations	in the
	 rotation of the earth,	for instance), whereas GMT does	not.

	 Under MacOS Classic, however, both input and output are considered to
	 be in local time.

	 The ranges of year and	month follow the same rules as throughout the
	 rest of this module (and not the contorted rules of its Unix
	 equivalent), i.e., the	year "2001" stays "2001" and the month ranges
	 from 1	to 12.

	 A fatal "date out of range" error will	occur if the given date	cannot
	 be expressed in terms of seconds since	the epoch (this	happens	for
	 instance when the date	lies before the	epoch, or if it	is later than
	 19-Jan-2038A 03:14:07A	GMT on 32A bit Unix systems, or	later than
	 06-Feb-2040A 06:28:15 (local time) on a Macintosh with	MacOS
	 Classic).

	 This function should be very fast, because it is implemented in a
	 very straightforward manner and doesn't use any internal system
	 calls.

	 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
	 guaranteed to be complementary, i.e., that
	 ""Date_to_Time(Time_to_Date($time))"" and
	 ""Time_to_Date(Date_to_Time($year,$month,$day,	$hour,$min,$sec))""
	 will always return the	initial	values.

       o "($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);"

	 This function is an alternative to the	POSIX "gmtime()" function (and
	 its built-in Perl equivalent),	which converts a given time value into
	 the corresponding date	and time. The given time value must be the
	 number	of seconds since whatever moment in time your system considers
	 to be the "epoch". On Unix and	most other systems this	is the number
	 of seconds since January 1st 1970 at midnight (GMT). On MacOS Classic
	 this is the number of seconds since January 1st 1904 at midnight
	 (local	time).

	 Under Unix, the given time value is considered	to be in UTC
	 ("Universal Time Coordinated",	and so is the resulting	date and time.

	 UTC is	almost the same	as GMT (or "Greenwich Mean Time"), except that
	 UTC has leap seconds (in order	to account for small variations	in the
	 rotation of the earth,	for instance), whereas GMT does	not.

	 Under MacOS Classic, however, both input and output are considered to
	 be in local time.

	 If the	input value ""time"" is	omitted, the ""time()""	function will
	 be called automatically, internally (similar to the built-in
	 functions ""localtime()"" and ""gmtime()"" in Perl).

	 A fatal "time out of range" error will	occur if the given time	value
	 is negative.

	 This function should be very fast, because it is implemented in a
	 very straightforward manner and doesn't use any internal system calls
	 (except for "time()", if the input value is omitted).

	 Moreover, the functions "Date_to_Time()" and "Time_to_Date()" are
	 guaranteed to be complementary, i.e., that
	 ""Date_to_Time(Time_to_Date($time))"" and
	 ""Time_to_Date(Date_to_Time($year,$month,$day,	$hour,$min,$sec))""
	 will always return the	initial	values.

       o "($year,$month,$day) =	Easter_Sunday($year);"

	 This function calculates the date of Easter Sunday for	all years in
	 the range from	1583 to	2299 (all other	year numbers will result in a
	 fatal "year out of range" error message) using	the method known as
	 the "Gaussian Rule".

	 Some related christian	feast days which depend	on the date of Easter
	 Sunday:

	   Carnival Monday / Rosenmontag / Veille du Mardi Gras	  =  -48 days
	   Mardi Gras /	Karnevalsdienstag / Mardi Gras		  =  -47 days
	   Ash Wednesday / Aschermittwoch / Mercredi des Cendres  =  -46 days
	   Palm	Sunday / Palmsonntag / Dimanche	des Rameaux	  =   -7 days
	   Easter Friday / Karfreitag /	Vendredi Saint		  =   -2 days
	   Easter Saturday / Ostersamstag / Samedi de Paques	  =   -1 day
	   Easter Monday / Ostermontag / Lundi de Paques	  =   +1 day
	   Ascension of	Christ / Christi Himmelfahrt / Ascension  =  +39 days
	   Whitsunday /	Pfingstsonntag / Dimanche de Pentecote	  =  +49 days
	   Whitmonday /	Pfingstmontag /	Lundi de Pentecote	  =  +50 days
	   Feast of Corpus Christi / Fronleichnam / Fete-Dieu	  =  +60 days

	 Use the offsets shown above to	calculate the date of the
	 corresponding feast day as follows:

	   ($year,$month,$day) = Add_Delta_Days(Easter_Sunday($year), $offset));

       o "if ($month = Decode_Month($string[,$lang]))"

	 This function takes a string as its argument, which should contain
	 the name of a month in	the given or currently selected	language (see
	 further below for details about the multi-language support of this
	 package), or any uniquely identifying abbreviation of a month's name
	 (i.e.,	the first few letters),	and returns the	corresponding number
	 (1..12) upon a	successful match, or "0" otherwise (therefore, the
	 return	value can also be used as the conditional expression in	an
	 "if" statement).

	 Note that the input string may	not contain any	other characters which
	 do not	pertain	to the month's name, especially	no leading or trailing
	 whitespace.

	 Note also that	matching is performed in a case-insensitive manner
	 (this may depend on the "locale" setting on your current system,
	 though!)

	 With "1" ("English") as the given language, the following examples
	 will all return the value "9":

	   $month = Decode_Month("s",1);
	   $month = Decode_Month("Sep",1);
	   $month = Decode_Month("septemb",1);
	   $month = Decode_Month("September",1);

       o "if ($dow = Decode_Day_of_Week($string[,$lang]))"

	 This function takes a string as its argument, which should contain
	 the name of a day of week in the given	or currently selected language
	 (see further below for	details	about the multi-language support of
	 this package),	or any uniquely	identifying abbreviation of the	name
	 of a day of week (i.e., the first few letters), and returns the
	 corresponding number (1..7) upon a successful match, or "0" otherwise
	 (therefore, the return	value can also be used as the conditional
	 expression in an "if" statement).

	 Note that the input string may	not contain any	other characters which
	 do not	pertain	to the name of the day of week,	especially no leading
	 or trailing whitespace.

	 Note also that	matching is performed in a case-insensitive manner
	 (this may depend on the "locale" setting on your current system,
	 though!)

	 With "1" ("English") as the given language, the following examples
	 will all return the value "3":

	   $dow	= Decode_Day_of_Week("w",1);
	   $dow	= Decode_Day_of_Week("Wed",1);
	   $dow	= Decode_Day_of_Week("wednes",1);
	   $dow	= Decode_Day_of_Week("Wednesday",1);

       o "if ($lang = Decode_Language($string))"

	 This function takes a string as its argument, which should contain
	 the name of one of the	languages supported by this package (IN	THIS
	 VERY LANGUAGE ITSELF),	or any uniquely	identifying abbreviation of
	 the name of a language	(i.e., the first few letters), and returns its
	 corresponding internal	number (1..14 in the original distribution)
	 upon a	successful match, or "0" otherwise (therefore, the return
	 value can also	be used	as the conditional expression in an "if"
	 statement).

	 Note that the input string may	not contain any	other characters which
	 do not	pertain	to the name of a language, especially no leading or
	 trailing whitespace.

	 Note also that	matching is performed in a case-insensitive manner
	 (this may depend on the "locale" setting on your current system,
	 though!)

	 The original distribution supports the	following fourteen languages:

		     English			==>    1    (default)
		     FranA<section>ais	  (French)	 ==>	2
		     Deutsch	 (German)	==>    3
		     EspaA+-ol	   (Spanish)	  ==>	 4
		     PortuguAas	  (Portuguese)	 ==>	5
		     Nederlands	 (Dutch)	==>    6
		     Italiano	 (Italian)	==>    7
		     Norsk	 (Norwegian)	==>    8
		     Svenska	 (Swedish)	==>    9
		     Dansk	 (Danish)	==>   10
		     suomi	 (Finnish)	==>   11
		     Magyar	 (Hungarian)	==>   12
		     polski	 (Polish)	==>   13
		     Romaneste	 (Romanian)	==>   14

	 See the section "How to install additional languages" in the file
	 "INSTALL.txt" in this distribution for	how to add more	languages to
	 this package.

	 In the	original distribution (no other	languages installed), the
	 following examples will all return the	value "3":

	   $lang = Decode_Language("d");
	   $lang = Decode_Language("de");
	   $lang = Decode_Language("Deutsch");

	 Note that you may not be able to enter	the special international
	 characters in some of the languages' names over the keyboard directly
	 on some systems.

	 This should never be a	problem, though; just enter an abbreviation of
	 the name of the language consisting of	the first few letters up to
	 the character before the first	special	international character.

       o "if (($year,$month,$day) = Decode_Date_EU($string[,$lang]))"

	 This function scans a given string and	tries to parse any date	which
	 might be embedded in it.

	 The function returns an empty list if it can't	successfully extract a
	 valid date from its input string, or else it returns the date found.

	 The function accepts almost any format, as long as the	date is	given
	 in the	european order (hence its name)	day-month-year.

	 Thereby, zero or more NON-NUMERIC characters may PRECEDE the day and
	 FOLLOW	the year.

	 Moreover, zero	or more	NON-ALPHANUMERIC characters are	permitted
	 BETWEEN these three items (i.e., between day and month	and between
	 month and year).

	 The month may be given	either numerically (i.e., a number from	"1" to
	 "12"),	or alphanumerically, i.e., as the name of the month in the
	 given or currently selected language, or any uniquely identifying
	 abbreviation thereof.

	 (See further below for	details	about the multi-language support of
	 this package!)

	 If the	year is	given as one or	two digits only	(i.e., if the year is
	 less than 100), it is mapped to a "window" of +/- 50 years around the
	 current year, as described by the "Moving_Window()" function (see
	 further below).

	 If the	day, month and year are	all given numerically but WITHOUT any
	 delimiting characters between them, this string of digits will	be
	 mapped	to the day, month and year as follows:

			 Length:	Mapping:
			   3		  dmy
			   4		  dmyy
			   5		  dmmyy
			   6		  ddmmyy
			   7		  dmmyyyy
			   8		  ddmmyyyy

	 (Where	"d" stands for "day", "m" stands for "month" and "y" stands
	 for "year".)

	 All other strings consisting purely of	digits (without	any
	 intervening delimiters) are rejected, i.e., not recognized.

	 Examples:

	   "3.1.64"
	   "3 1	64"
	   "03.01.64"
	   "03/01/64"
	   "3. Jan 1964"
	   "Birthday: 3. Jan '64 in Backnang/Germany"
	   "03-Jan-64"
	   "3.Jan1964"
	   "3Jan64"
	   "030164"
	   "3ja64"
	   "3164"

	 Experiment! (See the corresponding example applications in the
	 "examples" subdirectory of this distribution in order to do so.)

       o "if (($year,$month,$day) = Decode_Date_US($string[,$lang]))"

	 This function scans a given string and	tries to parse any date	which
	 might be embedded in it.

	 The function returns an empty list if it can't	successfully extract a
	 valid date from its input string, or else it returns the date found.

	 The function accepts almost any format, as long as the	date is	given
	 in the	U.S. american order (hence its name) month-day-year.

	 Thereby, zero or more NON-ALPHANUMERIC	characters may PRECEDE and
	 FOLLOW	the month (i.e., precede the month and separate	it from	the
	 day which follows behind).

	 Moreover, zero	or more	NON-NUMERIC characters are permitted BETWEEN
	 the day and the year, as well as AFTER	the year.

	 The month may be given	either numerically (i.e., a number from	"1" to
	 "12"),	or alphanumerically, i.e., as the name of the month in the
	 given or currently selected language, or any uniquely identifying
	 abbreviation thereof.

	 (See further below for	details	about the multi-language support of
	 this package!)

	 If the	year is	given as one or	two digits only	(i.e., if the year is
	 less than 100), it is mapped to a "window" of +/- 50 years around the
	 current year, as described by the "Moving_Window()" function (see
	 further below).

	 If the	month, day and year are	all given numerically but WITHOUT any
	 delimiting characters between them, this string of digits will	be
	 mapped	to the month, day and year as follows:

			 Length:	Mapping:
			   3		  mdy
			   4		  mdyy
			   5		  mddyy
			   6		  mmddyy
			   7		  mddyyyy
			   8		  mmddyyyy

	 (Where	"m" stands for "month",	"d" stands for "day" and "y" stands
	 for "year".)

	 All other strings consisting purely of	digits (without	any
	 intervening delimiters) are rejected, i.e., not recognized.

	 If only the day and the year form a contiguous	string of digits, they
	 will be mapped	as follows:

			 Length:	Mapping:
			   2		  dy
			   3		  dyy
			   4		  ddyy
			   5		  dyyyy
			   6		  ddyyyy

	 (Where	"d" stands for "day" and "y" stands for	"year".)

	 Examples:

	   "1 3	64"
	   "01/03/64"
	   "Jan	3 '64"
	   "Jan	3 1964"
	   "===> January 3rd 1964 (birthday)"
	   "Jan31964"
	   "Jan364"
	   "ja364"
	   "1364"

	 Experiment! (See the corresponding example applications in the
	 "examples" subdirectory of this distribution in order to do so.)

       o "$year	= Fixed_Window($yy);"

	 This function applies a "fixed	window"	strategy to two-digit year
	 numbers in order to convert them into four-digit year numbers.

	 All other year	numbers	are passed through unchanged, except for
	 negative year numbers,	which cause the	function to return zero	("0")
	 instead.

	 Two-digit year	numbers	""yy"" below 70	are converted to ""20yy"",
	 whereas year numbers equal to or greater than 70 (but less than 100)
	 are converted to ""19yy"".

	 In the	original distribution of this package, the base	century	is set
	 to "1900" and the base	year to	"70" (which is a standard on UNIX
	 systems), but these constants (also called the	"epoch") can actually
	 be chosen at will (in the files "DateCalc.c" and "DateCalc.h")	at
	 compile time of this module.

       o "$year	= Moving_Window($yy);"

	 This function applies a "moving window" strategy to two-digit year
	 numbers in order to convert them into four-digit year numbers,
	 provided the necessary	system calls (system clock) are	available.
	 Otherwise the function	falls back to the "fixed window" strategy
	 described in the function above.

	 All other year	numbers	are passed through unchanged, except for
	 negative year numbers,	which cause the	function to return zero	("0")
	 instead.

	 Two-digit year	numbers	are mapped according to	a "window" of 50 years
	 in both directions (past and future) around the current year.

	 That is, two-digit year numbers are first mapped to the same century
	 as the	current	year. If the resulting year is smaller than the
	 current year minus 50,	then one more century is added to the result.
	 If the	resulting year is equal	to or greater than the current year
	 plus 50, then a century is subtracted from the	result.

       o "$date	= Compress($year,$month,$day);"

	 WARNING: This function	is legacy code,	its use	is deprecated!

	 This function encodes a date in 16 bits, which	is the value being
	 returned.

	 The encoding scheme is	as follows:

		     Bit number:    FEDCBA9 8765 43210
		     Contents:	    yyyyyyy mmmm ddddd

	 (Where	the "yyyyyyy" contain the number of the	year, "mmmm" the
	 number	of the month and "ddddd" the number of the day.)

	 The function returns "0" if the given input values do not represent a
	 valid date. Therefore,	the return value of this function can also be
	 used as the conditional expression in an "if" statement, in order to
	 check whether the given input values constitute a valid date).

	 Through this special encoding scheme, it is possible to COMPARE
	 compressed dates for equality and order (less than/greater than)
	 WITHOUT any previous DECODING!

	 Note however that contiguous dates do NOT necessarily have contiguous
	 compressed representations!

	 I.e., incrementing the	compressed representation of a date MAY	OR MAY
	 NOT yield a valid new date!

	 Note also that	this function can only handle dates within one
	 century.

	 This century can be chosen at will (at	compile	time of	this module)
	 by defining a base century and	year (also called the "epoch").	In the
	 original distribution of this package,	the base century is set	to
	 "1900"	and the	base year to "70" (which is standard on	UNIX systems).

	 This allows this function to handle dates from	"1970" up to "2069".

	 If the	given year is equal to,	say, "95", this	package	will
	 automatically assume that you really meant "1995" instead. However,
	 if you	specify	a year number which is SMALLER than 70,	like "64", for
	 instance, this	package	will assume that you really meant "2064".

	 You are not confined to two-digit (abbreviated) year numbers, though.

	 The function also accepts "full-length" year numbers, provided	that
	 they lie in the supported range (i.e.,	from "1970" to "2069", in the
	 original configuration	of this	package).

	 Note that this	function is maintained mainly for backward
	 compatibility,	and that its use is not	recommended.

       o "if (($century,$year,$month,$day) = Uncompress($date))"

	 WARNING: This function	is legacy code,	its use	is deprecated!

	 This function decodes dates that were encoded previously using	the
	 function ""Compress()"".

	 It returns the	century, year, month and day of	the date encoded in
	 "$date" if "$date" represents a valid date, or	an empty list
	 otherwise.

	 The year returned in "$year" is actually a two-digit year number
	 (i.e.,	the year number	taken modulo 100), and only the	expression
	 ""$century + $year"" yields the "full-length" year number (for
	 example, "1900	+ 95 = 1995").

	 Note that this	function is maintained mainly for backward
	 compatibility,	and that its use is not	recommended.

       o "if (check_compressed($date))"

	 WARNING: This function	is legacy code,	its use	is deprecated!

	 This function returns "true" ("1") if the given input value
	 constitutes a valid compressed	date, and "false" ("0")	otherwise.

	 Note that this	function is maintained mainly for backward
	 compatibility,	and that its use is not	recommended.

       o "$string = Compressed_to_Text($date[,$lang]);"

	 WARNING: This function	is legacy code,	its use	is deprecated!

	 This function returns a string	of fixed length	(always	9 characters
	 long) containing a textual representation of the compressed date
	 encoded in "$date".

	 This string has the form "dd-Mmm-yy", where "dd" is the two-digit
	 number	of the day, "Mmm" are the first	three letters of the name of
	 the month in the given	or currently selected language (see further
	 below for details about the multi-language support of this package),
	 and "yy" is the two-digit year	number (i.e., the year number taken
	 modulo	100).

	 If "$date" does not represent a valid date, the string	"??-???-??" is
	 returned instead.

	 Note that this	function is maintained mainly for backward
	 compatibility,	and that its use is not	recommended.

       o "$string = Date_to_Text($year,$month,$day[,$lang]);"

	 This function returns a string	containing a textual representation of
	 the given date	of the form "www dd-Mmm-yyyy", where "www" are the
	 first three letters of	the name of the	day of week in the given or
	 currently selected language, or a special abbreviation, if special
	 abbreviations have been defined for the given or currently selected
	 language (see further below for details about the multi-language
	 support of this package), "dd"	is the day (one	or two digits),	"Mmm"
	 are the first three letters of	the name of the	month in the given or
	 currently selected language, and "yyyy" is the	number of the year in
	 full length.

	 If the	given input values do not constitute a valid date, a fatal
	 "not a	valid date" error occurs.

	 (See the section "RECIPES" near the end of this document for a	code
	 snippet for how to print dates	in any format you like.)

       o "$string = Date_to_Text_Long($year,$month,$day[,$lang]);"

	 This function returns a string	containing a textual representation of
	 the given date	roughly	of the form "Wwwwww, dd	Mmmmmm yyyy", where
	 "Wwwwww" is the name of the day of week in the	given or currently
	 selected language (see	further	below for details about	the multi-
	 language support of this package), "dd" is the	day (one or two
	 digits), "Mmmmmm" is the name of the month in the given or currently
	 selected language, and	"yyyy" is the number of	the year in full
	 length.

	 The exact format of the output	string depends on the given or
	 currently selected language. In the original distribution of this
	 package, these	formats	are defined as follows:

	   1  English	 :  "Wwwwww, Mmmmmm ddth yyyy"
	   2  French	 :  "Wwwwww dd mmmmmm yyyy"
	   3  German	 :  "Wwwwww, den dd. Mmmmmm yyyy"
	   4  Spanish	 :  "Wwwwww, dd	de mmmmmm de yyyy"
	   5  Portuguese :  "Wwwwww, dia dd de mmmmmm de yyyy"
	   6  Dutch	 :  "Wwwwww, dd	mmmmmm yyyy"
	   7  Italian	 :  "Wwwwww, dd	Mmmmmm yyyy"
	   8  Norwegian	 :  "wwwwww, dd. mmmmmm	yyyy"
	   9  Swedish	 :  "wwwwww, dd	mmmmmm yyyy"
	  10  Danish	 :  "wwwwww, dd. mmmmmm	yyyy"
	  11  Finnish	 :  "wwwwww, dd. mmmmmmta yyyy"
	  12  Hungarian	 :  "dd. Mmmmmm	yyyy., wwwwww"
	  13  Polish	 :  "Wwwwww, dd	Mmmmmm yyyy"
	  14  Romanian	 :  "Wwwwww dd Mmmmmm yyyy"

	 (You can change these formats in the file "DateCalc.c"	before
	 building this module in order to suit your personal preferences.)

	 If the	given input values do not constitute a valid date, a fatal
	 "not a	valid date" error occurs.

	 In order to capitalize	the day	of week	at the beginning of the	string
	 in Norwegian, use
	 ""ucfirst(Date_to_Text_Long($year,$month,$day,8));"".

	 (See the section "RECIPES" near the end of this document for an
	 example on how	to print dates in any format you like.)

       o "$string = English_Ordinal($number);"

	 This function returns a string	containing the (english) abbreviation
	 of the	ordinal	number for the given (cardinal)	number "$number".

	 I.e.,

	     0	=>  '0th'    10	 =>  '10th'    20  =>  '20th'
	     1	=>  '1st'    11	 =>  '11th'    21  =>  '21st'
	     2	=>  '2nd'    12	 =>  '12th'    22  =>  '22nd'
	     3	=>  '3rd'    13	 =>  '13th'    23  =>  '23rd'
	     4	=>  '4th'    14	 =>  '14th'    24  =>  '24th'
	     5	=>  '5th'    15	 =>  '15th'    25  =>  '25th'
	     6	=>  '6th'    16	 =>  '16th'    26  =>  '26th'
	     7	=>  '7th'    17	 =>  '17th'    27  =>  '27th'
	     8	=>  '8th'    18	 =>  '18th'    28  =>  '28th'
	     9	=>  '9th'    19	 =>  '19th'    29  =>  '29th'

	 etc.

       o "$string = Calendar($year,$month[,$orthodox[,$lang]]);"

	 This function returns a calendar of the given month in	the given year
	 (somewhat similar to the UNIX ""cal"" command), in the	given or
	 currently selected language (see further below	for details about the
	 multi-language	support	of this	package).

	 Example:

	   print Calendar(1998,5);

	 This will print:

		    May	1998
	   Mon Tue Wed Thu Fri Sat Sun
			     1	 2   3
	     4	 5   6	 7   8	 9  10
	    11	12  13	14  15	16  17
	    18	19  20	21  22	23  24
	    25	26  27	28  29	30  31

	 If the	optional boolean parameter "$orthodox" is given	and true, the
	 calendar starts on Sunday instead of Monday.

       o "$string = Month_to_Text($month[,$lang]);"

	 This function returns the name	of the given month in the given	or
	 currently selected language (see further below	for details about the
	 multi-language	support	of this	package).

	 If the	given month lies outside of the	valid range from "1" to	"12",
	 a fatal "month	out of range" error will occur.

       o "$string = Day_of_Week_to_Text($dow[,$lang]);"

	 This function returns the name	of the given day of week in the	given
	 or currently selected language	(see further below for details about
	 the multi-language support of this package).

	 If the	given day of week lies outside of the valid range from "1" to
	 "7", a	fatal "day of week out of range" error will occur.

       o "$string = Day_of_Week_Abbreviation($dow[,$lang]);"

	 This function returns the special abbreviation	of the name of the
	 given day of week, IF such special abbreviations have been defined
	 for the given or currently selected language (see further below for
	 details about the multi-language support of this package).

	 (In the original distribution of this package,	this was only true for
	 Portuguese. Starting with version 5.1,	abbreviations for Polish have
	 also been introduced. Starting	with version 5.7, the abbreviations
	 for Portuguese	have been disabled. So Polish is currently the only
	 language to define such special abbreviations.)

	 If not, the first three letters of the	name of	the day	of week	in the
	 given or currently selected language are returned instead.

	 If the	given day of week lies outside of the valid range from "1" to
	 "7", a	fatal "day of week out of range" error will occur.

	 Currently, this table of special abbreviations	is only	used by	the
	 functions ""Date_to_Text()"" and ""Calendar()"", internally.

       o "$string = Language_to_Text($lang);"

	 This function returns the name	of any language	supported by this
	 package when the internal number representing that language is	given
	 as input.

	 The original distribution supports the	following fourteen languages:

		     1	 ==>   English			   (default)
		     2	 ==>   FranA<section>ais    (French)
		     3	 ==>   Deutsch	   (German)
		     4	 ==>   EspaA+-ol     (Spanish)
		     5	 ==>   PortuguAas   (Portuguese)
		     6	 ==>   Nederlands  (Dutch)
		     7	 ==>   Italiano	   (Italian)
		     8	 ==>   Norsk	   (Norwegian)
		     9	 ==>   Svenska	   (Swedish)
		    10	 ==>   Dansk	   (Danish)
		    11	 ==>   suomi	   (Finnish)
		    12	 ==>   Magyar	   (Hungarian)
		    13	 ==>   polski	   (Polish)
		    14	 ==>   Romaneste   (Romanian)

	 See the section "How to install additional languages" in the file
	 "INSTALL.txt" in this distribution for	how to add more	languages to
	 this package.

	 See the description of	the function ""Languages()"" further below to
	 determine how many languages are actually available in	a given
	 installation of this package.

       o "$lang	= Language();"

       o "Language($lang); # DEPRECATED"

       o "$oldlang = Language($newlang); # DEPRECATED"

	 This function can be used to determine	which language is currently
	 selected, and to change the selected language (this latter use	is
	 deprecated, because this global setting may cause conflicts between
	 threads or modules running concurrently).

	 Thereby, each language	has a unique internal number.

	 The original distribution contains the	following fourteen languages:

		     1	 ==>   English			   (default)
		     2	 ==>   FranA<section>ais    (French)
		     3	 ==>   Deutsch	   (German)
		     4	 ==>   EspaA+-ol     (Spanish)
		     5	 ==>   PortuguAas   (Portuguese)
		     6	 ==>   Nederlands  (Dutch)
		     7	 ==>   Italiano	   (Italian)
		     8	 ==>   Norsk	   (Norwegian)
		     9	 ==>   Svenska	   (Swedish)
		    10	 ==>   Dansk	   (Danish)
		    11	 ==>   suomi	   (Finnish)
		    12	 ==>   Magyar	   (Hungarian)
		    13	 ==>   polski	   (Polish)
		    14	 ==>   Romaneste   (Romanian)

	 See the section "How to install additional languages" in the file
	 "INSTALL.txt" in this distribution for	how to add more	languages to
	 this package.

	 See the description of	the function ""Languages()"" further below to
	 determine how many languages are actually available in	a given
	 installation of this package.

	 BEWARE	that in	order for your programs	to be portable,	you should
	 NEVER actually	use the	internal number	of a language in this package
	 EXPLICITLY, because the same number could mean	different languages on
	 different systems, depending on what languages	have been added	to any
	 given installation of this package.

	 Therefore, you	should always use a statement such as

	   Language(Decode_Language("Name_of_Language")); # DEPRECATED

	 or

	   DateCalc_Function(@parameters,Decode_Language("Name_of_Language")); # RECOMMENDED

	 to select the desired language, and

	   $language = Language_to_Text(Language());

	 or

	   $old_language = Language_to_Text(Language("Name_of_new_Language")); # DEPRECATED

	 to determine the (previously) selected	language.

	 If the	so chosen language is not available in the current
	 installation, this will result	in an appropriate error	message,
	 instead of silently using the wrong (a	random)	language (which	just
	 happens to have the same internal number in the other installation).

	 BEWARE	that when using	the function ""Language()"", the selected
	 language is a global setting, shared by all threads or	modules	you
	 might be running concurrently,	thus possibly causing conflicts
	 between them.

	 In order to avoid these conflicts, you	should NEVER use the function
	 ""Language()"", but should ALWAYS pass	a language number (as returned
	 by the	function ""Decode_Language()"")	to the functions which are
	 language-dependent, which are:

	 "Decode_Month()", "Decode_Day_of_Week()", "Compressed_to_Text()",
	 "Date_to_Text()", "Date_to_Text_Long()", "Calendar()",
	 "Month_to_Text()", "Day_of_Week_to_Text()",
	 "Day_of_Week_Abbreviation()", "Decode_Date_EU()", "Decode_Date_US()",
	 "Decode_Date_EU2()", "Decode_Date_US2()", "Parse_Date()".

	 Note that when	you pass an invalid number, such as e.g. zero, or no
	 language parameter at all, these functions will revert	to their
	 behaviour in the versions of this module prior	to 6.0,	which means
	 that the global setting (as set by ""Language()"") becomes active
	 again (only in	case of	an invalid or missing language parameter!).

	 In the	C library "DateCalc.c",	where omitting a parameter is not an
	 option, passing a zero	for the	language is therefore the recommended
	 way to	guarantee backward compatibility.

       o "$max_lang = Languages();"

	 This function returns the (maximum) number of languages which are
	 currently available in	your installation of this package.

	 (This may vary	from installation to installation.)

	 See the section "How to install additional languages" in the file
	 "INSTALL.txt" in this distribution for	how to add more	languages to
	 this package.

	 In the	original distribution of this package there are	fourteen
	 built-in languages, therefore the value returned by this function
	 will be "14" if no other languages have been added to your particular
	 installation.

       o "if (($year,$month,$day) = Decode_Date_EU2($string[,$lang))"

	 This function is the Perl equivalent of the function
	 ""Decode_Date_EU()"" (implemented in C), included here	merely as an
	 example to demonstrate	how easy it is to write	your own routine in
	 Perl (using regular expressions) adapted to your own special needs,
	 should	the necessity arise, and intended primarily as a basis for
	 your own development.

	 In one	particular case	this Perl version is actually slightly more
	 permissive than its C equivalent, as far as the class of permitted
	 intervening (i.e., delimiting)	characters is concerned.

	 (Can you tell the subtle, almost insignificant	difference by looking
	 at the	code? Or by experimenting? Hint: Try the string	"a3b1c64d"
	 with both functions.)

       o "if (($year,$month,$day) = Decode_Date_US2($string[,$lang))"

	 This function is the Perl equivalent of the function
	 ""Decode_Date_US()"" (implemented in C), included here	merely as an
	 example to demonstrate	how easy it is to write	your own routine in
	 Perl (using regular expressions) adapted to your own special needs,
	 should	the necessity arise, and intended primarily as a basis for
	 your own development.

	 In one	particular case	this Perl version is actually slightly more
	 permissive than its C equivalent.

	 (Hint:	This is	the same difference as with the	""Decode_Date_EU()""
	 and ""Decode_Date_EU2()"" pair	of functions.)

	 In a different	case, the C version is a little	bit more permissive
	 than its Perl equivalent.

	 (Can you tell the difference by looking at the	code? Or by
	 experimenting?	 Hint: Try the string "(1/364)"	with both functions.)

       o "if (($year,$month,$day) = Parse_Date($string[,$lang))"

	 This function is useful for parsing dates as returned by the UNIX
	 ""date"" command or as	found in the headers of	e-mail (in order to
	 determine the date at which some e-mail has been sent or received,
	 for instance).

	 Example #1:

	   ($year,$month,$day) = Parse_Date(`/bin/date`);

	 Example #2:

	   while (<MAIL>)
	   {
	       if (/^From \S/)
	       {
		   ($year,$month,$day) = Parse_Date($_);
		   ...
	       }
	       ...
	   }

	 The function returns an empty list if it can't	extract	a valid	date
	 from the input	string.

       o "$lower = ISO_LC($string);"

	 Returns a copy	of the given string where all letters of the
	 ISO-Latin-1 character set have	been replaced by their lower case
	 equivalents.

	 Similar to Perl's built-in function ""lc()"" (see "lc"	in
	 perlfunc(1)) but for the whole	ISO-Latin-1 character set, not just
	 plain ASCII.

       o "$upper = ISO_UC($string);"

	 Returns a copy	of the given string where all letters of the
	 ISO-Latin-1 character set have	been replaced by their upper case
	 equivalents.

	 Similar to Perl's built-in function ""uc()"" (see "uc"	in
	 perlfunc(1)) but for the whole	ISO-Latin-1 character set, not just
	 plain ASCII.

       o "$string = Date::Calc::Version();"

	 This function returns a string	with the (numeric) version number of
	 the CA	library	("DateCalc.c") at the core of this package (which is
	 also (automatically) the version number of the	"Calc.xs" file).

	 Note that under all normal circumstances, this	version	number should
	 be identical with the one found in the	Perl variable
	 "$Date::Calc::VERSION"	(the version number of the "Calc.pm" file).

	 Since this function is	not exported, you always have to qualify it
	 explicitly, i.e., ""Date::Calc::Version()"".

	 This is to avoid possible name	space conflicts	with version functions
	 from other modules.

RECIPES
       1)  How do I compare two	dates?

	   Solution #1:

	     use Date::Calc qw(	Date_to_Days );

	     if	(Date_to_Days($year1,$month1,$day1)  <
		 Date_to_Days($year2,$month2,$day2))

	     if	(Date_to_Days($year1,$month1,$day1)  <=
		 Date_to_Days($year2,$month2,$day2))

	     if	(Date_to_Days($year1,$month1,$day1)  >
		 Date_to_Days($year2,$month2,$day2))

	     if	(Date_to_Days($year1,$month1,$day1)  >=
		 Date_to_Days($year2,$month2,$day2))

	     if	(Date_to_Days($year1,$month1,$day1)  ==
		 Date_to_Days($year2,$month2,$day2))

	     if	(Date_to_Days($year1,$month1,$day1)  !=
		 Date_to_Days($year2,$month2,$day2))

	     $cmp = (Date_to_Days($year1,$month1,$day1)	 <=>
		     Date_to_Days($year2,$month2,$day2));

	   Solution #2:

	     use Date::Calc qw(	Delta_Days );

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) > 0)

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) >= 0)

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) < 0)

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) <= 0)

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) == 0)

	     if	(Delta_Days($year1,$month1,$day1,
			    $year2,$month2,$day2) != 0)

       2)  How do I check whether a given date lies within a certain range of
	   dates?

	     use Date::Calc qw(	Date_to_Days );

	     $lower = Date_to_Days($year1,$month1,$day1);
	     $upper = Date_to_Days($year2,$month2,$day2);

	     $date = Date_to_Days($year,$month,$day);

	     if	(($date	>= $lower) && ($date <=	$upper))
	     {
		 # ok
	     }
	     else
	     {
		 # not ok
	     }

       3)  How do I compare two	dates with times? How do I check whether two
	   dates and times lie more or less than a given time interval apart?

	   Solution #1:

	     use Date::Calc qw(	Add_Delta_DHMS Date_to_Days );

	     @date1 = (2002,8,31,23,59,1);
	     @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours

	     #@date1 = (2002,8,31,22,59,1);
	     #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours

	     # Omit the	next line if you just want to compare the two dates
	     # (and change @date3 and @d3 to @date1 and	@d1, respectively):

	     @date3 = Add_Delta_DHMS(@date1, 0,12,0,0);	# ==> is the difference	within 12 hours?

	     @d2 = ( Date_to_Days(@date2[0..2]), ($date2[3]*60+$date2[4])*60+$date2[5] );
	     @d3 = ( Date_to_Days(@date3[0..2]), ($date3[3]*60+$date3[4])*60+$date3[5] );

	     @diff = ( $d2[0]-$d3[0], $d2[1]-$d3[1] );

	     if	($diff[0] > 0 and $diff[1] < 0)	{ $diff[0]--; $diff[1] += 86400; }
	     if	($diff[0] < 0 and $diff[1] > 0)	{ $diff[0]++; $diff[1] -= 86400; }

	     if	(($diff[0] || $diff[1])	>= 0) {	print "More than 12 hours.\n"; }
	     else			      {	print "Less than 12 hours.\n"; }

	   Solution #2:

	   This	solution is only feasible if your dates	are guaranteed to lie
	   within the range given by your system's epoch and overflow date and
	   time!

		Unix:	 1-Jan-1970 00:00:00  to  19-Jan-2038 03:14:07
		MacOS:	 1-Jan-1904 00:00:00  to   6-Feb-2040 06:28:15

	     use Date::Calc qw(	Date_to_Time );

	     @date1 = (2002,8,31,23,59,1);
	     @date2 = (2002,9,1,11,30,59); # ==> less than 12 hours

	     #@date1 = (2002,8,31,22,59,1);
	     #@date2 = (2002,9,1,11,30,59); # ==> more than 12 hours

	     $d1 = Date_to_Time(@date1);
	     $d2 = Date_to_Time(@date2);

	     if	($d1 <=	$d2) { print "The two dates are	in chronological order.\n"; }
	     else	     { print "The two dates are	in reversed order.\n"; }

	     if	($d1 + 12*60*60	<= $d2)	{ print	"More than 12 hours.\n"; }
	     else			{ print	"Less than 12 hours.\n"; }

       4)  How do I verify whether someone has a certain age?

	     use Date::Calc qw(	Decode_Date_EU Today leap_year Delta_Days );

	     $date = <STDIN>; #	get birthday

	     ($year1,$month1,$day1) = Decode_Date_EU($date);

	     ($year2,$month2,$day2) = Today();

	     if	(($day1	== 29) && ($month1 == 2) && !leap_year($year2))
		 { $day1--; }

	     if	( (($year2 - $year1) >	18) ||
		( (($year2 - $year1) ==	18) &&
		(Delta_Days($year2,$month1,$day1, $year2,$month2,$day2)	>= 0) )	)
	     {
		 print "Ok - you are over 18.\n";
	     }
	     else
	     {
		 print "Sorry -	you aren't 18 yet!\n";
	     }

	     Or, alternatively (substituting the last "if" statement above):

	     if	(($year1+18 <=>	$year2 || $month1 <=> $month2 || $day1 <=> $day2) <= 0)
		 { print "Ok - you are over 18.\n"; }
	     else
		 { print "Sorry	- you aren't 18	yet!\n"; }

       5)  How do I calculate the number of the	week of	month the current date
	   lies	in?

	   For example:

		       April 1998
	       Mon Tue Wed Thu Fri Sat Sun
			 1   2	 3   4	 5  =  week #1
		 6   7	 8   9	10  11	12  =  week #2
		13  14	15  16	17  18	19  =  week #3
		20  21	22  23	24  25	26  =  week #4
		27  28	29  30		    =  week #5

	   Solution:

	     use Date::Calc qw(	Today Day_of_Week );

	     ($year,$month,$day) = Today();

	     $week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;

       6)  How do I calculate whether a	given date is the 1st, 2nd, 3rd, 4th
	   or 5th of that day of week in the given month?

	   For example:

		      October 2000
	       Mon Tue Wed Thu Fri Sat Sun
					 1
		 2   3	 4   5	 6   7	 8
		 9  10	11  12	13  14	15
		16  17	18  19	20  21	22
		23  24	25  26	27  28	29
		30  31

	   Is Sunday, the 15th of October 2000,	the 1st, 2nd, 3rd, 4th or 5th
	   Sunday of that month?

	   Solution:

	     use Date::Calc qw(	Day_of_Week Delta_Days
				Nth_Weekday_of_Month_Year
				Date_to_Text_Long English_Ordinal
				Day_of_Week_to_Text Month_to_Text );

	     ($year,$month,$day) = (2000,10,15);

	     $dow = Day_of_Week($year,$month,$day);

	     $n	= int( Delta_Days(
		       Nth_Weekday_of_Month_Year($year,$month,$dow,1),
		       $year,$month,$day)
		       / 7) + 1;

	     printf("%s	is the %s %s in	%s %d.\n",
		 Date_to_Text_Long($year,$month,$day),
		 English_Ordinal($n),
		 Day_of_Week_to_Text($dow),
		 Month_to_Text($month),
		 $year);

	   This	prints:

	     Sunday, October 15th 2000 is the 3rd Sunday in October 2000.

       7)  How do I calculate the date of the Wednesday	of the same week as
	   the current date?

	   Solution #1:

	     use Date::Calc qw(	Today Day_of_Week Add_Delta_Days );

	     $searching_dow = 3; # 3 = Wednesday

	     @today = Today();

	     $current_dow = Day_of_Week(@today);

	     @date = Add_Delta_Days(@today, $searching_dow - $current_dow);

	   Solution #2:

	     use Date::Calc qw(	Today Add_Delta_Days
				Monday_of_Week Week_of_Year );

	     $searching_dow = 3; # 3 = Wednesday

	     @today = Today();

	     @date = Add_Delta_Days( Monday_of_Week( Week_of_Year(@today) ),
				     $searching_dow - 1	);

	   Solution #3:

	     use Date::Calc qw(	Standard_to_Business Today
				Business_to_Standard );

	     @business = Standard_to_Business(Today());

	     $business[2] = 3; # 3 = Wednesday

	     @date = Business_to_Standard(@business);

       8)  How can I add a week	offset to a business date (including across
	   year	boundaries)?

	     use Date::Calc qw(	Business_to_Standard Add_Delta_Days
				Standard_to_Business );

	     @temp = Business_to_Standard($year,$week,$dow);

	     @temp = Add_Delta_Days(@temp, $week_offset	* 7);

	     ($year,$week,$dow)	= Standard_to_Business(@temp);

       9)  How do I calculate the last and the next Saturday for any given
	   date?

	     use Date::Calc qw(	Today Day_of_Week Add_Delta_Days
				Day_of_Week_to_Text Date_to_Text );

	     $searching_dow = 6; # 6 = Saturday

	     @today = Today();

	     $current_dow = Day_of_Week(@today);

	     if	($searching_dow	== $current_dow)
	     {
		 @prev = Add_Delta_Days(@today,-7);
		 @next = Add_Delta_Days(@today,+7);
	     }
	     else
	     {
		 if ($searching_dow > $current_dow)
		 {
		     @next = Add_Delta_Days(@today,
			       $searching_dow -	$current_dow);
		     @prev = Add_Delta_Days(@next,-7);
		 }
		 else
		 {
		     @prev = Add_Delta_Days(@today,
			       $searching_dow -	$current_dow);
		     @next = Add_Delta_Days(@prev,+7);
		 }
	     }

	     $dow = Day_of_Week_to_Text($searching_dow);

	     print "Today is:	   ", '	' x length($dow),
					  Date_to_Text(@today),	"\n";
	     print "Last $dow was:     ", Date_to_Text(@prev),	"\n";
	     print "Next $dow will be: ", Date_to_Text(@next),	"\n";

	   This	will print something like:

	     Today is:		    Sun	12-Apr-1998
	     Last Saturday was:	    Sat	11-Apr-1998
	     Next Saturday will	be: Sat	18-Apr-1998

       10) How can I calculate the last	business day (payday!) of a month?

	   Solution #1 (holidays NOT taken into	account):

	     use Date::Calc qw(	Days_in_Month Day_of_Week Add_Delta_Days );

	     $day = Days_in_Month($year,$month);
	     $dow = Day_of_Week($year,$month,$day);
	     if	($dow >	5)
	     {
		 ($year,$month,$day) =
		     Add_Delta_Days($year,$month,$day, 5-$dow);
	     }

	   Solution #2 (holidays taken into account):

	   This	solution expects a multi-dimensional array "@holiday", which
	   contains all	holidays, as follows: ""$holiday[$year][$month][$day]
	   = 1;"".

	   (See	the description	of the function	""Easter_Sunday()"" further
	   above for how to calculate the moving (variable) christian feast
	   days!)

	   Days	which are not holidays remain undefined	or should have a value
	   of zero in this array.

	     use Date::Calc qw(	Days_in_Month Add_Delta_Days Day_of_Week );

	     $day = Days_in_Month($year,$month);
	     while (1)
	     {
		 while ($holiday[$year][$month][$day])
		 {
		     ($year,$month,$day) =
			 Add_Delta_Days($year,$month,$day, -1);
		 }
		 $dow =	Day_of_Week($year,$month,$day);
		 if ($dow > 5)
		 {
		     ($year,$month,$day) =
			 Add_Delta_Days($year,$month,$day, 5-$dow);
		 }
		 else {	last; }
	     }

	   Solution #3 (holidays taken into account, more comfortable, but
	   requires Date::Calendar(3) and Date::Calc::Object(3)):

	     use Date::Calc::Object qw(	Today Add_Delta_YM Date_to_Text_Long );
	     use Date::Calendar::Profiles qw($Profiles);
	     use Date::Calendar;

	     $calendar = Date::Calendar->new( $Profiles->{'DE-BW'} );

	     @today = Today();
	     @nextmonth	= Add_Delta_YM(@today[0,1],1, 0,1);

	     $workaround = $calendar->add_delta_workdays(@nextmonth,+1);
	     $payday	 = $calendar->add_delta_workdays($workaround,-2);

	     print "Pay	day = ", Date_to_Text_Long($payday->date()), "\n";

	   The "workaround" is necessary due to	a bug in the method
	   "add_delta_workdays()" when adding a	negative number	of workdays.

       11) How do I convert a MS Visual	Basic "DATETIME" value into its	date
	   and time constituents?

	     use Date::Calc qw(	Add_Delta_DHMS Date_to_Text );

	     $datetime = "35883.121653";

	     ($Dd,$Dh,$Dm,$Ds) = ($datetime =~ /^(\d+)\.(\d\d)(\d\d)(\d\d)$/);

	     ($year,$month,$day, $hour,$min,$sec) =
		 Add_Delta_DHMS(1900,1,1, 0,0,0, $Dd,$Dh,$Dm,$Ds);

	     printf("The given date is %s %02d:%02d:%02d\n",
		 Date_to_Text($year,$month,$day), $hour, $min, $sec);

	   This	prints:

	     The given date is Tue 31-Mar-1998 12:16:53

	   Since I do not have or use Visual Basic, I can't guarantee that the
	   number format assumed here is really	the one	used by	Visual Basic -
	   but you get the general idea. ":-)"

	   Moreover, consider the following:

	   Morten Sickel <Morten.Sickel@nrpa.no> wrote:

	   I discovered	a bug in Excel (2000): Excel thinks that 1900 was a
	   leap	year. Users should use 31-Dec-1899 as the date to add an Excel
	   date	value to in order to get the correct date.

	   I found out on the web that this bug	originated in Lotus 123, which
	   made	29-Feb-1900 an "industrial standard". MS chose to keep the bug
	   in order to be compatible with Lotus	123. But they have not
	   mentioned anything about it in the help files.

       12) How can I send a reminder to	members	of a group on the day before a
	   meeting which occurs	every first Friday of a	month?

	     use Date::Calc qw(	Today Date_to_Days Add_Delta_YMD
				Nth_Weekday_of_Month_Year );

	     ($year,$month,$day) = Today();

	     $tomorrow = Date_to_Days($year,$month,$day) + 1;

	     $dow = 5; # 5 = Friday
	     $n	  = 1; # 1 = First of that day of week

	     $meeting_this_month = Date_to_Days(
		 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );

	     ($year,$month,$day) = Add_Delta_YMD($year,$month,$day, 0,1,0);

	     $meeting_next_month = Date_to_Days(
		 Nth_Weekday_of_Month_Year($year,$month,$dow,$n) );

	     if	(($tomorrow == $meeting_this_month) ||
		 ($tomorrow == $meeting_next_month))
	     {
		 # Send	reminder e-mail!
	     }

       13) How can I print a date in a different format	than provided by the
	   functions ""Date_to_Text()"", ""Date_to_Text_Long()"" or
	   ""Compressed_to_Text()""?

	     use Date::Calc qw(	Today Day_of_Week_to_Text
				Day_of_Week Month_to_Text
				English_Ordinal	);

	     ($year,$month,$day) = Today();

	   For example with leading zeros for the day: "FriA 03-Jan-1964"

	     printf("%.3s %02d-%.3s-%d\n",
		 Day_of_Week_to_Text(Day_of_Week($year,$month,$day)),
		 $day,
		 Month_to_Text($month),
		 $year);

	   For example in U.S. american	format:	"AprilA	12th,A 1998"

	     $string = sprintf("%s %s, %d",
			   Month_to_Text($month),
			   English_Ordinal($day),
			   $year);

	   For example in one of the possible formats as specified by
	   ISOA	8601:

	     @date = ($year,$month,$day,$hour,$min,$sec);
	     $date = sprintf("%d-%02d-%02d %02d:%02d:%02d", @date);

	   (See	also "printf" in perlfunc(1) and/or "sprintf" in perlfunc(1)!)

       14) How can I iterate through a range of	dates?

	     use Date::Calc qw(	Delta_Days Add_Delta_Days );

	     @start = (1999,5,27);
	     @stop  = (1999,6,1);

	     $j	= Delta_Days(@start,@stop);

	     for ( $i =	0; $i <= $j; $i++ )
	     {
		 @date = Add_Delta_Days(@start,$i);
		 printf("%4d/%02d/%02d\n", @date);
	     }

	   Note	that the loop can be improved; see also	the recipe below.

       15) How can I create a (Perl) list of dates in a	certain	range?

	     use Date::Calc qw(	Delta_Days Add_Delta_Days Date_to_Text );

	     sub date_range
	     {
		 my(@date) = (@_)[0,1,2];
		 my(@list);
		 my($i);

		 $i = Delta_Days(@_);
		 while ($i-- >=	0)
		 {
		     push( @list, [ @date ] );
		     @date = Add_Delta_Days(@date, 1) if ($i >=	0);
		 }
		 return(@list);
	     }

	     @range = &date_range(1999,11,3, 1999,12,24); # in chronological order

	     foreach $date (@range)
	     {
		 print Date_to_Text(@{$date}), "\n";
	     }

	   Note	that you probably shouldn't use	this one, because it is	much
	   more	efficient to iterate through all the dates (as shown in	the
	   recipe immediately above) than to construct such an array and then
	   to loop through it. Also, it	is much	more space-efficient not to
	   create this array.

       16) How can I calculate the difference in days between dates, but
	   without counting Saturdays and Sundays?

	     sub Delta_Business_Days
	     {
		 my(@date1) = (@_)[0,1,2];
		 my(@date2) = (@_)[3,4,5];
		 my($minus,$result,$dow1,$dow2,$diff,$temp);

		 $minus	 = 0;
		 $result = Delta_Days(@date1,@date2);
		 if ($result !=	0)
		 {
		     if	($result < 0)
		     {
			 $minus	= 1;
			 $result = -$result;
			 $dow1 = Day_of_Week(@date2);
			 $dow2 = Day_of_Week(@date1);
		     }
		     else
		     {
			 $dow1 = Day_of_Week(@date1);
			 $dow2 = Day_of_Week(@date2);
		     }
		     $diff = $dow2 - $dow1;
		     $temp = $result;
		     if	($diff != 0)
		     {
			 if ($diff < 0)
			 {
			     $diff += 7;
			 }
			 $temp -= $diff;
			 $dow1 += $diff;
			 if ($dow1 > 6)
			 {
			     $result--;
			     if	($dow1 > 7)
			     {
				 $result--;
			     }
			 }
		     }
		     if	($temp != 0)
		     {
			 $temp /= 7;
			 $result -= ($temp << 1);
		     }
		 }
		 if ($minus) { return -$result;	}
		 else	     { return  $result;	}
	     }

	   This	solution is probably of	little practical value,	however,
	   because it doesn't take legal holidays into account.

	   See Date::Calendar(3) for how to do that.

       17) How can I "normalize" the output of the "Delta_YMDHMS()" (or
	   "Delta_YMD()") function so that it contains only positive values?

	   I.e., how can I show	a difference in	date (and time)	in a more
	   human-readable form,	for example in order to	show how much time
	   until (or since) the	expiration of something	(e.g. an account, a
	   domain, a credit card, etc.)	is left	(has passed)?

	   Correct solution: Use the functions "N_Delta_YMDHMS()" and
	   "N_Delta_YMD()" instead!

	   The following gives a rudimentary sketch of a (much inferior)
	   solution, which is maintained here only for historical reasons of
	   this	module:

	   a) Delta_YMDHMS():

	     #!perl
	     use strict;
	     use Date::Calc qw(Today_and_Now Delta_YMDHMS Add_Delta_YMDHMS Delta_DHMS Date_to_Text);

	     my	$today = [Today_and_Now()];
	     my	$target	= [2005,1,1,0,0,0];

	     my	$sign =	"until";
	     my	$delta = Normalize_Delta_YMDHMS($today,$target);
	     if	($delta->[0] < 0)
	     {
		 $sign = "since";
		 $delta	= Normalize_Delta_YMDHMS($target,$today);
	     }
	     printf("Today is %s %02d:%02d:%02d\n", Date_to_Text(@{$today}[0..2]), @{$today}[3..5]);
	     printf
	     (
		 "%d year%s, %d	month%s, %d day%s, %d hour%s, %d minute%s, %d second%s %s %s %02d:%02d:%02d\n",
		 $delta->[0], (($delta->[0]==1)?'':'s'),
		 $delta->[1], (($delta->[1]==1)?'':'s'),
		 $delta->[2], (($delta->[2]==1)?'':'s'),
		 $delta->[3], (($delta->[3]==1)?'':'s'),
		 $delta->[4], (($delta->[4]==1)?'':'s'),
		 $delta->[5], (($delta->[5]==1)?'':'s'),
		 $sign,
		 Date_to_Text(@{$target}[0..2]),
		 @{$target}[3..5]
	     );

	     sub Normalize_Delta_YMDHMS
	     {
		 my($date1,$date2) = @_;
		 my(@delta);

		 @delta	= Delta_YMDHMS(@$date1,@$date2);
		 while ($delta[1] < 0 or
			$delta[2] < 0 or
			$delta[3] < 0 or
			$delta[4] < 0 or
			$delta[5] < 0)
		 {
		     if	($delta[1] < 0)	{ $delta[0]--; $delta[1] += 12;	}
		     if	($delta[2] < 0)
		     {
			 $delta[1]--;
			 @delta[2..5] =	(0,0,0,0);
			 @delta[2..5] =	Delta_DHMS(Add_Delta_YMDHMS(@$date1,@delta),@$date2);
		     }
		     if	($delta[3] < 0)	{ $delta[2]--; $delta[3] += 24;	}
		     if	($delta[4] < 0)	{ $delta[3]--; $delta[4] += 60;	}
		     if	($delta[5] < 0)	{ $delta[4]--; $delta[5] += 60;	}
		 }
		 return	\@delta;
	     }

	   b) Delta_YMD():

	     #!perl
	     use strict;
	     use Date::Calc qw(Today Delta_YMD Add_Delta_YM Delta_Days Date_to_Text);

	     my($sign,$delta);
	     my	$today = [Today()];
	     my	$target	= [2005,1,1];

	     if	(Delta_Days(@$today,@$target) <	0)
	     {
		 $sign = "since";
		 $delta	= Normalize_Delta_YMD($target,$today);
	     }
	     else
	     {
		 $sign = "until";
		 $delta	= Normalize_Delta_YMD($today,$target);
	     }
	     print "Today is ",	Date_to_Text(@$today), "\n";
	     printf
	     (
		 "%d year%s, %d	month%s, %d day%s %s %s\n",
		 $delta->[0], (($delta->[0]==1)?'':'s'),
		 $delta->[1], (($delta->[1]==1)?'':'s'),
		 $delta->[2], (($delta->[2]==1)?'':'s'),
		 $sign,
		 Date_to_Text(@$target)
	     );

	     sub Normalize_Delta_YMD
	     {
		 my($date1,$date2) = @_;
		 my(@delta);

		 @delta	= Delta_YMD(@$date1,@$date2);
		 while ($delta[1] < 0 or $delta[2] < 0)
		 {
		     if	($delta[1] < 0)	{ $delta[0]--; $delta[1] += 12;	}
		     if	($delta[2] < 0)
		     {
			 $delta[1]--;
			 $delta[2] = Delta_Days(Add_Delta_YM(@$date1,@delta[0,1]),@$date2);
		     }
		 }
		 return	\@delta;
	     }

	   Note	that for normalizing just a time vector, you can use the
	   built-in function "Normalize_DHMS()". However, this will yield
	   either all positive OR all negative values, NOT all positive	values
	   as above.

SEE ALSO
       Date::Calc::Util(3), Date::Calc::Object(3), Date::Calendar(3),
       Date::Calendar::Year(3),	Date::Calendar::Profiles(3).

	 "The Calendar FAQ":
	 http://www.tondering.dk/claus/calendar.html
	 by Claus Tondering <claus@tondering.dk>

BEWARE
       When you	are using the (deprecated) function "Language()", the language
       setting is stored in a global variable.

       This may	cause conflicts	between	threads	or modules running
       concurrently.

       Therefore, in order to avoid such conflicts, NEVER use the function
       "Language()", but ALWAYS	pass a language	parameter to the functions
       which are language-dependent.

VERSION
       This man	page documents "Date::Calc" version 6.4.

AUTHOR
	 Steffen Beyer
	 mailto:STBEY@cpan.org
	 http://www.engelschall.com/u/sb/download/

COPYRIGHT
       Copyright (c) 1995 - 2015 by Steffen Beyer. All rights reserved.

LICENSE
       This package is free software; you can use, modify and redistribute it
       under the same terms as Perl itself, i.e., at your option, under	the
       terms either of the "Artistic License" or the "GNU General Public
       License".

       The C library at	the core of the	module "Date::Calc::XS"	can, at	your
       discretion, also	be used, modified and redistributed under the terms of
       the "GNU	Library	General	Public License".

       Please refer to the files "Artistic.txt", "GNU_GPL.txt" and
       "GNU_LGPL.txt" in the "license" subdirectory of this distribution for
       any details!

DISCLAIMER
       This package is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A	PARTICULAR PURPOSE.

       See the "GNU General Public License" for	more details.

POD ERRORS
       Hey! The	above document had some	coding errors, which are explained
       below:

       Around line 1761:
	   Non-ASCII character seen before =encoding in	'FranA<section>ais'.
	   Assuming CP1252

perl v5.32.1			  2015-03-07			 Date::Calc(3)

NAME | MOTTO | PREFACE | SYNOPSIS | IMPORTANT NOTES | DESCRIPTION | RECIPES | SEE ALSO | BEWARE | VERSION | AUTHOR | COPYRIGHT | LICENSE | DISCLAIMER | POD ERRORS

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Date::Calc&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help