File Coverage

blib/lib/Date/Holidays/US.pm
Criterion Covered Total %
statement 48 60 80.0
branch 54 66 81.8
condition 229 312 73.4
subroutine 8 8 100.0
pod 4 4 100.0
total 343 450 76.2


line stmt bran cond sub pod time code
1             package Date::Holidays::US;
2 7     7   456393 use strict;
  7         66  
  7         186  
3 7     7   30 use warnings;
  7         14  
  7         192  
4 7     7   32 use base qw{Exporter};
  7         10  
  7         966  
5 7     7   2989 use POSIX; #strftime to calculate wday
  7         38573  
  7         32  
6              
7             our @EXPORT_OK = qw(is_holiday holidays is_us_holiday us_holidays);
8              
9             our $VERSION = '0.02';
10              
11             =head1 NAME
12              
13             Date::Holidays::US - Date::Holidays Adapter for US Federal holidays
14              
15             =head1 SYNOPSIS
16              
17             use Date::Holidays::US qw{is_holiday};
18             my $holiday_name = is_holiday($year, $month, $day);
19              
20             =head1 DESCRIPTION
21              
22             Date::Holidays Adapter for US Federal holidays back to 1880 with updates from 2022.
23              
24             =head1 METHODS
25              
26             =head2 is_holiday
27              
28             Returns a holiday name or undef given three arguments (year, month, day).
29              
30             my ($year, $month, $day) = (2022, 6, 19);
31             use Date::Holidays::US qw{is_holiday};
32             my $holiday_name = is_holiday($year, $month, $day);
33             if (defined $holiday_name) {
34             print "Holiday: $holiday_name\n";
35             } else {
36             print "Not a US Holiday\n";
37             }
38              
39             =cut
40              
41             sub is_holiday {
42 381     381 1 929 my $year = shift;
43 381         488 my $month = shift;
44 381         436 my $day = shift;
45 381         9743 my $wday = POSIX::strftime(qq{%w}, 0, 0, 0, $day, $month-1, $year-1900); #12:00 am
46              
47             #5 U.S. Code § 6103 - Holidays
48             #The history of federal holidays in the United States dates back to June 28, 1870
49 381 100 66     18944 if ($year > 1870 and $month == 1 and $day == 1) {
    50 100        
    100 66        
    100 100        
    50 66        
    50 100        
    50 100        
    100 66        
    50 100        
    50 66        
    100 100        
    100 100        
    100 66        
    100 100        
    50 100        
    100 66        
    100 66        
    100 66        
    100 33        
    50 66        
    50 66        
    100 33        
    50 33        
    100 100        
    100 66        
    100 100        
    50 100        
    100 66        
    100 66        
    100 33        
    100 66        
    50 66        
      33        
      33        
      100        
      66        
      66        
      66        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      100        
      66        
      66        
      100        
      66        
      100        
      100        
      66        
      66        
      66        
      66        
      100        
      100        
      100        
      100        
      33        
      33        
      33        
      33        
      33        
      33        
      0        
      66        
      66        
      66        
      33        
      33        
      33        
      0        
      66        
      66        
      66        
      33        
      33        
      66        
      100        
      100        
      66        
      100        
      66        
      100        
      66        
      66        
      100        
      66        
      100        
      66        
      100        
      100        
      66        
      100        
      66        
      100        
      100        
      66        
      100        
      66        
50 12         77 return q{New Year's Day}; #January 1
51             } elsif ($year > 1909 and $month == 1 and $day == 2 and $wday == 1) { #Executive Order 1076 (May 22, 1909)
52 0         0 return q{New Year's Day Observed}; #Monday afer January 1
53              
54             #observed for the first time on January 20, 1986. - Pub.L. 98–399, 98 Stat. 1475, enacted November 2, 1983
55             } elsif ($year >= 1986 and $month == 1 and $day >= 15 and $day <= 21 and $wday == 1) {
56 8         35 return 'Birthday of Martin Luther King, Jr.' #the third Monday in January
57              
58             #Inauguration Day - Really only DC and few
59             } elsif ($year >= 1965 and $month == 1 and $day == 20 and $year % 4 == 1) { #5 U.S. Code 6103(c)
60 1         5 return 'Inauguration Day' #January 20 of each fourth year after 1965
61             } elsif ($year >= 1965 and $month == 1 and $day == 21 and $year % 4 == 1 and $wday == 1) { #5 U.S. Code 6103(c)
62 0         0 return 'Inauguration Day Observed' #When January 20 ... falls on Sunday, the next succeeding day ... observance
63              
64             # Washington's Birthday was celebrated on February 22 from 1879 until 1970.
65             # in 1968 the Uniform Monday Holiday Act moved it to the third Monday in February
66             # The Act was signed into law on June 1, 1968, and took effect on January 1, 1971.
67             } elsif ($year >= 1879 and $year < 1971 and $month == 2 and $day == 22) {
68 0         0 return q{Washington's Birthday}; #February 22 from 1879 until 1970
69             } elsif ($year > 1909 and $year < 1971 and $month == 2 and $day == 23 and $wday == 1) { #Executive Order 1076 (May 22, 1909)
70 0         0 return q{Washington's Birthday Observed}; #February 23 when Monday
71             } elsif ($year >= 1971 and $month == 2 and $day >= 15 and $day <= 21 and $wday == 1) { #Uniform Monday Holiday Act (June 28, 1968)
72 8         32 return q{Washington's Birthday}; #the third Monday in February
73              
74             # Memorial Day/Decoration Day
75             } elsif ($year >= 1888 and $year < 1971 and $month == 5 and $day == 30) {
76 0         0 return 'Decoration Day'; #May 30
77             } elsif ($year >= 1909 and $year < 1971 and $month == 6 and $day == 1 and $wday == 1) { #Executive Order 1076 (May 22, 1909)
78 0         0 return 'Decoration Day Observed'; #June 1st
79             } elsif ($year >= 1971 and $month == 5 and $day >= 25 and $day <= 31 and $wday == 1) { #Uniform Monday Holiday Act (June 28, 1968)
80 8         28 return 'Memorial Day'; #the last Monday in May
81              
82             #The day was first recognized as a federal holiday in June 2021, when President
83             #Joe Biden signed the Juneteenth National Independence Day Act into law.
84             } elsif ($year >= 2021 and $month == 6 and $day == 18 and $wday == 5) { #Executive Order 11582 (Feb. 11, 1971) "or any other calendar day designated as a holiday by Federal statute"
85 1         5 return 'Juneteenth National Independence Day Observed'; #Friday before June 19
86             } elsif ($year >= 2021 and $month == 6 and $day == 19) { #Juneteenth National Independence Day Act (June 17, 2021)
87 7         24 return 'Juneteenth National Independence Day'; #June 19
88             } elsif ($year >= 2021 and $month == 6 and $day == 20 and $wday == 1) { #Executive Order 11582 (Feb. 11, 1971)
89 4         13 return 'Juneteenth National Independence Day Observed'; #Monday afer June 19
90              
91             #Independence Day
92              
93             } elsif ($year >= 1971 and $month == 7 and $day == 3 and $wday == 5) { #Executive Order 11582 (Feb. 11, 1971)
94 0         0 return 'Independence Day Observed'; #Friday before July 4
95             } elsif ($year >= 1870 and $month == 7 and $day == 4) {
96 7         24 return 'Independence Day'; #July 4
97             } elsif ($year >= 1909 and $month == 7 and $day == 5 and $wday == 1) { #Executive Order 1076 (May 22, 1909)
98 1         5 return 'Independence Day Observed'; #Monday afer July 4
99              
100             ## Labor Day
101             # By 1894, thirty U.S. states were already officially celebrating Labor Day. In that year,
102             # Congress passed a bill recognizing the first Monday of September as Labor Day and making
103             # it an official federal holiday. President Grover Cleveland signed the bill into law on
104             # June 28.[15][4] The federal law, however, only made it a holiday for federal workers.
105              
106             } elsif ($year >= 1894 and $month == 9 and $day >= 1 and $day <= 7 and $wday == 1) {
107 8         32 return 'Labor Day'; #the first Monday in September
108              
109             ##Columbus Day
110             } elsif ($year >= 1971 and $month == 10 and $day >= 8 and $day <= 14 and $wday == 1) { #Uniform Monday Holiday Act
111 8         84 return 'Columbus Day'; #the second Monday in October
112              
113             ##Veterans Day (>1954)/Armistice Day (<1954)
114             #November 11 (1938 to 1970 and >1978)
115             #fourth Monday in October (1971 to 1977)
116              
117             } elsif ($year >= 1938 and $year < 1954 and $month == 11 and $day == 11) {
118 0         0 return 'Armistice Day'; #November 11
119             } elsif ($year >= 1945 and $year < 1954 and $month == 11 and $day == 12 and $wday == 1) { #Executive Order 9636 (October 3, 1945)
120 0         0 return 'Armistice Day Observed'; #Monday afer November 11
121              
122             } elsif ($year >= 1954 and $year < 1971 and $month == 11 and $day == 11) {
123 1         6 return 'Veterans Day'; #November 11
124             } elsif ($year >= 1954 and $year < 1971 and $month == 11 and $day == 12 and $wday == 1) { #Executive Order 9636 (October 3, 1945)
125 0         0 return 'Veterans Day Observed'; #Monday afer November 11
126              
127             } elsif ($year >= 1971 and $year < 1978 and $month == 10 and $day >= 22 and $day <= 28 and $wday == 1) {
128 7         39 return 'Veterans Day'; #fourth Monday in October
129              
130             } elsif ($year >= 1978 and $month == 11 and $day == 10 and $wday == 5) { #Executive Order 11582 (Feb. 11, 1971)
131 1         11 return 'Veterans Day Observed'; #Friday before November 11
132             } elsif ($year >= 1978 and $month == 11 and $day == 11) {
133 17         91 return 'Veterans Day'; #November 11
134             } elsif ($year >= 1978 and $month == 11 and $day == 12 and $wday == 1) { #Executive Order 11582 (Feb. 11, 1971)
135 0         0 return 'Veterans Day Observed'; #Monday afer November 11
136              
137             ##Thanksgiving Day
138             } elsif ($year >= 1870 and $month == 11 and $day >= 22 and $day <= 28 and $wday == 4) {
139 8         29 return 'Thanksgiving Day'; #the fourth Thursday in November.
140              
141             ##Christmas Day
142             } elsif ($year >= 1971 and $month == 12 and $day == 24 and $wday == 5) { #Executive Order 11582 (Feb. 11, 1971)
143 1         5 return 'Christmas Day Observed'; #Friday before December 25
144             } elsif ($year >= 1870 and $month == 12 and $day == 25) {
145 7         28 return 'Christmas Day'; #December 25
146             } elsif ($year >= 1909 and $month == 12 and $day == 26 and $wday == 1) { #Executive Order 9636 (October 3, 1945)
147 4         11 return 'Christmas Day Observed'; #Monday afer December 25
148              
149             } elsif ($year >= 1971 and $month == 12 and $day == 31 and $wday == 5) { #Executive Order 11582 (Feb. 11, 1971)
150 0         0 return q{New Year's Day Observed}; #Friday before January 1
151              
152             } else {
153 262         732 return undef;
154             }
155             }
156              
157             =head2 is_us_holiday
158              
159             Wrapper around is_holiday function per the API specification. See L
160              
161             =cut
162              
163 4     4 1 913 sub is_us_holiday {return is_holiday(@_)};
164              
165             =head2 holidays
166              
167             Returns a hash reference containing all of the holidays in specied year. The keys for the returned hash reference are the dates where 2-digit month and 2-digit day are concatenated.
168              
169             use Date::Holidays::US qw{holidays};
170             my $year = 2022;
171             my $holidays_href = holidays($year);
172             foreach my $key (sort keys %$holidays_href) { #e.g. "0101", "0619","0704"
173             my ($month, $day) = $key =~ m/\A([0-9]{2})([0-9]{2})\Z/;
174             my $name = $holidays_href->{$key};
175             print "Year: $year, Month: $month, Day: $day, Name: $name\n";
176             }
177              
178             =cut
179              
180             sub holidays {
181 5     5 1 12 my $year = shift;
182 5         8 my %holidays = ();
183             #All possible dates that could be a holiday
184 5         79 my @dates = qw{
185             0101 0102
186             0115 0116 0117 0118 0119 0120 0121
187             0222
188             0215 0216 0217 0218 0219 0220 0221
189             0525 0526 0527 0528 0529 0530 0531
190             0618 0619 0620
191             0703 0704 0705
192             0901 0902 0903 0904 0905 0906
193             1007 1008 1009 1010 1011 1012 1013
194             1110 1111 1112
195             1022 1023 1024 1025 1026 1027 1028
196             1122 1123 1124 1125 1126 1127 1128
197             1224 1225 1226
198             1231
199             };
200 5         9 foreach my $date (@dates) {
201 320         1385 my ($month, $day) = $date =~ m/\A(..)(..)\Z/;
202 320         586 my $name = is_holiday($year, $month, $day);
203 320 100       782 $holidays{$date} = $name if defined($name);
204             }
205 5         34 return \%holidays;
206             }
207              
208             =head2 us_holidays
209              
210             Wrapper around holidays function per the API specification. See L
211              
212             =cut
213              
214 2     2 1 7 sub us_holidays {return holidays(@_)};
215              
216             =head1 TODO
217              
218             Add Federal Holidays for President mark of respect holidays (e.g. 2007-01-02 for Gerald R. Ford, the thirty-eighth President of the United States)
219              
220             =head1 SEE ALSO
221              
222             L, L
223              
224             =head1 AUTHOR
225              
226             Michael R. Davis, MRDVT
227              
228             =head1 COPYRIGHT AND LICENSE
229              
230             Copyright (C) 2022 by Michael R. Davis
231              
232             MIT License
233              
234             =cut
235              
236             1;