File Coverage

blib/lib/Date/Holidays/CW.pm
Criterion Covered Total %
statement 74 77 96.1
branch 24 30 80.0
condition 10 20 50.0
subroutine 12 12 100.0
pod 3 3 100.0
total 123 142 86.6


line stmt bran cond sub pod time code
1 2     2   307603 use utf8;
  2         571  
  2         12  
2             package Date::Holidays::CW;
3             our $VERSION = '0.004';
4 2     2   113 use strict;
  2         5  
  2         38  
5 2     2   17 use warnings;
  2         4  
  2         84  
6              
7             # ABSTRACT: Curaçao's official holidays
8              
9 2     2   10 use Exporter qw(import);
  2         2  
  2         109  
10              
11             our @EXPORT = qw(
12             holidays
13             is_holiday
14             is_holiday_dt
15             );
16              
17 2     2   9 use base qw(Date::Holidays::Abstract);
  2         3  
  2         1236  
18 2     2   17025 use DateTime::Event::Easter;
  2         1203953  
  2         153  
19 2     2   22 use DateTime;
  2         5  
  2         1763  
20              
21             my %FIXED_DATES = (
22             newyears => {
23             m => 1,
24             d => 1,
25             pap => "A\x{00f1}a Nobo",
26             nl => 'Nieuwjaarsdag',
27             en => 'New years day',
28             },
29             flagday => {
30             m => 7,
31             d => 2,
32             pap => 'Dia di Himno i Bandera',
33             nl => 'Dag van volkslied en vlag',
34             en => 'National Anthem and Flag day',
35             },
36             isladay => {
37             m => 10,
38             d => 2,
39             pap => "Dia di Pais K\x{00f2}rsou",
40             nl => 'Dag van het land Curaçao',
41             en => 'Day of the country Curaçao',
42             },
43             wimlex => {
44             m => 4,
45             d => 27,
46             nl => 'Koningsdag',
47             en => 'Kings day',
48             pap => 'Dia di Rei',
49              
50             # change day of week if it falls on a sunday
51             dow => { 7 => -1 },
52             year_started => 2014,
53             },
54             'minna-princess' => {
55             m => 8,
56             d => 31,
57             nl => 'Prinsessedag',
58             en => "Princess's day",
59             pap => 'Dia di Prensesa',
60              
61             # change day of week if it falls on a sunday
62             dow => { 7 => 1 },
63             year_started => 1885,
64             year_ended => 1890,
65             },
66             'minna-queen' => {
67             m => 8,
68             d => 31,
69             nl => 'Koninginnedag',
70             en => "Queen's day",
71             pap => 'Dia di Reina',
72              
73             # change day of week if it falls on a sunday
74             dow => { 7 => 1 },
75             year_started => 1891,
76             year_ended => 1948,
77             },
78             'juliana-beatrix' => {
79             m => 4,
80             d => 30,
81             nl => 'Koninginnedag',
82             en => "Queen's day",
83             pap => 'Dia di Reina',
84              
85             # change day of week if it falls on a sunday
86             dow => { 7 => 1 },
87             year_started => 1949,
88             year_ended => 1979,
89             },
90             'juliana-beatrix-2' => {
91             m => 4,
92             d => 30,
93             nl => 'Koninginnedag',
94             en => "Queen's day",
95             pap => 'Dia di Reina',
96              
97             # change day of week if it falls on a sunday
98             dow => { 7 => -1 },
99             year_started => 1980,
100             year_ended => 2013,
101             },
102             labor => {
103             m => 5,
104             d => 1,
105             pap => 'Dia di Labor/Dia di Obrero',
106             nl => 'Dag van de arbeid',
107             en => 'Labor day',
108             dow => { 7 => -1 },
109             },
110             xmas => {
111             m => 12,
112             d => 25,
113             pap => 'Pasku di Nacemento',
114             nl => 'Kerst',
115             en => 'Christmas',
116             },
117             boxing => {
118             m => 12,
119             d => 26,
120             pap => 'Di dos dia di Pasku di Nacemento',
121             nl => 'Tweede kerstdag',
122             en => 'Boxing day',
123             },
124             );
125              
126             my %EASTER_BASED = (
127             'carnaval' => {
128             d => -48,
129             pap => 'Karnaval',
130             nl => 'De maandag na de Grote Karnaval',
131             en => 'The monday after big carnaval',
132             },
133             goodfri => {
134             d => -2,
135             pap => 'Bierna Santo',
136             nl => 'Goede vrijdag',
137             en => 'Good friday',
138             },
139             easter => {
140             d => 0,
141             pap => 'Pasku Grandi',
142             nl => 'Pasen',
143             en => 'Easter',
144             },
145             easter2 => {
146             d => 1,
147             pap => 'Pasku Grandi',
148             nl => 'Tweede paasdag',
149             en => 'Second day of easter',
150             },
151             ascension => {
152             d => 39,
153             pap => 'Dia di Asuncion',
154             nl => 'Hemelvaartsdag',
155             en => 'Ascension day',
156             },
157             );
158              
159             my %cache;
160              
161             sub holidays {
162 20     20 1 271671 my $year = shift;
163 20         55 my %args = @_;
164              
165 20   66     91 $year //= DateTime->now()->year;
166              
167 20         477 my $key = $year;
168 20 50       75 if ($args{gov}) {
169 0         0 $key .= 'gov';
170             }
171              
172 20 100       120 return $cache{$key} if $cache{$key};
173              
174 10         26 my %h;
175 10         70 foreach (keys %FIXED_DATES) {
176 110         1355 my $holiday = $FIXED_DATES{$_};
177              
178 110 100       390 if (my $end = $holiday->{year_ended}) {
179 40 100       132 next if $year > $end;
180             }
181 76 100       230 if (my $start = $holiday->{year_started}) {
182 16 100       65 next if $year < $start;
183             }
184              
185 70 50 33     538 if (my $int = $holiday->{interval}) {
    50          
186 0 0 0     0 next if !$args{gov} && $year % $int != 0;
187             }
188             # Skip government only holidays
189             # This is due to "Algemene termijnwet" which is also valid on the BES
190             # islands: https://wetten.overheid.nl/BWBR0002448/2010-10-10
191             elsif (!$args{gov} && $holiday->{gov}) {
192 0         0 next;
193             }
194              
195 70         220 my $dt = _to_date($holiday->{d}, $holiday->{m}, $year);
196              
197 70 100       32977 if (my $dow = $holiday->{dow}) {
198 20         86 my $cur = $dt->dow();
199 20         144 foreach (keys %$dow) {
200 20 100       94 next unless $cur == $_;
201 3         19 $dt->add(days => $dow->{$_});
202 3         3698 last;
203             }
204             }
205              
206 70         238 _to_holidays(\%h, $dt, $holiday);
207             }
208              
209 10         257 my $dt = _to_date(1, 1, $year);
210 10         4641 foreach (keys %EASTER_BASED) {
211 50         944 my $holiday = $EASTER_BASED{$_};
212 50 50 33     423 next if !$args{gov} && $holiday->{gov};
213              
214             my $easter = DateTime::Event::Easter->new(
215             easter => 'western',
216             day => $holiday->{d}
217 50         290 );
218 50         12568 my $dt = $easter->following($dt);
219 50         142095 _to_holidays(\%h, $dt, $holiday);
220             }
221              
222 10         263 $cache{$key} = \%h;
223              
224 10         71 return \%h;
225             }
226              
227             sub _to_holidays {
228 120     120   349 my ($cache, $dt, $info) = @_;
229             $cache->{ sprintf("%02i", $dt->day) . sprintf("%02i", $dt->month) }
230 120         267 = [map { $info->{$_} } qw(pap nl en)];
  360         1335  
231             }
232              
233             sub _to_date {
234 97     97   230 my ($day, $month, $year) = @_;
235 97         412 return DateTime->new(
236             day => $day,
237             month => $month,
238             year => $year,
239             hour => 0,
240             minute => 0,
241             second => 0,
242             time_zone => 'UTC',
243             );
244             }
245              
246             sub is_holiday {
247 17     17 1 6323 my $year = shift;
248 17         40 my $month = shift;
249 17         29 my $day = shift;
250              
251 17         55 my $dt = _to_date($day, $month, $year);
252 17         8044 return is_holiday_dt($dt, @_);
253             }
254              
255             sub is_holiday_dt {
256 18     18 1 478 my $dt = shift;
257              
258 18         58 my %args = @_;
259              
260 18         65 my $holidays = holidays($dt->year, @_);
261 18         62 my $key = sprintf("%02i", $dt->day) . sprintf("%02i", $dt->month);
262              
263 18 100       306 if (exists $holidays->{$key}) {
264 16   100     93 my $lang = lc(delete $args{lang} // 'pap');
265 16 100 66     86 if ($lang eq 'nl' || $lang eq 'nld') {
266 1         10 return $holidays->{$key}[1];
267             }
268 15 100 66     75 if ($lang eq 'en' || $lang eq 'eng') {
269 1         9 return $holidays->{$key}[2];
270             }
271              
272             # default to pap
273 14         169 return $holidays->{$key}[0];
274             }
275 2         28 return;
276             }
277              
278             "Sinti pa bo mes";
279              
280             __END__
281              
282             =pod
283              
284             =encoding UTF-8
285              
286             =head1 NAME
287              
288             Date::Holidays::CW - Curaçao's official holidays
289              
290             =head1 VERSION
291              
292             version 0.004
293              
294             =head1 SYNOPSIS
295              
296             use Date::Holidays::CW;
297              
298             if (my $thing = is_holiday(2020, 10, 2, lang => 'en')) {
299             print "It is $thing!", $/; # prints 'Day of the country Curaçao!'
300             }
301              
302             =head1 DESCRIPTION
303              
304             A L<Date::Holidays> family member from Curaçao
305              
306             =head1 METHODS
307              
308             This module implements the C<is_holiday> and C<holiday> functions from
309             L<Date::Holidays::Abstract>.
310              
311             =head2 is_holiday(yyyy, mm, dd, %additional)
312              
313             is_holiday(
314             '2020', '4', '30',
315             gov => 1, # Important for government institutions
316             lang => 'en' # defaults to pap, alternatively nl/nld or en/eng can be used.
317             );
318              
319             =head2 is_holiday_dt(dt, %additional)
320              
321             is_holiday_dt(
322             DateTime->new(
323             year => 2020,
324             month => 4,
325             day => 30,
326             time_zone => 'America/Curacao',
327             ),
328             gov => 1, # Important for government institutions
329             lang => 'en' # defaults to pap, alternatively nl/nld or en/eng can be used.
330             );
331              
332             =head2 holidays(yyyy, gov => 1)
333              
334             holidays('2022', gov => 1);
335              
336             Similar API to the other functions, returns an hashref for the year.
337              
338             =head1 UTF-8
339              
340             Be aware that we return UTF-8. Please set your enconding to UTF-8, otherwise
341             you may see weird things.
342              
343             =head1 AUTHOR
344              
345             Wesley Schwengle <waterkip@cpan.org>
346              
347             =head1 COPYRIGHT AND LICENSE
348              
349             This software is Copyright (c) 2024 by Wesley Schwengle.
350              
351             This is free software, licensed under:
352              
353             The (three-clause) BSD License
354              
355             =cut