Pcalendar(3pm)
okay bestie, welcome to Pcalendar(3pm) π this is the manual page for Date::Pcalendar, and itβs lowkey iconic if you need calendar objects with holiday schemes. no cap.
β¨ NAME β¨
Date::Pcalendar β Calendar objects for different holiday schemes π
π MOTTO π
The motto is literally: βThere is more than one way to do it - this is just one of them!β π
π¦ PREFACE π¦
Basically, Date::Pcalendar is just a caching proxy class for Date::Pcalendar::Year objects, which are embedded in each Date::Pcalendar object. bestie, thatβs the whole vibe.
However, and in contrast to Date::Pcalendar::Year methods, Date::Pcalendar methods permit calculations spanning an arbitrary number of years, without loss of efficiency. β¨
So you should usually use Date::Pcalendar and not Date::Pcalendar::Year, since that way you donβt have to worry about calculations crossing year boundaries. periodt.
Note however that Date::Pcalendar and Date::Pcalendar::Year can only deal with years lying within the range [1583..2299]. π«Ά
πΈ SYNOPSIS πΈ
Hereβs the group-chat screenshot of how it looks, fr fr:
use Date::Pcalendar::Profiles qw( $Profiles );
use Date::Pcalendar;
$calendar_US_AZ = Date::Pcalendar->new( $Profiles->{'US-AZ'} [,LANG[,WEEKEND]] );
$calendar_DE_SN = Date::Pcalendar->new( $Profiles->{'DE-SN'} [,LANG[,WEEKEND]] );
$year_2000_US_AZ = $calendar_US_AZ->year( 2000 );
$year_2001_DE_SN = $calendar_DE_SN->year( 2001 );
@years = $calendar->cache_keys(); # returns list of year numbers
@years = $calendar->cache_vals(); # returns list of year objects
$calendar->cache_clr();
$calendar->cache_add(YEAR|DATE,...);
$calendar->cache_del(YEAR|DATE,...);
$index = $calendar->date2index(YEAR,MONTH,DAY|DATE);
@names = $calendar->labels(YEAR,MONTH,DAY|DATE);
@holidays = $calendar->labels();
$holidays = $calendar->labels();
@dates = $calendar->search(PATTERN);
$dates = $calendar->search(PATTERN);
$hashref = $calendar->tags(YEAR,MONTH,DAY|DATE);
$days = $calendar->delta_workdays(YEAR1,MONTH1,DAY1|DATE1
,YEAR2,MONTH2,DAY2|DATE2
,FLAG1,FLAG2);
($date,$rest) = $calendar->add_delta_workdays(YEAR,MONTH,DAY|DATE
,DELTA);
$date = $calendar->add_delta_workdays(YEAR,MONTH,DAY|DATE
,DELTA);
$flag = $calendar->is_full(YEAR,MONTH,DAY|DATE);
$flag = $calendar->is_half(YEAR,MONTH,DAY|DATE);
$flag = $calendar->is_work(YEAR,MONTH,DAY|DATE);
π INTERFACE π
Note that whenever a year number, a date, a time or a combined date and time are expected as input parameters by one of the methods of this class, you can always pass a Date::Pcalc[::Object] date object or an array reference (of an array of appropriate length) instead! π«Ά
See Date::Pcalc::Object(3) for more details.
So instead of calling a given method like this:
$object->method1( $year,$month,$day );
$object->method2( $year1,$month1,$day1, $year2,$month2,$day2 );
$object->method3( $year1, $year2, $year3 );
You can also call it like so:
$object->method1( $date );
$object->method1( [1964,1,3] );
$object->method2( $year1,$month1,$day1, $date2 );
$object->method2( $date1, $year2,$month2,$day2 );
$object->method2( $date1, $date2 );
$object->method2( $year1,$month1,$day1, [2001,3,17] );
$object->method2( [1964,1,3], $year2,$month2,$day2 );
$object->method2( [1964,1,3], [2001,3,17] );
$object->method2( $date1, [2001,3,17] );
$object->method2( [1964,1,3], $date2 );
$object->method3( $year1, $date2, [2001,3,17] );
And similarly if a time or a combined date and time are expected. β¨
If you substitute an expected year number by an anonymous array (this is the recommended way of writing date constants, for increased readability of your programs), it must contain three values, nevertheless (otherwise the use of an anonymous array would be pointless). π
Donβt confuse year numbers and their substitutes (a date object or an array reference) with Date::Pcalendar::Year objects, which are a totally different thing! not me mixing those up, bestie.
But incidentally :-), you may also pass a Date::Pcalendar::Year object whenever a year number is expected. However, and perhaps against your expectations at times, especially in conjunction with the method cache_add(), only the year number from that object will be used, not the year object itself (the year object in question might be using the wrong profile!). π«
Moreover, whenever a method of this class returns a date, it does so by returning a Date::Pcalc[::Object] date object. periodt.
π DESCRIPTION π
okay so here are the methods, and yes every detail matters. letβs go. π
$calendar = Date::Pcalendar->new(PROFILE[,LANG[,WEEKEND]]);β creates your shiny new calendar object.
The first argument must be the reference of a hash, which contains a holiday scheme or profile to be used in all calculations involving the new calendar object.
The second argument is optional, and must consist of the valid name or number of a language as provided by the Date::Pcalc(3) module if given.
After the second argument, a list of day numbers which will constitute the weekend can optionally be specified, where 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday and 7=Sunday.
If no values are given, 6 and 7 (Saturday and Sunday) are automatically taken as default.
If values outside of the range 1..7 are given, they will be ignored.
This can be used to switch off this feature and to have no regularly recurring holidays at all when for instance a zero is given.
See Date::Pcalendar::Profiles(3) and Date::Pcalendar::Year(3) for more details about these arguments and about how to roll your own calendar profiles.
The method creates a new calendar object for a given profile, i.e., a given location and its scheme of holidays (or a scheme of your own).
This calendar object is a caching proxy object; it stores the reference of the given profile and contains a hash (the cache) of Date::Pcalendar::Year objects.
$year = $calendar->year(YEAR|DATE);β grab the year object, bestie.
This method returns a Date::Pcalendar::Year object for the given year and the profile that was associated with the given calendar object.
If the cache in the given calendar object already contains an object for the requested year, the corresponding object reference is simply returned. slay.
If not, a new Date::Pcalendar::Year object is created using the profile that has been associated with the given calendar object. The new Date::Pcalendar::Year object is then stored in the calendar objectβs cache and its object reference is returned.
A fatal given year out of range error will occur if the given year number lies outside the valid range of [1583..2299]. β οΈ
@years = $calendar->cache_keys();β returns the list of YEAR NUMBERS of theDate::Pcalendar::Yearobjects contained in the given calendar objectβs cache. π@years = $calendar->cache_vals();β returns the list of OBJECT REFERENCES of theDate::Pcalendar::Yearobjects contained in the given calendar objectβs cache. π$calendar->cache_clr();β clears the entire cache of the given calendar object (by destroying the cache hash and creating a new one). bye felicia to that cache. π§Ή$calendar->cache_add(YEAR|DATE,...);β roughly, this method is a shortcut for
for $year (@list)
{
$calendar->year($year);
}
$calendar->cache_del(YEAR|DATE,...);β removes theDate::Pcalendar::Yearobjects whose year numbers are given from the cache of the given calendar object.
Year numbers for which the calendar objectβs cache doesnβt contain an entry are simply ignored. lowkey chill.
$index = $calendar->date2index(YEAR,MONTH,DAY|DATE);β turns a date into its day-of-year number.
This method converts a given date into the number of the day in that year (this is sometimes also referred to as the julian date), i.e., a number between 0 (for January 1st) and the number of days in the given year minus one, i.e., 364 or 365 (for December 31st).
You may need this in order to access the bit vectors returned by the Date::Pcalendar::Year methods vec_full(), vec_half() and vec_work().
If the Date::Pcalendar::Year object for the given YEAR is not in the $calendarβs cache yet, it will be created and added.
An exception (invalid date) is thrown if the given arguments do not constitute a valid date, or (given year out of range [1583..2299]) if the given year lies outside of the permitted range. π
@names = $calendar->labels(YEAR,MONTH,DAY|DATE);β the holiday-label queen.
@holidays = $calendar->labels();
$holidays = $calendar->labels();
If any arguments are given, they are supposed to represent a date. In that case, a list of all labels (= names of holidays) associated with that date are returned. The first item returned is always the name of the day of week for that date. The corresponding year object for the given dateβs year is added to the calendarβs cache first if necessary.
If no arguments are given, the list of all available labels in all years that have previously been accessed in the given calendar (i.e., the years which are already in the given calendarβs cache) is constructed. Note that this means that the returned list will be empty if there are no year objects in the given calendarβs cache yet (!). The returned list does NOT include any names of the days of week (which would be pointless in this case).
Multiple labels are reported only once.
Usually all years have the same set of labels, so it may seem superfluous to scan all the years in the cache instead of just one. But there may be exceptions, because it is possible to define calendar profiles which do not contain all possible holidays in every year. See Date::Pcalendar::Profiles(3) and Date::Pcalendar::Year(3) for more details.
In list context, the resulting list itself is returned. In scalar context, the number of items in the resulting list is returned. π
@dates = $calendar->search(PATTERN);β search era, but read the caveat.
$dates = $calendar->search(PATTERN);
This method searches through all the labels in all years that have previously been accessed in the given calendar (i.e., the years which are already in the given calendarβs cache) and returns a list of date objects with all dates whose labels match the given pattern.
(Use the methods cache_clr(), cache_add() and cache_del() in order to put the year numbers you want into the calendar objectβs cache, or to make sure it only contains the year numbers you want to search.)
Note that this is a simple, case-insensitive substring search, NOT a full-fledged regular expression search! π
The result is guaranteed to be sorted chronologically. β¨
Oh, and fr β if you call this one in scalar context, you only get the number of items in the resulting list back, not the resulting list itself (that's what list context gives you). Context is the main character here, bestie. π
π $hashref = $calendar->tags(YEAR,MONTH,DAY|DATE);
Hand it a calendar plus a date and it gives you back a hash reference. The hash it points at is a copy of the calendar profile's internal hash, and it works like this: the names for that date are the keys, and the values are 0, 1, 2, or 3, meaning:
0=> commemorative day1=> "half" holiday2=> "full" holiday3=> both a "half" and a "full" holiday
You'll only ever see the value 3 if some date got redefined by the underlying profile using the same key (i.e., the same name) but with a different type of holiday. So like, same name, different vibe. Noted. πΈ
π¦ $days = $calendar->delta_workdays(YEAR1,MONTH1,DAY1, YEAR2,MONTH2,DAY2, FLAG1,FLAG2);
π¦ $days = $calendar->delta_workdays(DATE1,DATE2,FLAG1,FLAG2);
This one counts the number of work days between two dates β so, the number of days, but with all the holidays yeeted out of the count. π§
In other words, it's literally equivalent to the Delta_Days() function from the Date::Pcalc module, except it disregards holidays while it's counting. Slay.
The two flags say whether the start date and the end date should be included in the counting or not (and yes, that only matters if those dates aren't holidays anyway).
Super common real-world use: you wanna know how many work days are left between today and some deadline. π°οΈ Typically you want to count the current date but not the deadline's date β so you pass true (1) for FLAG1 and false (0) for FLAG2 and boom, that's exactly what you get.
So to spell it out:
- a value of
truemeans "including this date" - a value of
falsemeans "excluding this date"
Just like with Delta_Days() from Date::Pcalc, the dates have to be in chronological order for you to get a positive result. Flip them around and the result comes back negative, no cap.
FLAG1 belongs to the first date you passed in, FLAG2 belongs to the second one (and that holds whether the dates are in chronological order or not, okay?).
π An exception (invalid date) gets raised if either of the two date arguments isn't actually a valid date. So, y'know, give it real dates.
π ($date,$rest) = $calendar->add_delta_workdays(YEAR,MONTH,DAY, DELTA);
π ($date,$rest) = $calendar->add_delta_workdays(DATE,DELTA);
π $date = $calendar->add_delta_workdays(YEAR,MONTH,DAY, DELTA);
π $date = $calendar->add_delta_workdays(DATE,DELTA);
This is the equivalent of the Add_Delta_Days() function from the Date::Pcalc module β except it adds work days and skips holidays. Iconic behaviour, honestly. β¨
So basically: you add or subtract a number of work days DELTA to/from a given date, and you get a brand new date back (as a Date::Pcalc object).
- add days (go forward in time) with a positive offset
DELTA - subtract days (go backward in time) with a negative offset
Note that an exception (invalid date) is raised if the date argument you gave doesn't constitute a valid date. π
Context matters, as always:
- in scalar context, the method just returns the resulting date object
- in list context, the method returns not only the new date but also a
restβ and that rest is useful for cases where your profile has "half" holidays, or when you're adding/subtracting fractions of a day
Sometimes it's just not possible to accommodate the number of work days you asked for, and a rest is left over. π
That rest can currently only assume the value 0.0 (zero), -0.5 (minus one half) or 0.5 (one half) β provided you only use integral or multiples of 0.5 as offsets. How to read it:
- a rest of zero = the calculation yielded an exact result
- a rest of 0.5 or -0.5 = interpret it as "the resulting date at 12:00 o'clock", not "the resulting date at 0:00 o'clock"
The rest is always positive (or zero) if the offset DELTA is positive (or zero), and always negative (or zero) if the offset is negative (or zero).
Example:
#!perl
use Date::Pcalendar;
use Date::Pcalendar::Profiles qw( $Profiles );
$year = shift;
$cal = Date::Pcalendar->new( $Profiles->{'sdm-MUC'} );
($date,$rest) = $cal->add_delta_workdays($year,1,3, -3);
$date->date_format(1);
print "\$date = $date, \$rest = $rest.\n";
__END__
This program calculates "January 3rd of the given year minus 3 work days":
> perl test.pl 2001
$date = 28-Dec-2000, $rest = 0.
> perl test.pl 2002
$date = 28-Dec-2001, $rest = -0.5.
And just fyi, December 31st is a "half" holiday in 2001 for the calendar profile used in this example. π
You can easily verify those results above with the help of the calendar.cgi CGI script or the linearcal.pl script from the examples subdirectory in the Date::Pcalc distribution.
π¨ BEWARE that this method may currently return unexpected (i.e., contradicting the above documentation) or plain wrong results when going back in time (this is a bug!). However, it works correctly and as documented above when going forward in time. So forward = slay, backward = pray. π
π $flag = $calendar->is_full(YEAR,MONTH,DAY|DATE);
Returns true (1) if the bit corresponding to the given date is set in the bit vector representing "full" holidays, and false (0) otherwise.
I.e., the method returns true if the given date is a (full) holiday β according to the calendar profile associated with the given calendar object, of course. π
The corresponding Date::Pcalendar::Year object gets created first, and it's stored in the calendar object's cache if necessary (like, if it's not already chilling there).
Oh and you can grab a reference to this bit vector (so you can use it in bit vector operations) like this:
$vec_full = $calendar->year($year)->vec_full();
The number of bits in this bit vector is the same as the number of days in the given year $year, which you can retrieve through either $days = $vec_full->Size(); or $days = $year->val_days();.
See Date::Pcalendar::Year(3) and Bit::Vector(3) for more details.
π $flag = $calendar->is_half(YEAR,MONTH,DAY|DATE);
Returns true (1) if the bit corresponding to the given date is set in the bit vector representing "half" holidays, and false (0) otherwise.
I.e., the method returns true if the given date is a half holiday β according to the calendar profile associated with the given calendar object. π
Note that if a date is a "full" holiday, the "half" bit is never set β even if you try to do so in your calendar profile, on purpose or by accident. The full holiday ate, and that's periodt.
The corresponding Date::Pcalendar::Year object is created first and stored in the calendar object's cache if necessary (if it's not already there).
You can get a reference to this bit vector (to use it in bit vector operations) like so:
$vec_half = $calendar->year($year)->vec_half();
The number of bits in this bit vector is the same as the number of days in the given year $year, which you can retrieve through either $days = $vec_half->Size(); or $days = $year->val_days();.
See Date::Pcalendar::Year(3) and Bit::Vector(3) for more details.
π $flag = $calendar->is_work(YEAR,MONTH,DAY|DATE);
Returns true (1) if the bit corresponding to the given date is set in the bit vector used to perform all sorts of calculations, and false (0) otherwise.
The corresponding Date::Pcalendar::Year object is created first and stored in the calendar object's cache if necessary (if it's not already there).
π¨ BEWARE that the "work" in this method's name does NOT come from "work days"! It comes from the fact that the corresponding bit vector can be used for any "work" that you need to do. In other words, it's a "work space". π
So therefore, this bit vector might contain about everything you could imagine β including a bit pattern which marks all "work days" with set bits, if it so happens! But you better don't rely on it, unless you put the bit pattern there yourself in the first place. iykyk. π«Ά
You can get a reference to this bit vector (so you can fill it with any bit pattern you like) like this:
$vec_work = $calendar->year($year)->vec_work();
The number of bits in this bit vector is the same as the number of days in the given year $year, which you can retrieve through either $days = $vec_work->Size(); or $days = $year->val_days();.
See Date::Pcalendar::Year(3) and Bit::Vector(3) for more details.
π SEE ALSO π
Date::Pcalendar::Year(3), Date::Pcalendar::Profiles(3), Date::Pcalc::Object(3), Date::Pcalc(3), Date::Calc::Util(3), Bit::Vector(3).
Like, go read those too, bestie. They're the whole friend group. π
π LIMITATIONS π
The calendar profiles included in Date::Pcalendar::Profiles(3) usually do not take historical irregularities into account (even though some do, just to show how this can be done). They only provide means for calculating regularly recurring events β so the profiles should therefore not be relied upon for historical faithfulness. It's giving β¨vibes onlyβ¨, not β¨history PhDβ¨.
π KNOWN BUGS π
The method add_delta_workdays() is known to produce results which are sometimes off by one working day when a negative offset is used.
As a workaround, try to add one working day first and then subtract one working day more than initially intended. See also the file examples/bug.pl for how to do this. Not me having to do math twice but okay, we adapt. π
β VERSION β
This man page documents Date::Pcalendar version 6.1.
π AUTHOR π
Steffen Beyer
mailto:STBEY@cpan.org
http://www.engelschall.com/u/sb/download/
π COPYRIGHT π
Copyright (c) 2000 - 2009 by Steffen Beyer. All rights reserved.
π LICENSE π
This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License".
Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this distribution for 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.
okay and that's a wrap on this one π«Ά this page is Date::Pcalendar(3pm), documenting version 6.1, generated for Perl v5.42.3 and dated 2026-08-20 β go forth and count your work days, bestie, you got this πβ¨
π¦ where this page comes from
- ubuntu stonking: libdate-pcalc-perl 6.1-8build1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms