NAME
Date::WorkdayCalendar - Calendar and Date objects to handle business days, holidays and weekends
SYNOPSIS
use Date::WorkdayCalendar;
# construct a default workday calendar
my $calendar = WorkdayCalendar.new;
# work out the next workday away from the given date
# 2016-11-18 is a Friday
$calendar.workdays-away(Date.new('2016-11-18'), 1); # 2016-11-21
# construct a workday calendar from a file
my $calendar-from-file = WorkdayCalendar.new('days.cal');
# create a workdate from a date string
my $workdate = Workdate.new('2016-05-02');
# create a workdate from a Date object
my $date = Date.new('2016-11-18');
my $workdate-from-date = Workdate.new($date);
# is the day a workday?
$workdate = Workdate.new('2016-11-18');
$workdate.is-workday; # True
$workdate.is-weekend; # False
$workdate.is-holiday; # False
DESCRIPTION
The WorkdayCalendar
and Workdate
objects allow date calculations to be made 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 which days are to be considered holidays.
By default, the workweek is composed of Monday, Tuesday, Wednesday, Thursday, and Friday. Saturday and Sunday form the weekend.
Although most countries have a Monday to Friday workweek, some have very different ones.
More information about workweeks can be found at http://en.wikipedia.org/wiki/Workweek.
INTRODUCTION
The module provides two classes: WorkdayCalendar
and Workday
. Objects of these classes allow date calculations to be made on a calendar that takes workdays (also called "business days") into account.
Built on top of the Date
datatype, it uses a calendar file to specify how many days a workweek has and which days are to be considered holidays.
By default, the workweek is composed by Mon, Tue, Wed, Thu, and Fri. Sat and Sun form the weekend.
Alhough most countries have a workweek of Mon to Fri, some have very different ones.
More information about workweeks can be found at http://en.wikipedia.org/wiki/Workweek.
# An example calendar file
W:Mon,Tue,Wed,Thu,Fri
H:2011/01/01
H:2011-04-05
This calendar specifies that Mon to 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 must be in the order Year, Month, Day.
If the W:
specification is incorrect, the default workweek (Mon, Tue, Wed, Thu, Fri) is used. If a holiday (a row starting with H:
) is not well defined, it is ignored.
Lines starting with #
are comments and will be ignored when parsing the file.
WorkdayCalendar
class
method new
my $wdc1 = WorkdayCalendar.new;
my $wdc2 = WorkdayCalendar.new('calendar.cal');
Creates a new calendar. Optionally, accepts the name of a file using the calendar format specified above. If a filename is not specified, the calendar will have no holidays and a default workweek of Mon, Tue, Wed, Thu, Fri.
method clear
Empties the information for holidays and workdays, and resets the workweek to the default: Mon, Tue, Wed, Thu, Fri.
method read(Str $calendar_filename)
Reads the data of holidays and workdays from a calendar file.
method is-workday(Date $day)
Returns True
if the day is part of the workweek and not a holiday.
method is-weekend(Date $day)
Returns True
if the day is not part of the workweek.
method is-holiday(Date $day)
Returns True
if the day has been defined as holiday in the calendar file.
method workdays-away(Date $start, Int $days)
Returns a Date
that corresponds to the workday 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 = 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 number of days.
method workdays-to(Date $start, Date $target)
Returns the 'distance', in workdays, of $start
and $target
dates.
method networkdays(Date $start, Date $target)
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
method range(Date $start, Date $end)
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.
method raku
Returns a string representing the contents of the WorkdayCalendar
attributes.
Workdate
class
Implemented as a subclass of Date
. It replaces Date
's .succ
and .pred
methods to take workdays into account and provides the functionality to perform basic workdate calculations.
You can specify a previously created WorkdayCalendar
object as a parameter, or none at all. If a WorkdayCalendar
is not specified, it uses a default workweek of 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
method new
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 Workdate
s from regular Date
s. Thus, we can create a Workdate
in 4 different ways, from named and positional parameters, and by using a Date
or a DateTime
object for specifying the date. In all cases, the calendar is optional, and if it is not specified a default calendar will be applied to the new Workdate
.
method succ
Returns the next workdate.
method pred
Returns the previous workdate.
method is-workday
Returns True if the workdate is not a holiday and is not part of the weekend.
method is-weekend
Returns True if the workdate is not part of the workweek.
method is-holiday
Returns True if the workdate is reported as a holiday.
method workdays-away(Int $days)
Returns the workdate that is $days
workdays from the given workdate.
method workdays-to(Date $target)
Return the number of workdays until $target
.
method raku
Returns a string representing the contents of the Workdate
attributes.
OPERATORS
Comparison: $WorkdayCalendar_1 B<eq> $WorkdayCalendar_2
Compares two calendars and returns True if they are equivalent. For that, they must have the same holidays and the same workweek. For instance, this would be 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
.
Comparison: $WorkdayCalendar_1 B<ne> $WorkdayCalendar_2
Returns the opposite of eq
.
Arithmetic: Workdate $wd1 B<-> Workdate $wd2
Returns the difference, in workdays, between $wd1
and $wd2
.
AUTHOR
Shinobi
COPYRIGHT AND LICENSE
Copyright 2012 - 2013 Shinobi
Copyright 2014 - 2022 Raku Community
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.