shinobi/Date-WorkdayCalendar/lib/Date/WorkdayCalendar
Date-WorkdayCalendar src
Introduction
The B<WorkdayCalendar> and B<Workday> objects allows to perform date calculations on a calendar
that considers workdays (also called "business days").
Built on top of the Date datatype, it uses a calendar file to specify how
many days a workweek has and what are the days considered holidays.
By default, the I<workweek> is composed by B<Mon, Tue, Wed, Thu, Fri>. And
B<Sat> and B<Sun> form the I<weekend>.
Though most countries has the workweek of B<Mon> to B<Fri>, some have very
different ones.
More information about workweeks can be found at
L<http://en.wikipedia.org/wiki/Workweek>
Calendar File format
# An example calendar file
W:Mon,Tue,Wed,Thu,Fri
H:2011/01/01
H:2011-04-05
This calendar specifies that B<Mon> to B<Fri> are to be considered workdays. And
that 2011/01/01 and 2011/04/05 are national holidays. You can use / or - as
separators in a date. The format of the date B<must be> in the order Year, Month, Day
If the W: specification is incorrect, the default workweek
B<Mon, Tue, Wed, Thu, Fri> is used. If a holiday (rows starting with H: ) is not
well defined, is just ignored.
Calendar files accepts comments, with lines starting with #
C class
(head2) C
my $wdc1 = WorkdayCalendar.new;
my $wdc2 = WorkdayCalendar.new('calendar.cal');
Creates a new calendar. Optionally, accepts a filename of a file with the calendar format
specified above. If a filename is not specified, the calendar will have no holidays
and a default workweek of B<Mon, Tue, Wed, Thu, Fri>.
(head2) C
Empties the information for holidays and workdays, and resets the
workweek to the default B<Mon, Tue, Wed, Thu, Fri>.
(head2) C
Reads the data of holidays and workdays from a calendar file.
(head2) C
Returns True if the day is part of the workweek and not a holiday.
(head2) C
Returns True if the day is not part of the workweek.
(head2) C
Returns True if the day has been defined as holiday in the calendar file
(head2) C
Returns a Date that corresponds to the working day at which $days working days have passed.
With this method you can ask questions like:
"what is the next working day for some date?" or
"what is the previous working day of some date?" or
"what date is 2 working days from a date?"
Examples:
Considering the workdays = B<Mon Tue Wed Thu Fri>...
$start : July 29, 2011 (it is a Friday)
$days : +1
Return Value : Aug 1, 2011 (it is a Monday)
$start : July 30, 2011 (it is a Saturday)
$days : +1
Return Value : Aug 1, 2011 (it is a Monday)
This also works for a negative amount of days.
(head2) C
Returns the 'distance', in workdays, of $start and $target dates.
(head2) C
Works like the workdays-to method, but emulates the NETWORKDAYS function in
Microsoft Excel.
Examples
Start Target workdays-to networkdays
2011-07-07 2011-07-14 5 6
2011-07-07 2011-07-07 0 1
2011-07-07 2011-07-08 1 2
2011-07-07 2011-07-01 -4 -5
2011-01-01 2011-01-01 0 0
2011-01-01 2011-01-02 0 0
2011-01-01 2011-01-03 1 1
(head2) C
Returns a part of a calendar as a new WorkdayCalendar object, between the $start
and $end dates, inclusive.
For example, if you have a calendar that contains holiday information for 3 years,
you can use range to obtain a new calendar that covers a period of 6 months of
these 3 years. Useful with the eq operator for WorkdayCalendar objects.
(head2) C
Returns a string representing the contents of the WorkdayCalendar attributes.
C class
Implemented as a subclass of Date . it replaces Date 's .succ and .pred
methods to consider workdays in the account, and provides the functionality to perform
basic workdate calculations.
As parameter, you can specify a previously created
WorkdayCalendar object, or none at all. If a WorkdayCalendar is not specified,
it uses a default workweek of B<Mon,Tue,Wed,Thu,Fri> and no holidays.
Example:
# July 1st of 2011 is a Friday
my $wdate = Workdate.new(year=>2011, month=>07, day=>01); #--- Uses a default calendar with
#--- default workweek and no holidays
my $next_day = $wdate.succ; # $next_day is Monday, July 4, 2011
Another example:
my $CAL = WorkdayCalendar.new('example.cal'); # Some calendar file with 2011-Feb-2 as holiday
my $date = Workdate.new(year=>2011, month=>02, day=>01, calendar=>$CAL);
# February 1 of 2011 is a Tuesday
my $next_day = $date.succ; # $next_day is Thursday, February 3, 2011
(head2) C
my $wd1 = Workdate.new(year=>2000, month=>12, day=>01, calendar=>$aWorkdayCalendar);
my $wd2 = Workdate.new(2000, 12, 01, $aWorkdayCalendar);
my $wd3 = Workdate.new($aDateString, $aWorkdayCalendar);
my $wd4 = Workdate.new($aDateTimeObject, $aWorkdayCalendar);
my $wd4 = Workdate.new($aDateObject, $aWorkdayCalendar);
We try to provide the same constructors as the base Date class, plus another to
create Workdates from regular Dates. So, we can create a Workdate in
4 different ways, from named and positional parameters, and using a Date or a DateTime
object for specifying the date. In all cases, the calendar is optional, and if is not specified
a default calendar will be applied to the new Workdate.
(head2) C
Returns the next workdate.
(head2) C
Returns the previous workdate.
(head2) C
Returns true if the workdate is not a holiday and is not part of the weekend
(head2) C
Returns true if the workdate is not part of the workweek
(head2) C
Returns true if the workdate is reported as a holiday
(head2) C
Returns what is the workdate that is $days workdays from the workdate
(head2) C
Return the amount of workdays until $target
(head2) C
Returns a string representing the contents of the Workdate attributes.
Operators
(head2) Comparison: C<$WorkdayCalendar_1 B $WorkdayCalendar_2>
Compares 2 calendars and see if they are equivalent. For that, they must have the
same holidays and the same workweek. As if they used the same calendar file. You can
use the range method for WorkdayCalendar objects to compare smaller periods of time
instead of a whole WorkdayCalendar.
(head2) Comparison: C<$WorkdayCalendar_1 B $WorkdayCalendar_2>
Returns the opposite of eq
(head2) Arithmetic: C Workdate $wd2>
Returns the difference, in workdays, between $wd1 and $wd2