Date::Calc - Gregorian calendar date calculations
| Use Case | Command | Description |
|---|---|---|
| Days in month | Days_in_Month($year,$month) | Returns number of days in given month |
| Leap year check | leap_year($year) | True if leap year, else false |
| Day of week | Day_of_Week($year,$month,$day) | 1 (Mon) .. 7 (Sun) |
| Current date | Today() | Returns current (year,month,day) |
| Date difference | Delta_Days($y1,$m1,$d1, $y2,$m2,$d2) | Signed days difference |
| Add days | Add_Delta_Days($y,$m,$d, $offset) | Add a days offset |
| ISO week number | Week_of_Year($year,$month,$day) | Returns (week, year) |
| Easter Sunday | Easter_Sunday($year) | Date of Easter (1583-2299) |
| Date to text | Date_to_Text($year,$month,$day[, $lang]) | Formatted date string |
Keep it small, fast and simple
This package consists of a C library and a Perl module for all kinds of date calculations based on the Gregorian calendar, complying with ISO/R2015-1971, DIN1355 and partially ISO8601.
Year numbers from 1 up to the largest positive integer (≥32767) are supported, except for system-dependent POSIX import/export functions which are limited to roughly 1970–2038 (Unix) or 1904–2040 (MacOS Classic).
The Gregorian calendar is projected back to 1 A.D., even though it was introduced in 1582.
This is a toolbox – see recipes at the end for common solutions.
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);
Function signatures:
$days = Days_in_Year($year,$month);
$days = Days_in_Month($year,$month);
$weeks = Weeks_in_Year($year);
if (leap_year($year)) ...
if (check_date($year,$month,$day)) ...
if (check_time($hour,$min,$sec)) ...
if (check_business_date($year,$week,$dow)) ...
$doy = Day_of_Year($year,$month,$day);
$days = Date_to_Days($year,$month,$day);
$dow = Day_of_Week($year,$month,$day);
$week = Week_Number($year,$month,$day); # DEPRECATED
($week,$year) = Week_of_Year($year,$month,$day); # RECOMMENDED
$week = Week_of_Year($year,$month,$day); # DANGEROUS
($year,$month,$day) = Monday_of_Week($week,$year);
if (($year,$month,$day) = Nth_Weekday_of_Month_Year($year,$month,$dow,$n)) ...
($year,$week,$dow) = Standard_to_Business($year,$month,$day);
($year,$month,$day) = Business_to_Standard($year,$week,$dow);
$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);
($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
($Dy,$Dm,$Dd) = Delta_YMD($year1,$month1,$day1, $year2,$month2,$day2);
($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) = Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
($Dy,$Dm,$Dd) = N_Delta_YMD($year1,$month1,$day1, $year2,$month2,$day2);
($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) = N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
($Dd,$Dh,$Dm,$Ds) = Normalize_DHMS($Dd,$Dh,$Dm,$Ds);
($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);
($year,$month,$day, $hour,$min,$sec) = Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);
($year,$month,$day) = Add_Delta_YM($year,$month,$day, $Dy,$Dm);
($year,$month,$day) = Add_Delta_YMD($year,$month,$day, $Dy,$Dm,$Dd);
($year,$month,$day, $hour,$min,$sec) = Add_Delta_YMDHMS($year,$month,$day, $hour,$min,$sec, $D_y,$D_m,$D_d, $Dh,$Dm,$Ds);
($year,$month,$day) = Add_N_Delta_YMD($year,$month,$day, $Dy,$Dm,$Dd);
($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);
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = System_Clock([$gmt]);
($year,$month,$day) = Today([$gmt]);
($hour,$min,$sec) = Now([$gmt]);
($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);
$year = This_Year([$gmt]);
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Gmtime([time]);
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Localtime([time]);
$time = Mktime($year,$month,$day, $hour,$min,$sec);
($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);
$time = Date_to_Time($year,$month,$day, $hour,$min,$sec);
($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
($year,$month,$day) = Easter_Sunday($year);
if ($month = Decode_Month($string[,$lang])) ...
if ($dow = Decode_Day_of_Week($string[,$lang])) ...
if ($lang = Decode_Language($string)) ...
if (($year,$month,$day) = Decode_Date_EU($string[,$lang])) ...
if (($year,$month,$day) = Decode_Date_US($string[,$lang])) ...
$year = Fixed_Window($yy);
$year = Moving_Window($yy);
$date = Compress($year,$month,$day);
if (($century,$year,$month,$day) = Uncompress($date)) ...
if (check_compressed($date)) ...
$string = Compressed_to_Text($date[,$lang]);
$string = Date_to_Text($year,$month,$day[,$lang]);
$string = Date_to_Text_Long($year,$month,$day[,$lang]);
$string = English_Ordinal($number);
$string = Calendar($year,$month[,$orthodox[,$lang]]);
$string = Month_to_Text($month[,$lang]);
$string = Day_of_Week_to_Text($dow[,$lang]);
$string = Day_of_Week_Abbreviation($dow[,$lang]);
$string = Language_to_Text($lang);
$lang = Language();
Language($lang); # DEPRECATED
$oldlang = Language($newlang); # DEPRECATED
$max_lang = Languages();
if (($year,$month,$day) = Decode_Date_EU2($string[,$lang])) ...
if (($year,$month,$day) = Decode_Date_US2($string[,$lang])) ...
if (($year,$month,$day) = Parse_Date($string[,$lang])) ...
$lower = ISO_LC($string);
$upper = ISO_UC($string);
$string = Date::Calc::Version();
use Date::Calc qw( ... );use Date::Calc qw(:all);
Import specific functions or all available.
$days = Days_in_Year($year,$month);
Returns the sum of days from January up to `$month` in `$year`. E.g., `Days_in_Year(1998,2)` → 59, `Days_in_Year($year,12)` → length of year.
$days = Days_in_Month($year,$month);
Returns number of days in the given month, considering leap years for February.
$weeks = Weeks_in_Year($year);
Returns 52 or 53 (ISO weeks) for the given year.
if (leap_year($year)) ...
True (1) if `$year` is a leap year, false (0) otherwise.
if (check_date($year,$month,$day)) ...
True if the values form a valid date.
if (check_time($hour,$min,$sec)) ...
True if 0 ≤ hour < 24, 0 ≤ min < 60, 0 ≤ sec < 60.
if (check_business_date($year,$week,$dow)) ...
True if the three values constitute a valid date in business format (year, week, day of week). Does NOT check whether it’s a workday (use `Day_of_Week < 6` for that).
$doy = Day_of_Year($year,$month,$day);
Returns the day‑of‑year number (1..365/366). Convert back via Add_Delta_Days($year,1,1, $doy - 1).
$days = Date_to_Days($year,$month,$day);
Absolute day number since 1‑Jan‑1 A.D. (1 = Jan 1, 1). Convert back with Add_Delta_Days(1,1,1, $days - 1).
$dow = Day_of_Week($year,$month,$day);
Returns 1 (Monday) to 7 (Sunday).
$week = Week_Number($year,$month,$day); [DEPRECATED]
Week number of the date. Returns 0 if the date belongs to the last week of the previous year, or `Weeks_in_Year($year)+1` for the first week of the next year. Use `Week_of_Year()` instead.
($week,$year) = Week_of_Year($year,$month,$day); [RECOMMENDED]
Returns the ISO week number and the year that week belongs to. In scalar context it returns only the week, but that is dangerous because the year is lost.
($year,$month,$day) = Monday_of_Week($week,$year);
Returns the date of the Monday of the given week.
if (($year,$month,$day) = Nth_Weekday_of_Month_Year($year,$month,$dow,$n)) ...
Returns the date of the `$n`th occurrence of day‑of‑week `$dow` in the given month. Returns empty list if that occurrence does not exist (e.g. 5th Friday).
($year,$week,$dow) = Standard_to_Business($year,$month,$day);($year,$month,$day) = Business_to_Standard($year,$week,$dow);
Convert between standard (year,month,day) and business (year,week,day‑of‑week) formats.
$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);
Signed difference in days (positive if date1 < date2).
($Dd,$Dh,$Dm,$Ds) = Delta_DHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
Signed difference in days, hours, minutes, seconds. All four values have the same sign.
($Dy,$Dm,$Dd) = Delta_YMD($year1,$month1,$day1, $year2,$month2,$day2);
Returns the vector ($year2-$year1, $month2-$month1, $day2-$day1). Adding this vector to date1 gives date2 (with possible wrapping of days into the next month).
($D_y,$D_m,$D_d, $Dh,$Dm,$Ds) = Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
Combination of `Delta_YMD` and time difference; adjusts `$D_d` for carry‑over.
($Dy,$Dm,$Dd) = N_Delta_YMD($year1,$month1,$day1, $year2,$month2,$day2);
Normalized date difference; all return values have the same sign, |$Dm| < 12, |$Dd| < 31. “Left‑to‑right with truncation” semantics (like `Add_Delta_YM`).
($D_y,$D_m,$D_d, $Dhh,$Dmm,$Dss) = N_Delta_YMDHMS($year1,$month1,$day1, $hour1,$min1,$sec1, $year2,$month2,$day2, $hour2,$min2,$sec2);
Normalized date/time difference. All components have the same sign, |$D_m|<12, |$D_d|<31, |$Dhh|<24, |$Dmm|<60, |$Dss|<60.
($Dd,$Dh,$Dm,$Ds) = Normalize_DHMS($Dd,$Dh,$Dm,$Ds);
Renormalizes a days/hours/minutes/seconds vector so that hours are in [-23..23], minutes/seconds in [-59..59], and all components share the same sign.
($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);
Adds (or subtracts) a days offset. Also used to convert absolute day numbers back to a date.
($year,$month,$day, $hour,$min,$sec) = Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);
Adds a days/hours/minutes/seconds offset to a date/time.
($year,$month,$day) = Add_Delta_YM($year,$month,$day, $Dy,$Dm);
Adds year and month offsets, truncating the resulting day to the last valid day of the month if necessary (e.g. 31 Jan + 1 month → 28/29 Feb).
($year,$month,$day) = Add_Delta_YMD($year,$month,$day, $Dy,$Dm,$Dd);
Adds year, month and day offsets. Years and months are added first; excessive days wrap into the next month (e.g. 31 Jan + 1 month + 1 day → 3 Mar).
($year,$month,$day, $hour,$min,$sec) = Add_Delta_YMDHMS(...);
Same as `Add_Delta_YMD` but also allows a time offset.
($year,$month,$day) = Add_N_Delta_YMD($year,$month,$day, $Dy,$Dm,$Dd);
Shortcut: applies `Add_Delta_YM` first (with truncation), then `Add_Delta_Days`. Complements `N_Delta_YMD()`.
($year,$month,$day, $hour,$min,$sec) = Add_N_Delta_YMDHMS(...);
Like `Add_N_Delta_YMD` but also includes a time offset.
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = System_Clock([$gmt]);
Returns current date/time and additional info from the system clock if available. `$gmt` true gives UTC.
($year,$month,$day) = Today([$gmt]);
Current date only.
($hour,$min,$sec) = Now([$gmt]);
Current time only.
($year,$month,$day, $hour,$min,$sec) = Today_and_Now([$gmt]);
Current date and time.
$year = This_Year([$gmt]);
Current year.
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Gmtime([time]);
Like Perl’s `gmtime`, but returns month 1‑12 and full year.
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Localtime([time]);
Like Perl’s `localtime`, same ordering as `Gmtime`.
$time = Mktime($year,$month,$day, $hour,$min,$sec);
Converts date/time (local) to seconds since the epoch. Similar to POSIX::mktime, but with standard month range.
($D_y,$D_m,$D_d, $Dh,$Dm,$Ds, $dst) = Timezone([time]);
Returns the difference between local time and GMT (timezone offset), and a daylight‑saving flag.
$time = Date_to_Time($year,$month,$day, $hour,$min,$sec);
Converts a date/time (UTC on Unix, local on MacOS Classic) to seconds since the epoch. Inverse of `Time_to_Date`.
($year,$month,$day, $hour,$min,$sec) = Time_to_Date([time]);
Converts seconds since the epoch to UTC (Unix) or local (MacOS) date/time. Inverse of `Date_to_Time`.
($year,$month,$day) = Easter_Sunday($year);
Returns the date of Easter Sunday for years 1583‑2299 using the Gaussian rule.
if ($month = Decode_Month($string[,$lang])) ...
Translates a month name or unique abbreviation to its number (1‑12). Returns 0 on failure.
if ($dow = Decode_Day_of_Week($string[,$lang])) ...
As above, for day‑of‑week names (1‑7).
if ($lang = Decode_Language($string)) ...
Returns the internal language number from its name (e.g. "Deutsch" → 3).
if (($year,$month,$day) = Decode_Date_EU($string[,$lang])) ...
Extracts a date in European order (day‑month‑year) from a string. Supports many formats and abbreviations.
if (($year,$month,$day) = Decode_Date_US($string[,$lang])) ...
Same for US order (month‑day‑year).
$year = Fixed_Window($yy);
Converts two‑digit year to four digits: yy < 70 → 20yy, ≥70 → 19yy. Returns 0 for negative years.
$year = Moving_Window($yy);
Two‑digit year mapping using a 50‑year window around the current year (falls back to `Fixed_Window` if system clock unavailable).
$date = Compress($year,$month,$day); [DEPRECATED]
Encodes a date into 16 bits (legacy). Handles years 1970‑2069.
if (($century,$year,$month,$day) = Uncompress($date)) ... [DEPRECATED]
Decodes a compressed date. Returns empty list on failure.
if (check_compressed($date)) ... [DEPRECATED]
True if `$date` is a valid compressed date.
$string = Compressed_to_Text($date[,$lang]); [DEPRECATED]
Returns a fixed‑length string "dd‑Mmm‑yy" or "??‑???‑??" for invalid input.
$string = Date_to_Text($year,$month,$day[,$lang]);
Returns a string like "Wed 15‑Oct‑1998".
$string = Date_to_Text_Long($year,$month,$day[,$lang]);
Returns a long format, e.g. "Wednesday, October 15th 1998". Actual format depends on language.
$string = English_Ordinal($number);
Returns the English ordinal suffix (e.g. 1st, 2nd, 3rd, 4th…).
$string = Calendar($year,$month[,$orthodox[,$lang]]);
Returns a formatted calendar for the given month. If `$orthodox` is true, weeks start on Sunday.
$string = Month_to_Text($month[,$lang]);
Returns the full month name.
$string = Day_of_Week_to_Text($dow[,$lang]);
Returns the full day‑of‑week name.
$string = Day_of_Week_Abbreviation($dow[,$lang]);
Returns a special abbreviated name if defined (e.g. Polish), otherwise the first three letters.
$string = Language_to_Text($lang);
Returns the name of a language given its internal number.
$lang = Language();Language($lang); [DEPRECATED]$oldlang = Language($newlang); [DEPRECATED]
Gets or sets the global language. Deprecated; pass language parameter directly to avoid conflicts.
$max_lang = Languages();
Returns the number of languages currently installed.
if (($year,$month,$day) = Decode_Date_EU2($string[,$lang])) ...
Perl‑only version of `Decode_Date_EU`, slightly more permissive. Serves as an example for custom parsers.
if (($year,$month,$day) = Decode_Date_US2($string[,$lang])) ...
Perl‑only version of `Decode_Date_US`, analogous to above.
if (($year,$month,$day) = Parse_Date($string[,$lang])) ...
Parses dates in the format produced by the Unix `date` command or found in email headers.
$lower = ISO_LC($string);$upper = ISO_UC($string);
Lower‑/upper‑case conversion for the whole ISO‑Latin‑1 character set.
$string = Date::Calc::Version();
Returns the numeric version of the underlying C library (and XS file). Always fully qualified.
if (Date_to_Days($y1,$m1,$d1) > Date_to_Days($y2,$m2,$d2)) ...
$lower = Date_to_Days($y1,$m1,$d1);
$upper = Date_to_Days($y2,$m2,$d2);
$date = Date_to_Days($y,$m,$d);
if ($date >= $lower && $date <= $upper) { ... }
@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]);
# then compare...
if (($year1+18 <=> $year2 || $month1 <=> $month2 || $day1 <=> $day2) <= 0) { ... }
$week = int(($day + Day_of_Week($year,$month,1) - 2) / 7) + 1;
$n = int(Delta_Days(
Nth_Weekday_of_Month_Year($year,$month,DOW,1),
$date)/7)+1;
$dow_today = Day_of_Week(@today);
@wed = Add_Delta_Days(@today, 3 - $dow_today);
@temp = Business_to_Standard($year,$week,$dow);
@temp = Add_Delta_Days(@temp, $weeks * 7);
($year,$week,$dow) = Standard_to_Business(@temp);
$dow = Day_of_Week(@today);
if (6 == $dow) { @prev = Add_Delta_Days(@today,-7); @next = Add_Delta_Days(@today,7); }
elsif (6 > $dow) { @next = Add_Delta_Days(@today, 6-$dow); @prev = Add_Delta_Days(@next,-7); }
else { @prev = Add_Delta_Days(@today, 6-$dow); @next = Add_Delta_Days(@prev,7); }
$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); }
($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);
$tomorrow = Date_to_Days(Today()) + 1;
$meeting_this = Date_to_Days(Nth_Weekday_of_Month_Year($y,$m,5,1));
$meeting_next = Date_to_Days(Nth_Weekday_of_Month_Year($y,$m+1,5,1));
if ($tomorrow == $meeting_this || $tomorrow == $meeting_next) { ... }
printf("%.3s %02d-%.3s-%d\n",
Day_of_Week_to_Text(Day_of_Week($y,$m,$d)),
$d, Month_to_Text($m), $y);
$j = Delta_Days(@start,@stop);
for $i (0..$j) { @date = Add_Delta_Days(@start,$i); ... }
sub date_range {
my(@date)=@_[0..2];
my $i = Delta_Days(@_);
my @list;
while ($i-- >= 0) { push @list,[@date]; @date = Add_Delta_Days(@date,1) if $i>=0; }
return @list;
}
sub Delta_Business_Days {
my($minus,$result,$dow1,$dow2,$diff);
$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) { $result -= ($temp/7)*2; }
}
return $minus ? -$result : $result;
}
Use N_Delta_YMDHMS() instead. Older workaround shown here is obsolete.
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
The deprecated function Language() uses a global variable. To avoid thread or module conflicts, always pass an explicit language parameter to language‑dependent functions.
This man page documents Date::Calc version 6.4.
Steffen Beyer
STBEY@cpan.org
http://www.engelschall.com/u/sb/download/
Copyright (c) 1995 - 2015 by Steffen Beyer. All rights reserved.
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 of the "Artistic License" or the "GNU General Public License". The C library at the core of Date::Calc::XS can also be used under the "GNU Library General Public License".
See the files Artistic.txt, GNU_GPL.txt and GNU_LGPL.txt in the license subdirectory of this distribution.
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.
Generated by phpman v4.9.26-5-g7740029 Author: Che Dong Under GNU General Public License
2026-08-25 05:20 @216.73.216.179
CrawledBy Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)