NAME
DateTime::Calendar::Fiscal5253 - Perl extension for DateTime
SYNOPSIS
use DateTime::Calendar::Fiscal5253;
my $fc = DateTime::Calendar::Fiscal5253->new( year => 2012 );
DESCRIPTION
This module generates calendars for a "52/53 week" fiscal year. They are also known as "4-4-5" or "4-5-4" calendars due to the repeating week patterns of the periods in each quarter. A 52/53 week year will always have either 52 or 53 weeks (364 or 371 days.) One of the best known of this type is the standard Retail 4-5-4 calendar as defined by the National Retail Federation.
You are strongly advised to speak with your accounting people (after all, the reason you are reading this is because they want reports, right?) and show them a dump of the data for any given year and see if it matches what they expect.
Keep in mind that when an accountant says they want data for fiscal year 2012 they are talking about an accounting year that ends in 2012. An accountant will usually think in terms of "the fiscal year ending in October, 2012." (Unless they are talking about Retail 4-5-4 years, see the section below that deals specifically with this.)
ERROR HANDLING
All methods return undef
if an error occurs as well as emitting an error message via carp
.
CONSTRUCTOR
new
my $fc = DateTime::Calendar::Fiscal5253->new();
The constructor accepts the following parameters:
end_month
-
set the last calendar month of the fiscal year. This should be an integer in the range 1 .. 12 where "1" is January. Default: 12
end_dow
-
sets the last day of the week of the fiscal year. This is an integer in the range 1 .. 7 with Monday being 1. Remember, a 52/52 week fiscal calendar always ends on the same weekday. Default: 6 (Saturday)
end_type
-
determines how to calculate the last day of the fiscal year based on the
end_month
andend_dow
. There are two legal vaules: "Last" and "Closest". Default: "Last""Last" says to use the last weekday of the type specified in
end_dow
as the end of the fiscal year."Closest" says to use the weekday of the type specified that is closest to the end of the calendar month as the last day, even if it is in the following month.
leap_period
-
determines what period the 53rd week (if needed) is placed in. This could be of importance when creating year-over-year reports. There are two legal values: "First" and "Last". Default: "Last"
"First" says to place the extra week in period 1.
"Last" says to place the extra week in period 12.
The last two parameters control what year the calendar is generated for. Note: These parameters are mutually exclusive and will throw an error if both are present.
year
-
sets the fiscal year to build for. It defaults to the correct fiscal year for the current date or to the fiscal year containing the date specified by
date
.The fiscal year value will often be different than the calendar year for dates that are near the beginning or end of the fiscal year. For example, Jan 3, 2015 is the last day of FYE2014 when using an
end_type
of "closest".NOTE! In normal accounting terms, a fiscal year is named for the calendar year it ends in. That is, for a fiscal year that ends in October, fiscal year 2005 would begin in October or November of calendar year 2004 (depending upon the setting of
end_type
.) However, Retail 4-5-4 calendars are named for the year they begn in. This means that a Retail 4-5-4 calendar for 2005 would begin in 2005 and not 2004 as an accountant would normally think. See the discussion at the end of this documentation about Retail 4-5-4 calendars for more information. date
-
if present, is either a string representing a date or a DateTime object. This will be used to build a calendar that contains the given value. Again, be aware that dates that are close to the end of a given fiscal year might have different values for the calendar year vs the fiscal year.
If the value for
date
is a string, it must be specified as either "YYYY-MM-DD" or "MM/DD/YYYY" or some reason able variant of those such as single digit days and months. Time components, if present, are discarded. Any other format will generate a fatal error. A DateTime object will be cloned before being used to prevent unwanted changes to the original object.
ACCESSORS
All accessors are read-only methods that return meta-information about parameters that were used to construct the object or the base values represented by the object as a result of those parameters.
If you want to change any of the underlying properties that define an object, create a new object!
meta
my $meta = $fc->meta();
my %meta = $fc->meta();
This method will return either a hash or a reference to a hash (denpending upon context) containing all of the available meta-information in one structure.
my $fc = DateTime::Calendar::Fiscal5253->new( year => 2012 );
my $fc_info = $fc->meta();
print Dumper($fc_info);
$VAR1 = {
'end_dow' => 5,
'leap_period' => 'last',
'end_type' => 'closest',
'end' => '2012-02-03',
'end_month' => 1,
'year' => 2012,
'start' => '2011-01-29',
'weeks' => 53
};
The value contained in $fc_info-
{year}> is the name of the fiscal year as commonly used by accountants (as in "fye2012") and is usually the same as the calendar year the fiscal year ends in. However, it is possible for the actual ending date to be in the following calendar year, especially if a leap week is present. Fiscal year 2014 built as shown below demonstrates this:
my $fc = DateTime::Calendar::Fiscal5253->new(
year => 2014,
end_type => 'closest'
);
print Dumper($fc->meta());
$VAR1 = {
'end_dow' => 6,
'leap_period' => 'last',
'end_type' => 'closest',
'end' => '2015-01-03',
'end_month' => 12,
'year' => 2014,
'start' => '2013-12-29',
'weeks' => 53
};
Individual Attributes
The following are provided as a means to access the invidual items in the above structure for those who prefer individual accessors. Remember, these are all read-only.
- year
-
my $year = $fc->year();
- end_month
-
my $end_month = $fc->end_month();
- end_dow
-
my $end_dow = $fc->end_dow();
- end_type
-
my $end_type = $fc->end_type();
- start
-
my $start = $fc->start();
- end
-
my $end = $fc->end();
- weeks
-
my $weeks = $fc->weeks();
- leap_period
-
my $leap_period = $fc->leap_period();
METHODS
has_leap_week
my $fc = DateTime::Calendar::Fiscal5253->new( year => 2006 );
print "This is a Fiscal Leap Year" if $fc->has_leap_week;
Returns a Boolean value indicating whether or not the Fiscal Year for the object has 53 weeks instead of the standard 52 weeks.
contains
if ( my $pnum = $fc->contains() ) {
print "The current date is in period $pnum\n";
}
if ( $fc->contains( date => 'today', calendar => 'Restated' ) ) {
print 'The current day is in the Fiscal calendar';
}
if ( $fc->contains( date => '2012-01-01', calendar => 'Fiscal' ) ) {
print '2012-01-01 is in the Fiscal calendar';
}
my $dt = DateTime->today( time_zone => 'floating' );
if ( my $pnum = $fc->contains( date => $dt ) ) {
print "$dt is in period $pnum\n";
}
This method takes two named parameters, 'date' and 'calendar', and returns the period number containing 'date' if the given date is valid for the specified calendar. Bear in mind that some dates that are in the Fiscal calendar might not be in a Restated or Truncated calendar.
date
-
Accepts the same formats as the contructor as well as the special keyword 'today'. Defaults to the current date if not supplied.
calendar
-
Specifies which calendar style to check against and accepts the same values as the 'calendar' method does. The default is 'Fiscal'.
calendar
my $cal = $fc->calendar();
my $cal = $fc->calendar( style => 'Normal' );
my $rcal = $fc->calendar( style = 'Restated' );
my @cal = $fc->calendar()
...
Returns either an array or a reference to an array (depending upon context) that contains an entry with meta data in the first element ($cal->[0]) and period (month) data in the folling twelve entries. This allows for a natural access cycle using for ( 1 .. 12 )
in many cases.
It accepts a single parameter, style
, which must be 'Fiscal', 'Restated' or 'Truncated' (defaults to 'Fiscal'.)
The value 'Fiscal' will build a calendar with the full number of weeks without regard to whether there are 52 or 53 weeks in the year.
The value 'Restated' says to ignore the first week in a 53 week year and create a calendar with only 52 weeks. This allows for more accurate year-over-year comparisons involving a year that would otherwise have 53 weeks.
The value 'Truncated' says to ignore the last week in a 53 week year and create a calendar with only 52 weeks. This may allow for more accurate year-over-year comparisons involving a year that would otherwise have 53 weeks.
Note! The method will return a 'Fiscal' calendar if either 'Restated' or 'Truncated' is requested for a normal 52 week year since there is no difference in those cases.
The meta information in the first element ($cal[0]) contains the following information about how the calendar (not the object!) is configured:
print Dumper($cal->[0]);
$VAR1 = {
'end_dow' => 6,
'leap_period' => 'last',
'style' => 'restated',
'end_type' => 'closest',
'end' => '2013-02-02',
'end_month' => 1,
'year' => 2013,
'start' => '2012-02-05',
'weeks' => 52
};
Note! The meta data in the calendar structure will be different from that returned by the 'meta' method if either 'Restated' or 'Truncated' is requested for a 53 week year! Always use the data from the 'year' method to see how the object itself was created.
Each period element will have information about the start and end date, number of weeks, and the nominal name of the month as well as the period number.
print Dumper($cal=>[1]);
$VAR1 = {
'period' => 1,
'month' => 'February',
'end' => '2012-03-03',
'weeks' => 4,
'start' => '2012-02-05'
};
period
my %pdata = $fc->period( period => 5, calendar => 'Restated' );
my $pdata = $fc->period( period => 1, calendar => 'Fiscal' );
Read-only method that returns a hash or a reference to a hash depending upon context that contains all of the data for the requested period in the specified calendar type.
period
-
Must be a number in the range 1 - 12. If not given, the method will use the current date if it exists in the requested calendar and return the period data containing it.
calendar
-
Specifies what calendar style to retrieve the period information from. Default is 'Fiscal'.
The returned data is as follows:
print Dumper($pdata);
$VAR1 = {
'period' => 1,
'month' => 'February',
'start' => '2012-02-04',
'weeks' => 4,
'end' => '2012-03-02'
};
Note! It is an error condition to supply a value of undef
for 'period'. Consider what can happen if one is tempted to write code such as this:
my $pinfo = $fc->period( period => $fc->contains( date => $somedate ) );
This could produce unexpected results if $somedate
does not exist in the calendar. Without this restriction, the 'period' method would attempt to use the current date, which may or may not exist in the object, and would almost certainly be different than what was desired.
The following methods are provided for those who want to access the individual components of the period structure without dealing with a hash. They return a scalar value and accept the same parameters as period
does. undef
will be returned if an error occurs.
- period_month
-
my $pmonth = $fc->period_month( period => 3, calendar => 'Fiscal' );
- period_start
-
my $pstart = $fc->period_start( period => 5 );
- period_end
-
my $pend = $fc->period_end( calendar => 'Fiscal' );
- period_weeks
-
my $pweeks = $fc->period_weeks( period => 2, calendar => 'Restated' );
There is no method to return the period number component because presumably you already know that. Use the "contains" method to get the period number for the current date if applicable. (Besides, $fc->period_period
is just plain ugly!)
Retail 4-5-4 calendars
A Retail 4-5-4 calendar (as described by the National Retail Federation here: http://www.nrf.com/modules.php?name=Pages&sp_id=392) is an example of a Fiscal 52/53 week year that starts on the Sunday closest to Jan 31 of the specified year.
In other words, to create a Retail 4-5-4 calendar for 2012, you will create a Fiscal5253 object that ends in 2013 on the Saturday closest to Jan 31.
Note! Fiscal years are named for the year they end in, Retail 4-5-4 years are named for the year they begin in!
# Create a Retail 4-5-4 calendar for 2012
my $r2012 = DateTime::Calendar::Fiscal5253->new(
year => 2013, # This will be the ending year for the calendar
end_month => 1, # End in January
end_dow => 6, # on the Saturday
end_type => 'closest', # closest to the end of the month
leap_period => 'last' # and any leap week in the last period
);
You can verify that this is correct by viewing the calendars available at the NRF website: http://www.nrf.com/4-5-4Calendar
The reporting date can be determined by adding 5 days to the end of any given period. Using DateTime makes this trivial:
# Get the reporting date for period 5 for the object created above
my ($y,$m,$d) = split(/\-/,$r2012->period_end( period => 5 ));
my $report_date = DateTime->new(
year => $y,
month => $m,
day => $d
)->add( days => 5 )->ymd;
TO DO
Add better error reporting via a class variable/method instead of using Carp messages.
Add methods to work with fiscal week numbers.
Anything else that users of this module deem desirable.
SEE ALSO
DateTime to get ideas about how to work with an object suppiled to the constructor as the date
parameter.
Do a Google (or comparable) search to learn more about Fiscal Years and the 52/53 week. This is a fairly arcane subject that usually is of interest only to accountants and those of us who must provide reports to them.
Of particular interest will be how a Retail 4-5-4 calendar differs in definition from an accounting 4-4-5 fiscal year.
CREDITS
This module, like any other in the DateTime family, could not exist without the work and dedication of Dave Rolsky.
SUPPORT
Support is provided by the author. Please report bugs or make feature requests to the email address below.
AUTHOR
Jim Bacon, <jim@nortx.com>
COPYRIGHT AND LICENSE
Copyright (C) 2012 by Jim Bacon
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.