Skip to content

Instantly share code, notes, and snippets.

@chansen
Created February 16, 2012 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chansen/1848964 to your computer and use it in GitHub Desktop.
Save chansen/1848964 to your computer and use it in GitHub Desktop.
US § 6103. HOLIDAYS (Federal)
#!/usr/bin/perl
use strict;
use warnings;
do 'us_federal_holidays.pl';
# Test cases extracted from <http://www.opm.gov/Operating_Status_Schedules/fedhol/Index.asp>
my @tests = (
[ 1997, '1997-01-01', '1997-01-20', '1997-02-17', '1997-05-26', '1997-07-04',
'1997-09-01', '1997-10-13', '1997-11-11', '1997-11-27', '1997-12-25' ],
[ 1998, '1998-01-01', '1998-01-19', '1998-02-16', '1998-05-25', '1998-07-03',
'1998-09-07', '1998-10-12', '1998-11-11', '1998-11-26', '1998-12-25' ],
[ 1999, '1999-01-01', '1999-01-18', '1999-02-15', '1999-05-31', '1999-07-05',
'1999-09-06', '1999-10-11', '1999-11-11', '1999-11-25', '1999-12-24' ],
[ 2000, '1999-12-31', '2000-01-17', '2000-02-21', '2000-05-29', '2000-07-04',
'2000-09-04', '2000-10-09', '2000-11-10', '2000-11-23', '2000-12-25' ],
[ 2001, '2001-01-01', '2001-01-15', '2001-02-19', '2001-05-28', '2001-07-04',
'2001-09-03', '2001-10-08', '2001-11-12', '2001-11-22', '2001-12-25' ],
[ 2002, '2002-01-01', '2002-01-21', '2002-02-18', '2002-05-27', '2002-07-04',
'2002-09-02', '2002-10-14', '2002-11-11', '2002-11-28', '2002-12-25' ],
[ 2003, '2003-01-01', '2003-01-20', '2003-02-17', '2003-05-26', '2003-07-04',
'2003-09-01', '2003-10-13', '2003-11-11', '2003-11-27', '2003-12-25' ],
[ 2004, '2004-01-01', '2004-01-19', '2004-02-16', '2004-05-31', '2004-07-05',
'2004-09-06', '2004-10-11', '2004-11-11', '2004-11-25', '2004-12-24' ],
[ 2005, '2004-12-31', '2005-01-17', '2005-02-21', '2005-05-30', '2005-07-04',
'2005-09-05', '2005-10-10', '2005-11-11', '2005-11-24', '2005-12-26' ],
[ 2006, '2006-01-02', '2006-01-16', '2006-02-20', '2006-05-29', '2006-07-04',
'2006-09-04', '2006-10-09', '2006-11-10', '2006-11-23', '2006-12-25' ],
[ 2007, '2007-01-01', '2007-01-15', '2007-02-19', '2007-05-28', '2007-07-04',
'2007-09-03', '2007-10-08', '2007-11-12', '2007-11-22', '2007-12-25' ],
[ 2008, '2008-01-01', '2008-01-21', '2008-02-18', '2008-05-26', '2008-07-04',
'2008-09-01', '2008-10-13', '2008-11-11', '2008-11-27', '2008-12-25' ],
[ 2009, '2009-01-01', '2009-01-19', '2009-02-16', '2009-05-25', '2009-07-03',
'2009-09-07', '2009-10-12', '2009-11-11', '2009-11-26', '2009-12-25' ],
[ 2010, '2010-01-01', '2010-01-18', '2010-02-15', '2010-05-31', '2010-07-05',
'2010-09-06', '2010-10-11', '2010-11-11', '2010-11-25', '2010-12-24' ],
[ 2011, '2010-12-31', '2011-01-17', '2011-02-21', '2011-05-30', '2011-07-04',
'2011-09-05', '2011-10-10', '2011-11-11', '2011-11-24', '2011-12-26' ],
[ 2012, '2012-01-02', '2012-01-16', '2012-02-20', '2012-05-28', '2012-07-04',
'2012-09-03', '2012-10-08', '2012-11-12', '2012-11-22', '2012-12-25' ],
[ 2013, '2013-01-01', '2013-01-21', '2013-02-18', '2013-05-27', '2013-07-04',
'2013-09-02', '2013-10-14', '2013-11-11', '2013-11-28', '2013-12-25' ],
[ 2014, '2014-01-01', '2014-01-20', '2014-02-17', '2014-05-26', '2014-07-04',
'2014-09-01', '2014-10-13', '2014-11-11', '2014-11-27', '2014-12-25' ],
[ 2015, '2015-01-01', '2015-01-19', '2015-02-16', '2015-05-25', '2015-07-03',
'2015-09-07', '2015-10-12', '2015-11-11', '2015-11-26', '2015-12-25' ],
[ 2016, '2016-01-01', '2016-01-18', '2016-02-15', '2016-05-30', '2016-07-04',
'2016-09-05', '2016-10-10', '2016-11-11', '2016-11-24', '2016-12-26' ],
[ 2017, '2017-01-02', '2017-01-16', '2017-02-20', '2017-05-29', '2017-07-04',
'2017-09-04', '2017-10-09', '2017-11-10', '2017-11-23', '2017-12-25' ],
[ 2018, '2018-01-01', '2018-01-15', '2018-02-19', '2018-05-28', '2018-07-04',
'2018-09-03', '2018-10-08', '2018-11-12', '2018-11-22', '2018-12-25' ],
[ 2019, '2019-01-01', '2019-01-21', '2019-02-18', '2019-05-27', '2019-07-04',
'2019-09-02', '2019-10-14', '2019-11-11', '2019-11-28', '2019-12-25' ],
[ 2020, '2020-01-01', '2020-01-20', '2020-02-17', '2020-05-25', '2020-07-03',
'2020-09-07', '2020-10-12', '2020-11-11', '2020-11-26', '2020-12-25' ],
);
use Test::More tests => 24;
foreach my $test (@tests) {
my ($year, @dates) = @$test;
my $exp = join ', ', @dates;
my $got = join ', ', map { $_->ymd } calculate_federal_holidays($year);
is($got, $exp, "expected federal holidays for year $year");
}
#!/usr/bin/perl
use strict;
use warnings;
use DateTime qw[];
sub _ymd {
my ($y, $m, $d) = @_;
return DateTime->new(year => $y, month => $m, day => $d);
}
# Federal law 5 USC § 6103 - HOLIDAYS
# http://www.law.cornell.edu/uscode/text/5/6103
sub calculate_federal_holidays {
@_ == 1 || Carp::croak(q/Usage: calculate_federal_holiday($year)/);
my ($year) = @_;
my @dates = ();
# New Year's Day
push @dates, _ymd($year, 1, 1);
# Birthday of Martin Luther King, Jr.
push @dates, do {
# Third Monday in January
my $date = _ymd($year, 1, 1);
$date->add(days => 2*7 + (1 - $date->day_of_week) % 7);
};
# Inauguration Day
# § 6103. HOLIDAYS (c)
# push @dates, _ymd($year, 1, 20)
# if $year % 4 == 1 && $dates[-1]->day != 20; # 1969, 1997, 2025 ...
# Washington's Birthday
push @dates, do {
# Third Monday in February
my $date = _ymd($year, 2, 1);
$date->add(days => 2*7 + (1 - $date->day_of_week) % 7);
};
# Memorial Day
push @dates, do {
# Last Monday in May
my $date = _ymd($year, 5, 31);
$date->subtract(days => ($date->day_of_week - 1) % 7);
};
# Independence Day
push @dates, _ymd($year, 7, 4);
# Labor Day
push @dates, do {
# First Monday in September
my $date = _ymd($year, 9, 1);
$date->add(days => (1 - $date->day_of_week) % 7);
};
# Columbus Day
push @dates, do {
# Second Monday in October
my $date = _ymd($year, 10, 1);
$date->add(days => 1*7 + (1 - $date->day_of_week) % 7);
};
# Veterans Day
push @dates, _ymd($year, 11, 11);
# Thanksgiving Day
push @dates, do {
# Fourth Thursday in November
my $date = _ymd($year, 11, 1);
$date->add(days => 3*7 + (4 - $date->day_of_week) % 7);
};
# Christmas Day
push @dates, _ymd($year, 12, 25);
# § 6103. HOLIDAYS (b)
foreach my $date (@dates) {
$date->add(days => ($date->day_of_week == 6 ? -1 : +1))
if $date->day_of_week > 5;
}
return @dates;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment