File Coverage

blib/lib/Date/Holidays/NL.pm
Criterion Covered Total %
statement 73 74 98.6
branch 29 30 96.6
condition 10 14 71.4
subroutine 11 11 100.0
pod 3 3 100.0
total 126 132 95.4


line stmt bran cond sub pod time code
1             our $VERSION = '0.007';
2             use strict;
3 1     1   83972 use warnings;
  1         9  
  1         25  
4 1     1   4  
  1         1  
  1         23  
5             # ABSTRACT: The Netherlands official holidays
6              
7             use Exporter qw(import);
8 1     1   4  
  1         1  
  1         42  
9             our @EXPORT = qw(
10             holidays
11             is_holiday
12             is_holiday_dt
13             );
14              
15             use base qw(Date::Holidays::Abstract);
16 1     1   8 use DateTime::Event::Easter;
  1         1  
  1         377  
17 1     1   7088 use DateTime;
  1         486569  
  1         43  
18 1     1   7  
  1         2  
  1         783  
19             my %FIXED_DATES = (
20             'newyears' => {
21             m => 1,
22             d => 1,
23             nl => 'Nieuwjaarsdag',
24             en => 'New years day',
25             },
26             'wimlex' => {
27             m => 4,
28             d => 27,
29             nl => 'Koningsdag',
30             en => 'Kings day',
31             # change day of week if it falls on a sunday
32             dow => { 7 => -1 },
33             year_started => 2014,
34             },
35             'minna-princess' => {
36             m => 8,
37             d => 31,
38             nl => 'Prinsessedag',
39             en => "Princess's day",
40              
41             # change day of week if it falls on a sunday
42             dow => { 7 => 1 },
43             year_started => 1885,
44             year_ended => 1890,
45             },
46             'minna-queen' => {
47             m => 8,
48             d => 31,
49             nl => 'Koninginnedag',
50             en => "Queen's day",
51              
52             # change day of week if it falls on a sunday
53             dow => { 7 => 1 },
54             year_started => 1891,
55             year_ended => 1948,
56             },
57             'juliana-beatrix' => {
58             m => 4,
59             d => 30,
60             nl => 'Koninginnedag',
61             en => "Queen's day",
62              
63             # change day of week if it falls on a sunday
64             dow => { 7 => 1 },
65             year_started => 1949,
66             year_ended => 1979,
67             },
68             'juliana-beatrix-2' => {
69             m => 4,
70             d => 30,
71             nl => 'Koninginnedag',
72             en => "Queen's day",
73              
74             # change day of week if it falls on a sunday
75             dow => { 7 => -1 },
76             year_started => 1980,
77             year_ended => 2013,
78             },
79             'liberation' => {
80             m => 5,
81             d => 5,
82             nl => 'Bevrijdingsdag',
83             en => 'Liberation day',
84             interval => 5, # Day off every five years
85             gov => 1, # Government works are having a day off tho
86             },
87             'xmas' => {
88             m => 12,
89             d => 25,
90             nl => 'Kerst',
91             en => 'Christmas',
92             },
93             'boxing' => {
94             m => 12,
95             d => 26,
96             nl => 'Tweede kerstdag',
97             en => 'Boxing day',
98             },
99             );
100              
101             my %EASTER_BASED = (
102             'goodfri' => {
103             d => -2,
104             nl => 'Goede vrijdag',
105             en => 'Good friday',
106             gov => 1,
107             },
108             'easter' => {
109             d => 0,
110             nl => 'Pasen',
111             en => 'Easter',
112             },
113             'easter2' => {
114             d => 1,
115             nl => 'Tweede paasdag',
116             en => 'Second day of easter',
117             },
118             'ascension' => {
119             d => 40,
120             nl => 'Hemelvaartsdag',
121             en => 'Ascension day',
122             },
123             pentecost => {
124             d => 49,
125             nl => 'Pinksteren',
126             en => 'Pentecost',
127             },
128             pentecost2 => {
129             d => 50,
130             nl => 'Tweede pinksterdag',
131             en => 'Pentecost',
132             }
133             );
134              
135             my %cache;
136              
137             my $year = shift;
138             my %args = @_;
139 14     14 1 1483  
140 14         24 $year //= DateTime->now()->year;
141              
142 14   33     29 my $key = $year;
143             if ($args{gov}) {
144 14         15 $key .= 'gov';
145 14 100       32 }
146 2         3  
147             return $cache{$key} if $cache{$key};
148              
149 14 100       33 my %h;
150             foreach (keys %FIXED_DATES) {
151 9         12 my $holiday = $FIXED_DATES{$_};
152 9         35  
153 81         468 if (my $int = $holiday->{interval}) {
154             if (!$args{gov}) {
155 81 100 66     226 next if $year % $int != 0;
    50          
156 9 100       18 }
157 7 100       18 }
158             # Skip government holidays, currently good friday only
159             # https://wetten.overheid.nl/BWBR0002448/2010-10-10
160             elsif (!$args{gov} && $holiday->{gov}) {
161             next;
162             }
163 0         0  
164             if (my $start = $holiday->{year_started}) {
165             next if $year < $start;
166 75 100       119 }
167 45 100       79  
168             if (my $end = $holiday->{year_ended}) {
169             next if $year > $end;
170 69 100       105 }
171 34 100       64  
172             my $dt = _to_date($holiday->{d}, $holiday->{m}, $year);
173              
174 39         68 if (my $dow = $holiday->{dow}) {
175             my $cur = $dt->dow();
176 39 100       10485 foreach (keys %$dow) {
177 9         22 next unless $cur == $_;
178 9         36 $dt->add(days => $dow->{$_});
179 9 100       24 last;
180 3         9 }
181 3         2253 }
182              
183             _to_holidays(\%h, $dt, $holiday);
184             }
185 39         72  
186             my $dt = _to_date(1, 1, $year);
187             foreach (keys %EASTER_BASED) {
188 9         72 my $holiday = $EASTER_BASED{$_};
189 9         2295 if (!$args{gov} && $holiday->{gov}) {
190 54         534 next;
191 54 100 100     190 }
192 7         13 my $easter = DateTime::Event::Easter->new(
193             easter => 'western',
194             day => $holiday->{d}
195             );
196             my $dt = $easter->following($dt);
197 47         128 _to_holidays(\%h, $dt, $holiday);
198 47         6588 }
199 47         76099  
200             $cache{$key} = \%h;
201              
202 9         126 return \%h;
203             }
204 9         34  
205             my ($cache, $dt, $info) = @_;
206             $cache->{ sprintf("%02i", $dt->day) . sprintf("%02i", $dt->month) }
207             = [map { $info->{$_} } qw(nl en)];
208 86     86   158 }
209              
210 86         133 my ($day, $month, $year) = @_;
  172         451  
211             return DateTime->new(
212             day => $day,
213             month => $month,
214 58     58   79 year => $year,
215 58         142 hour => 0,
216             minute => 0,
217             second => 0,
218             time_zone => 'UTC',
219             );
220             }
221              
222             my $year = shift;
223             my $month = shift;
224             my $day = shift;
225              
226             my $dt = _to_date($day, $month, $year);
227 10     10 1 577 return is_holiday_dt($dt, @_);
228 10         11 }
229 10         13  
230             my $dt = shift;
231 10         19  
232 10         2745 my %args = @_;
233              
234             my $holidays = holidays($dt->year, @_);
235             my $key = sprintf("%02i", $dt->day) . sprintf("%02i", $dt->month);
236 11     11 1 249  
237             if (exists $holidays->{$key}) {
238 11         17 my $lang = lc(delete $args{lang} // 'nl');
239             if ($lang eq 'en' || $lang eq 'eng') {
240 11         22 return $holidays->{$key}[1];
241 11         23 }
242             # default to dutch
243 11 100       99 return $holidays->{$key}[0];
244 9   100     28 }
245 9 100 66     30 return;
246 1         6 }
247              
248             'I always get my sin';
249 8         48  
250              
251 2         11 =pod
252              
253             =encoding UTF-8
254              
255             =head1 NAME
256              
257             Date::Holidays::NL - The Netherlands official holidays
258              
259             =head1 VERSION
260              
261             version 0.007
262              
263             =head1 SYNOPSIS
264              
265             use Date::Holidays::NL;
266              
267             if (my $thing = is_holiday(2020, 5, 5, lang => 'en')) {
268             print "It is $thing!", $/; # prints 'It is Liberation day!'
269             }
270              
271             =head1 DESCRIPTION
272              
273             A L<Date::Holidays> family member from the Netherlands
274              
275             =head1 METHODS
276              
277             This module implements the C<is_holiday>, C<is_holiday_dt> and C<holiday>
278             functions from L<Date::Holidays::Abstract>.
279              
280             All methods accept additional parameters. The most important is a flag called
281             C<gov>, when supplied you will get days that the government considers special
282             in regards to service terms. It essentially says that if a company or
283             government needs to contact you before or on that day it can be expedited to
284             the following work day. See the L<relevant
285             law|https://wetten.overheid.nl/BWBR0002448/2010-10-10> for more information.
286              
287             =head2 is_holiday(yyyy, mm, dd, %additional)
288              
289             is_holiday(
290             '2022', '05', '05',
291             gov => 1, # Important for government institutions
292             lang => 'en' # defaults to nl/nld, alternatively en/eng can be used.
293             );
294              
295             =head2 is_holiday_dt(dt, %additional)
296              
297             is_holiday_dt(
298             DateTime->new(
299             year => 2022,
300             month => 5,
301             day => 5,
302             time_zone => 'Europe/Amsterdam',
303             ),
304             gov => 1, # Important for government institutions
305             lang => 'en' # defaults to nl/nld, alternatively en/eng can be used.
306             );
307              
308             =head2 holidays(yyyy, gov => 1)
309              
310             holidays('2022', gov => 1);
311              
312             Similar API to the other functions, returns an hashref for the year.
313              
314             =head1 SEE ALSO
315              
316             =over
317              
318             =item https://wetten.overheid.nl/BWBR0002448/2010-10-10
319              
320             =back
321              
322             =head1 AUTHOR
323              
324             Wesley Schwengle <waterkip@cpan.org>
325              
326             =head1 COPYRIGHT AND LICENSE
327              
328             This software is Copyright (c) 2020 by Wesley Schwengle.
329              
330             This is free software, licensed under:
331              
332             The (three-clause) BSD License
333              
334             =cut