File Coverage

blib/lib/Date/Holidays/AU.pm
Criterion Covered Total %
statement 677 677 100.0
branch 286 286 100.0
condition 39 39 100.0
subroutine 41 41 100.0
pod 2 2 100.0
total 1045 1045 100.0


line stmt bran cond sub pod time code
1             package Date::Holidays::AU;
2              
3 1     1   541 use strict;
  1         2  
  1         29  
4 1     1   5 use warnings;
  1         2  
  1         23  
5              
6 1     1   508 use Time::Local();
  1         2444  
  1         24  
7 1     1   446 use Date::Easter();
  1         765  
  1         22  
8 1     1   6 use Exporter();
  1         2  
  1         14  
9 1     1   4 use Carp();
  1         2  
  1         17  
10              
11 1     1   4 use base qw(Exporter);
  1         2  
  1         7091  
12             our @EXPORT_OK = qw(is_holiday holidays);
13             our $VERSION = '0.29';
14              
15 9     9   1039 sub _DEFAULT_STATE { return 'VIC' }
16              
17             my %allowed_states = (
18             VIC => 1,
19             WA => 1,
20             NT => 1,
21             QLD => 1,
22             TAS => 1,
23             NSW => 1,
24             SA => 1,
25             ACT => 1,
26             );
27              
28             sub holidays {
29 159     159 1 3172 my (%params) = @_;
30 159 100 100     744 if ( ( exists $params{year} ) && ( defined $params{year} ) ) {
31             }
32             else {
33 2         62 $params{year} = (localtime)[5];
34 2         10 $params{year} += 1900;
35             }
36 159 100       972 if ( $params{year} !~ /^\d{1,4}$/smx ) {
37 2         212 Carp::croak(
38             q[Year must be numeric and from one to four digits, eg '2004']);
39             }
40 157         287 my $year = $params{year};
41 157 100       318 if ( !defined $params{state} ) {
42 4         11 Carp::carp( 'State not defined, setting state to default: '
43             . _DEFAULT_STATE() );
44 4         24 $params{state} = _DEFAULT_STATE();
45             }
46              
47 157         298 my $state = uc $params{state};
48 157 100       364 if ( !$allowed_states{$state} ) {
49 1         108 Carp::croak(
50             q[State must be one of 'VIC','WA','NT','QLD','TAS','NSW','SA','ACT']
51             );
52             }
53 156         235 my $concat = $state;
54 156         629 foreach my $key ( sort { $a cmp $b } keys %params ) {
  232         624  
55 361 100       716 next if ( $key eq 'year' );
56 205 100       409 next if ( $key eq 'state' );
57 49 100       112 next if ( !$params{$key} );
58 44 100       92 if ( ref $params{$key} ) {
59 32 100       78 if ( ( ref $params{$key} ) eq 'ARRAY' ) {
60 30         53 $concat .= '_' . $key;
61 30         40 foreach my $element ( @{ $params{$key} } ) {
  30         55  
62 34         71 $concat .= '_' . $element;
63             }
64             }
65             }
66             else {
67 12         40 $concat .= '_' . $key . '_' . $params{$key};
68             }
69 44         83 $concat = lc $concat;
70 44         590 $concat =~ s/\s*//smxg;
71             }
72 156         250 my %holidays;
73 156 100       298 if ( $state eq 'TAS' ) {
74 42 100       104 if ( exists $params{holidays} ) {
75 32 100 100     128 if ( ( ref $params{holidays} )
76             && ( ( ref $params{holidays} ) eq 'ARRAY' ) )
77             {
78 30         51 foreach my $allowed ( @{ $params{holidays} } ) {
  30         67  
79 34         65 $allowed = lc $allowed;
80 34         259 $allowed =~ s/\s*//smxg;
81 34 100       93 if ( $allowed eq 'devonportcup' ) {
82 6         19 foreach my $holiday ( _compute_devonport_cup($year) )
83             { # TAS devonport cup
84 6         26 $holidays{$holiday} = 'Devonport Cup';
85             }
86             }
87             }
88             }
89             else {
90 2         293 Carp::croak(
91             q[Holidays parameter must be a reference to an array]);
92             }
93             }
94             }
95 154         505 foreach my $holiday ( _compute( 1, 1, $year, { 'day_in_lieu' => 1 } ) )
96             { # new years day
97 232 100       492 if ( $holiday eq '0101' ) {
98 154         473 $holidays{$holiday} = 'New Years Day';
99             }
100             else {
101 78         162 $holidays{$holiday} = 'New Years Day Holiday';
102             }
103             }
104 154         547 foreach my $holiday ( _compute( 26, 1, $year, { 'day_in_lieu' => 1 } ) )
105             { # australia day
106 168 100       369 if ( $holiday eq '0126' ) {
107 154         432 $holidays{$holiday} = 'Australia Day';
108             }
109             else {
110 14         41 $holidays{$holiday} = 'Australia Day Holiday';
111             }
112             }
113 154 100       651 if ( $state eq 'VIC' ) {
    100          
    100          
    100          
    100          
114 32         96 foreach my $holiday ( _compute_vic_labour_day($year) )
115             { # VIC labour day
116 32         107 $holidays{$holiday} = 'Labour Day';
117             }
118 32         109 foreach my $holiday ( _compute_vic_grand_final_eve_day($year) )
119             { # VIC grand final day
120 12         33 $holidays{$holiday} = 'Grand Final Eve';
121             }
122             }
123             elsif ( $state eq 'WA' ) {
124 31         85 foreach my $holiday ( _compute_wa_labour_day($year) ) { # WA labour day
125 31         92 $holidays{$holiday} = 'Labour Day';
126             }
127             }
128             elsif ( $state eq 'SA' ) {
129 6         23 foreach my $holiday ( _compute_sa_adelaide_cup_day($year) )
130             { # adelaide cup day
131 3         11 $holidays{$holiday} = 'Adelaide Cup Day';
132             }
133             }
134             elsif ( $state eq 'ACT' ) {
135 7         67 foreach my $holiday ( _compute_canberra_day($year) ) { # canberra day
136 7         27 $holidays{$holiday} = 'Canberra Day';
137             }
138             }
139             elsif ( $state eq 'TAS' ) {
140 40 100       102 if ( exists $params{holidays} ) {
141 30         40 foreach my $allowed ( @{ $params{holidays} } ) {
  30         66  
142 34         64 $allowed = lc $allowed;
143 34         310 $allowed =~ s/\s*//smxg;
144 34 100       138 if ( $allowed eq 'devonportcup' ) {
    100          
    100          
    100          
145 6         22 foreach my $holiday ( _compute_devonport_cup($year) )
146             { # TAS devonport cup
147 6         27 $holidays{$holiday} = 'Devonport Cup';
148             }
149             }
150             elsif ( $allowed eq 'hobartregatta' ) {
151 1         19 foreach my $holiday ( _compute_hobart_regatta($year) )
152             { # TAS hobart regatta
153 1         4 $holidays{$holiday} = 'Hobart Regatta';
154             }
155             }
156             elsif ( $allowed eq 'launcestoncup' ) {
157 4         10 foreach my $holiday ( _compute_launceston_cup($year) )
158             { # TAS launceston cup
159 4         17 $holidays{$holiday} = 'Launceston Cup';
160             }
161             }
162             elsif ( $allowed eq 'kingislandshow' ) {
163 1         6 foreach my $holiday ( _compute_king_island_show($year) )
164             { # TAS king island show
165 1         5 $holidays{$holiday} = 'King Island Show';
166             }
167             }
168             }
169             }
170 40         100 foreach my $holiday ( _compute_eight_hours_day($year) )
171             { # TAS eight hours day
172 40         114 $holidays{$holiday} = 'Eight Hours Day';
173             }
174             }
175 153         273 my $count = 0;
176 153         317 foreach my $holiday ( _compute_easter( $year, $state ) ) { # easter
177 652 100       1421 if ( $count == 0 ) {
    100          
    100          
    100          
178 153         340 $holidays{$holiday} = 'Good Friday';
179             }
180             elsif ( $count == 1 ) {
181 153         337 $holidays{$holiday} = 'Easter Saturday';
182             }
183             elsif ( $count == 2 ) {
184 153         292 $holidays{$holiday} = 'Easter Sunday';
185             }
186             elsif ( $count == 3 ) {
187 153         345 $holidays{$holiday} = 'Easter Monday';
188             }
189             else {
190 40         79 $holidays{$holiday} = 'Easter Tuesday';
191             }
192 652         927 $count += 1;
193             }
194 153 100 100     750 if ( ( $state eq 'VIC' ) || ( $state eq 'TAS' ) || ( $state eq 'NSW' ) ) {
      100        
195 86         190 foreach my $holiday ( _compute( 25, 4, $year ) ) { # ANZAC day
196 86         408 $holidays{$holiday} = 'Anzac Day';
197             }
198             }
199             else {
200 67         214 foreach my $holiday ( _compute( 25, 4, $year, { 'day_in_lieu' => 1 } ) )
201             { # ANZAC day
202 81 100       200 if ( $holiday eq '0425' ) {
203 67         215 $holidays{$holiday} = 'Anzac Day';
204             }
205             else {
206 14         36 $holidays{$holiday} = 'Anzac Day Holiday';
207             }
208             }
209             }
210 153 100       550 if ( $state eq 'SA' ) {
    100          
    100          
211 6         20 foreach my $holiday ( _compute_sa_volunteers_day($year) )
212             { # SA Volunteers day
213 3         11 $holidays{$holiday} = 'Volunteers Day';
214             }
215             }
216             elsif ( $state eq 'NT' ) {
217 15         54 foreach my $holiday ( _compute_nt_may_day($year) ) { # NT May day
218 15         46 $holidays{$holiday} = 'May Day';
219             }
220             }
221             elsif ( $state eq 'TAS' ) {
222 40 100       103 if ( exists $params{holidays} ) {
223 30         43 foreach my $allowed ( @{ $params{holidays} } ) {
  30         61  
224 34         65 $allowed = lc $allowed;
225 34         315 $allowed =~ s/\s*//smxg;
226 34 100       88 if ( $allowed eq 'agfest' ) {
227 2         9 foreach my $holiday ( _compute_agfest($year) )
228             { # TAS Agfest
229 2         10 $holidays{$holiday} = 'Agfest';
230             }
231             }
232             }
233             }
234             }
235 153 100       298 if ( $state eq 'WA' ) {
236 31         70 foreach my $holiday ( _compute_wa_foundation_day($year) )
237             { # WA Foundation day
238 31         95 $holidays{$holiday} = 'Foundation Day';
239             }
240             }
241             else {
242 122         263 foreach my $holiday ( _compute_royal_bday($year) )
243             { # King's Birthday day
244 122 100       265 if ( $year <= 2022 ) {
245 119         348 $holidays{$holiday} = q[Queen's Birthday];
246             }
247             else {
248 3         17 $holidays{$holiday} = q[King's Birthday];
249             }
250             }
251             }
252 153         281 my $holiday_hashref;
253 153 100       589 if ( $state eq 'VIC' ) {
    100          
    100          
    100          
    100          
    100          
    100          
254 31 100 100     109 if ( ( exists $params{no_melbourne_cup} )
255             && ( $params{no_melbourne_cup} ) )
256             {
257             }
258             else {
259 30         73 foreach my $holiday ( _compute_melbourne_cup_day($year) )
260             { # Melbourne Cup day
261 30         90 $holidays{$holiday} = 'Melbourne Cup Day';
262             }
263             }
264             }
265             elsif ( $state eq 'QLD' ) {
266 8 100 100     38 unless ( ( exists $params{no_show_day} )
267             && ( $params{no_show_day} ) )
268             {
269 7         31 foreach my $holiday ( _compute_qld_show_day($year) )
270             { # Queensland Show day
271 7         26 $holidays{$holiday} = 'Queensland Show Day';
272             }
273             }
274             }
275             elsif ( $state eq 'SA' ) {
276 6         19 foreach my $holiday ( _compute_nsw_sa_act_labour_day($year) )
277             { # SA labour day
278 6         23 $holidays{$holiday} = 'Labour Day';
279             }
280             }
281             elsif ( $state eq 'NT' ) {
282 15         44 foreach
283             my $holiday_hashref ( _compute_nt_show_day_hash( $year, \%params ) )
284             { # NT regional show days
285             $holidays{ $holiday_hashref->{date} } =
286 14         48 $holiday_hashref->{name};
287             }
288 14         56 foreach my $holiday ( _compute_nt_picnic_day($year) ) { # NT picnic day
289 14         43 $holidays{$holiday} = 'Picnic Day';
290             }
291             }
292             elsif ( $state eq 'WA' ) {
293 31         76 foreach my $holiday ( _compute_wa_royal_bday($year) )
294             { # WA Queens Birthday day
295 29 100       64 if ( $year <= 2022 ) {
296 26         79 $holidays{$holiday} = q[Queen's Birthday];
297             }
298             else {
299 3         10 $holidays{$holiday} = q[King's Birthday];
300             }
301             }
302             }
303             elsif ( $state eq 'ACT' ) {
304 7 100 100     30 if ( ( exists $params{include_bank_holiday} )
305             && ( $params{include_bank_holiday} ) )
306             {
307 1         5 foreach my $holiday ( _compute_nsw_act_bank_holiday($year) )
308             { # ACT bank holiday
309 1         4 $holidays{$holiday} = 'Bank Holiday';
310             }
311             }
312 7         27 foreach my $holiday ( _compute_nsw_sa_act_labour_day($year) )
313             { # ACT labour day
314 7         30 $holidays{$holiday} = 'Labour Day';
315             }
316             }
317             elsif ( $state eq 'TAS' ) {
318 40 100       93 if ( exists $params{holidays} ) {
319 30         40 foreach my $allowed ( @{ $params{holidays} } ) {
  30         69  
320 34         64 $allowed = lc $allowed;
321 34         704 $allowed =~ s/\s*//smxg;
322 34 100       160 if ( $allowed eq 'burnieshow' ) {
    100          
    100          
    100          
    100          
    100          
323 8         30 foreach my $holiday ( _compute_burnie_show($year) )
324             { # TAS burnie show day
325 8         28 $holidays{$holiday} = 'Burnie Show';
326             }
327             }
328             elsif ( $allowed eq 'launcestonshow' ) {
329 1         4 foreach my $holiday ( _compute_launceston_show($year) )
330             { # TAS launceston show day
331 1         6 $holidays{$holiday} = 'Launceston Show';
332             }
333             }
334             elsif ( $allowed eq 'flindersislandshow' ) {
335 1         7 foreach my $holiday ( _compute_flinders_island_show($year) )
336             { # TAS flinders island show day
337 1         4 $holidays{$holiday} = 'Flinders Island Show';
338             }
339             }
340             elsif ( $allowed eq 'hobartshow' ) {
341 3         11 foreach my $holiday ( _compute_hobart_show($year) )
342             { # TAS hobart show day
343 3         14 $holidays{$holiday} = 'Hobart Show';
344             }
345             }
346             elsif ( $allowed eq 'recreationday' ) {
347 3         12 foreach my $holiday ( _compute_recreation_day($year) )
348             { # TAS recreation day
349 3         14 $holidays{$holiday} = 'Recreation Day';
350             }
351             }
352             elsif ( $allowed eq 'devonportshow' ) {
353 4         11 foreach my $holiday ( _compute_devonport_show($year) )
354             { # TAS devonport show day
355 4         14 $holidays{$holiday} = 'Devonport Show';
356             }
357             }
358             }
359             }
360             }
361             else {
362 15 100 100     54 if ( ( exists $params{include_bank_holiday} )
363             && ( $params{include_bank_holiday} ) )
364             {
365 3         11 foreach my $holiday ( _compute_nsw_act_bank_holiday($year) )
366             { # NSW bank holiday
367 3         10 $holidays{$holiday} = 'Bank Holiday';
368             }
369             }
370 15         37 foreach my $holiday ( _compute_nsw_sa_act_labour_day($year) )
371             { # NSW labour day
372 15         49 $holidays{$holiday} = 'Labour Day';
373             }
374             }
375 150         369 foreach my $holiday_hashref ( _compute_christmas_hash( $year, $state ) )
376             { # christmas day + boxing day
377 461         1004 $holidays{ $holiday_hashref->{date} } = $holiday_hashref->{name};
378             }
379 150         686 return ( \%holidays );
380             }
381              
382             sub is_holiday {
383 151     151 1 4381 my ( $year, $month, $day, $state, $params ) = @_;
384 151 100       420 if ( !defined $state ) {
385 1         6 $state = _DEFAULT_STATE();
386             }
387 151         243 my $concat = $state;
388 151         218 foreach my $key ( sort { $a cmp $b } keys %{$params} ) {
  1         6  
  151         598  
389 49 100       226 next if ( !$params->{$key} );
390 44 100       104 if ( ref $params->{$key} ) {
391 32 100       93 if ( ( ref $params->{$key} ) eq 'ARRAY' ) {
392 30         62 $concat .= '_' . $key;
393 30         41 foreach my $element ( @{ $params->{$key} } ) {
  30         64  
394 34         69 $concat .= '_' . $element;
395             }
396             }
397             }
398             else {
399 12         37 $concat .= '_' . $key . '_' . $params->{$key};
400             }
401 44         98 $concat = lc $concat;
402 44         692 $concat =~ s/\s*//smxg;
403             }
404 151         271 my $holidays = holidays( 'year' => $year, 'state' => $state, %{$params} );
  151         331  
405 145         378 my $date = sprintf '%02d%02d', $month, $day;
406 145 100       331 if ( $holidays->{$date} ) {
407 110         921 return 1;
408             }
409             else {
410 35         274 return 0;
411             }
412             }
413              
414             my @days_in_month = ( 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 )
415             ; # feb will be calculated locally
416              
417             sub _compute_christmas_hash {
418 150     150   361 my ( $year, $state ) = @_;
419 150         200 my $day = 25;
420 150         224 my $month = 12;
421 150         414 my $date = Time::Local::timelocal( 0, 0, 0, $day, ( $month - 1 ), $year );
422 150         10188 my ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
423             localtime $date;
424 150         392 my $boxing_day = 'Boxing Day';
425 150 100       380 if ( $state eq 'SA' ) {
426 6         11 $boxing_day = 'Proclamation Day';
427             }
428 150         236 my @holidays;
429 150         775 push @holidays,
430             {
431             'name' => 'Christmas Day',
432             'date' => sprintf '%02d%02d',
433             $month, $day,
434             };
435 150         527 push @holidays,
436             {
437             'name' => $boxing_day,
438             'date' => sprintf '%02d%02d',
439             $month, ( $day + 1 ),
440             };
441 150 100       490 if ( $wday == 5 ) { # Christmas is on a Friday
    100          
    100          
442 8         40 push @holidays,
443             {
444             'name' => "$boxing_day Holiday",
445             'date' => sprintf '%02d%02d',
446             $month, ( $day + 2 ),
447             };
448 8 100 100     36 if ( ( $state eq 'NSW' ) && ( $year > 2011 ) ) {
449 1         6 push @holidays,
450             {
451             'name' => 'Additional Day',
452             'date' => sprintf '%02d%02d',
453             $month, ( $day + 3 ),
454             };
455             }
456             }
457             elsif ( $wday == 6 ) { # Christmas is on a Saturday
458 46         188 push @holidays,
459             {
460             'name' => 'Christmas Day Holiday',
461             'date' => sprintf '%02d%02d',
462             $month, ( $day + 2 ),
463             };
464 46         201 push @holidays,
465             {
466             'name' => "$boxing_day Holiday",
467             'date' => sprintf '%02d%02d',
468             $month, ( $day + 3 ),
469             };
470 46 100 100     157 if ( ( $state eq 'NSW' ) && ( $year > 2011 ) ) {
471 1         6 push @holidays,
472             {
473             'name' => 'Additional Day',
474             'date' => sprintf '%02d%02d',
475             $month, ( $day + 4 ),
476             };
477             }
478             }
479             elsif ( $wday == 0 ) { # Christmas is on a Sunday
480 58         204 push @holidays,
481             {
482             'name' => 'Christmas Day Holiday',
483             'date' => sprintf '%02d%02d',
484             $month, ( $day + 2 ),
485             };
486 58 100 100     183 if ( ( $state eq 'NSW' ) && ( $year > 2011 ) ) {
487 1         6 push @holidays,
488             {
489             'name' => 'Additional Day',
490             'date' => sprintf '%02d%02d',
491             $month, ( $day + 3 ),
492             };
493             }
494             }
495 150         511 return @holidays;
496             }
497              
498             sub _compute_nt_show_day_hash {
499 15     15   32 my ( $year, $params ) = @_;
500 15         196 my %nt_show_day = (
501             alicesprings =>
502             { name => 'Alice Springs Show Day', month => 6, num_fridays => 1 },
503             tennantcreek =>
504             { name => 'Tennant Creek Show Day', month => 6, num_fridays => 2 },
505             katherine =>
506             { name => 'Katherine Show Day', month => 6, num_fridays => 3 },
507             darwin => { name => 'Darwin Show Day', month => 6, num_fridays => 4 },
508             borroloola =>
509             { name => 'Borrolooda Show Day', month => 7, num_fridays => 4 },
510             );
511 15         36 my ( $month, $num_fridays, $name );
512 15 100 100     61 if ( ( exists $params->{region} ) && ( defined $params->{region} ) ) {
513 5         12 my $region = lc $params->{region};
514 5         49 $region =~ s/\s*//smxg;
515 5 100       15 if ( $nt_show_day{$region} ) {
516 4         9 $name = $nt_show_day{$region}{name};
517 4         7 $month = $nt_show_day{$region}{month};
518 4         8 $num_fridays = $nt_show_day{$region}{num_fridays};
519             }
520             else {
521 1         310 Carp::croak('Unknown region');
522             }
523             }
524             else {
525 10         22 $name = $nt_show_day{darwin}{name};
526 10         16 $month = $nt_show_day{darwin}{month};
527 10         21 $num_fridays = $nt_show_day{darwin}{num_fridays};
528             }
529 14         23 my $day = 1;
530 14         38 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
531 14         816 my $fridays = 0;
532 14         24 my ( $sec, $min, $hour, $wday, $yday, $isdst );
533 14         38 while ( $fridays < $num_fridays ) {
534 270         16400 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
535             localtime $date;
536 270 100       791 if ( $wday == 5 ) {
537 50         72 $fridays += 1;
538             }
539 270 100       499 if ( $fridays < $num_fridays ) {
540 256         337 $day += 1;
541 256         632 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
542             }
543             }
544 14         97 my @holidays = (
545             {
546             name => $name,
547             date => sprintf '%02d%02d',
548             ( $month + 1 ), $day,
549             }
550             );
551 14         92 return @holidays;
552             }
553              
554             sub _compute_qld_show_day
555             { # second wednesday in august, except when there are five wednesdays in august when it is the third wednesday
556 7     7   18 my ($year) = @_;
557 7         13 my $day = 1;
558 7         12 my $month = 7;
559 7         21 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
560 7         417 my $wednesdays = 0;
561 7         18 my ( $sec, $min, $hour, $wday, $yday, $isdst );
562 7         0 my $num_wednesdays;
563 7         108 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
564             localtime $date;
565              
566 7 100 100     47 if ( ( $wday >= 1 ) && ( $wday <= 3 ) ) {
567 5         12 $num_wednesdays = 3;
568             }
569             else {
570 2         4 $num_wednesdays = 2;
571             }
572 7         16 while ( $wednesdays < $num_wednesdays ) {
573 103         6209 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
574             localtime $date;
575 103 100       328 if ( $wday == 3 ) {
576 19         26 $wednesdays += 1;
577             }
578 103 100       189 if ( $wednesdays < $num_wednesdays ) {
579 96         120 $day += 1;
580 96         239 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
581             }
582             }
583 7         42 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
584             }
585              
586             sub _compute_devonport_show
587             { # friday nearest last day in november, but not later than first day in december
588 4     4   10 my ($year) = @_;
589 4         6 my $month = 10;
590 4         20 my $day = $days_in_month[$month];
591 4         16 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
592 4         239 my ( $sec, $min, $hour, $wday, $yday, $isdst );
593 4         62 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
594             localtime $date;
595 4 100       17 if ( $wday == 4 ) { # thursday
596 1         4 $day = 1;
597 1         2 $month = 11;
598             }
599             else {
600 3         19 my %adjustment = ( 0 => 2, 1 => 3, 2 => 4, 3 => 5, 5 => 0, 6 => 1 );
601 3         11 $day -= $adjustment{$wday};
602             }
603 4         21 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
604             }
605              
606             sub _compute_devonport_cup
607             { # wednesday not earlier than fifth and not later than the eleventh of January
608 12     12   25 my ($year) = @_;
609 12         19 my $day = 5;
610 12         20 my $month = 0;
611 12         39 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
612 12         758 my ( $sec, $min, $hour, $wday, $yday, $isdst );
613 12         174 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
614             localtime $date;
615 12         52 while ( $wday != 3 ) {
616 40         74 $day += 1;
617 40         98 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
618 40         2475 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
619             localtime $date;
620             }
621 12         82 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
622             }
623              
624             sub _compute_launceston_cup { # last wednesday in feb
625 4     4   10 my ($year) = @_;
626 4         6 my $month = 1;
627 4         7 my $day = 28;
628              
629 4 100       11 if ( $year % 4 ) {
630             }
631             else {
632 3 100       6 if ( $year % 100 ) {
633 1         3 $day = 29;
634             }
635             else {
636 2 100       10 if ( $year % 400 ) {
637             }
638             else {
639 1         6 $day = 29;
640             }
641             }
642             }
643 4         12 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
644 4         249 my $wednesdays = 0;
645 4         7 my ( $sec, $min, $hour, $wday, $yday, $isdst );
646 4         13 while ( $wednesdays < 1 ) {
647 15         804 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
648             localtime $date;
649 15 100       46 if ( $wday == 3 ) {
650 4         7 $wednesdays += 1;
651             }
652 15 100       34 if ( $wednesdays < 1 ) {
653 11         18 $day -= 1;
654 11         200 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
655             }
656             }
657 4         21 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
658             }
659              
660             sub _compute_eight_hours_day { # second monday in march
661 40     40   79 my ($year) = @_;
662 40         57 my $day = 1;
663 40         54 my $month = 2;
664 40         131 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
665 40         2141 my $mondays = 0;
666 40         66 my ( $sec, $min, $hour, $wday, $yday, $isdst );
667 40         95 while ( $mondays < 2 ) {
668 380         22108 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
669             localtime $date;
670 380 100       1194 if ( $wday == 1 ) {
671 80         124 $mondays += 1;
672             }
673 380 100       699 if ( $mondays < 2 ) {
674 340         430 $day += 1;
675 340         897 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
676             }
677             }
678 40         218 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
679             }
680              
681             sub _compute_king_island_show { # first tuesday in march
682 1     1   3 my ($year) = @_;
683 1         3 my $day = 1;
684 1         2 my $month = 2;
685 1         5 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
686 1         53 my $tuesdays = 0;
687 1         4 my ( $sec, $min, $hour, $wday, $yday, $isdst );
688 1         5 while ( $tuesdays < 1 ) {
689 2         95 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
690             localtime $date;
691 2 100       27 if ( $wday == 2 ) {
692 1         3 $tuesdays += 1;
693             }
694 2 100       8 if ( $tuesdays < 1 ) {
695 1         2 $day += 1;
696 1         4 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
697             }
698             }
699 1         9 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
700             }
701              
702             sub _compute_hobart_regatta { # second monday in feb
703 1     1   3 my ($year) = @_;
704 1         2 my $day = 1;
705 1         2 my $month = 1;
706 1         3 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
707 1         71 my $mondays = 0;
708 1         3 my ( $sec, $min, $hour, $wday, $yday, $isdst );
709 1         33 while ( $mondays < 2 ) {
710 9         546 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
711             localtime $date;
712 9 100       27 if ( $wday == 1 ) {
713 2         4 $mondays += 1;
714             }
715 9 100       22 if ( $mondays < 2 ) {
716 8         11 $day += 1;
717 8         21 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
718             }
719             }
720 1         7 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
721             }
722              
723             sub _compute_canberra_day { # third monday in march
724 7     7   17 my ($year) = @_;
725 7         43 my $day = 1;
726 7         10 my $month = 2;
727 7         23 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
728 7         364 my $mondays = 0;
729 7         14 my ( $sec, $min, $hour, $wday, $yday, $isdst );
730 7         22 while ( $mondays < 3 ) {
731 135         8309 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
732             localtime $date;
733 135 100       414 if ( $wday == 1 ) {
734 21         31 $mondays += 1;
735             }
736 135 100       290 if ( $mondays < 3 ) {
737 128         175 $day += 1;
738 128         321 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
739             }
740             }
741 7         42 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
742             }
743              
744             sub _compute_recreation_day { # first monday in november
745 3     3   8 my ($year) = @_;
746 3         6 my $day = 1;
747 3         8 my $month = 10;
748 3         10 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
749 3         162 my $mondays = 0;
750 3         9 my ( $sec, $min, $hour, $wday, $yday, $isdst );
751 3         11 while ( $mondays < 1 ) {
752 8         405 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
753             localtime $date;
754 8 100       37 if ( $wday == 1 ) {
755 3         6 $mondays += 1;
756             }
757 8 100       33 if ( $mondays < 1 ) {
758 5         7 $day += 1;
759 5         15 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
760             }
761             }
762 3         22 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
763             }
764              
765             sub _compute_melbourne_cup_day { # first tuesday in november
766 30     30   57 my ($year) = @_;
767 30         50 my $day = 1;
768 30         52 my $month = 10;
769 30         78 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
770 30         1642 my $tuesdays = 0;
771 30         52 my ( $sec, $min, $hour, $wday, $yday, $isdst );
772 30         79 while ( $tuesdays < 1 ) {
773 72         3642 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
774             localtime $date;
775 72 100       237 if ( $wday == 2 ) {
776 30         49 $tuesdays += 1;
777             }
778 72 100       187 if ( $tuesdays < 1 ) {
779 42         73 $day += 1;
780 42         124 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
781             }
782             }
783 30         158 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
784             }
785              
786             sub _compute_wa_foundation_day { # first monday in june
787 31     31   59 my ($year) = @_;
788 31         49 my $day = 1;
789 31         41 my $month = 5;
790 31         116 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
791 31         1736 my $mondays = 0;
792 31         81 my ( $sec, $min, $hour, $wday, $yday, $isdst );
793 31         79 while ( $mondays < 1 ) {
794 145         7836 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
795             localtime $date;
796 145 100       475 if ( $wday == 1 ) {
797 31         52 $mondays += 1;
798             }
799 145 100       304 if ( $mondays < 1 ) {
800 114         155 $day += 1;
801 114         290 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
802             }
803             }
804 31         162 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
805             }
806              
807             sub _compute_royal_bday { # second monday in june
808 122     122   417 my ($year) = @_;
809 122         157 my $day = 1;
810 122         164 my $month = 5;
811 122         275 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
812 122         6516 my $mondays = 0;
813 122         206 my ( $sec, $min, $hour, $wday, $yday, $isdst );
814 122         294 while ( $mondays < 2 ) {
815 1558         94600 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
816             localtime $date;
817 1558 100       5061 if ( $wday == 1 ) {
818 244         342 $mondays += 1;
819             }
820 1558 100       2793 if ( $mondays < 2 ) {
821 1436         1835 $day += 1;
822 1436         3738 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
823             }
824             }
825 122         699 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
826             }
827              
828             sub _compute_sa_volunteers_day { # third monday in may up excluding 2006
829 6     6   14 my ($year) = @_;
830 6 100       20 if ( $year == 2006 ) {
831 3         8 return ();
832             }
833 3         8 my $day = 1;
834 3         5 my $month = 4;
835 3         9 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
836 3         160 my $mondays = 0;
837 3         8 my ( $sec, $min, $hour, $wday, $yday, $isdst );
838 3         12 while ( $mondays < 3 ) {
839 48         2858 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
840             localtime $date;
841 48 100       141 if ( $wday == 1 ) {
842 9         13 $mondays += 1;
843             }
844 48 100       95 if ( $mondays < 3 ) {
845 45         63 $day += 1;
846 45         116 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
847             }
848             }
849 3         18 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
850             }
851              
852             sub _compute_sa_adelaide_cup_day { # second monday in march in 2006
853 6     6   18 my ($year) = @_;
854 6 100       19 if ( $year != 2006 ) {
855 3         10 return ();
856             }
857 3         6 my $day = 1;
858 3         6 my $month = 2;
859 3         9 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
860 3         163 my $mondays = 0;
861 3         7 my ( $sec, $min, $hour, $wday, $yday, $isdst );
862 3         22 while ( $mondays < 2 ) {
863 39         2305 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
864             localtime $date;
865 39 100       118 if ( $wday == 1 ) {
866 6         10 $mondays += 1;
867             }
868 39 100       88 if ( $mondays < 2 ) {
869 36         45 $day += 1;
870 36         101 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
871             }
872             }
873 3         22 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
874             }
875              
876             sub _compute_vic_labour_day { # second monday in march
877 32     32   67 my ($year) = @_;
878 32         55 my $day = 1;
879 32         46 my $month = 2;
880 32         112 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
881 32         1744 my $mondays = 0;
882 32         65 my ( $sec, $min, $hour, $wday, $yday, $isdst );
883 32         81 while ( $mondays < 2 ) {
884 381         23792 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
885             localtime $date;
886 381 100       1209 if ( $wday == 1 ) {
887 64         90 $mondays += 1;
888             }
889 381 100       717 if ( $mondays < 2 ) {
890 349         462 $day += 1;
891 349         947 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
892             }
893             }
894 32         186 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
895             }
896              
897             sub _compute_vic_grand_final_eve_day { # i have no words ...
898 32     32   62 my ($year) = @_;
899 32         49 my ( $day, $month );
900 32         419 my %grand_final_eve_day = (
901             2015 => { day => 2, month => 9 },
902             2016 => { day => 30, month => 8 },
903             2017 => { day => 29, month => 8 },
904             2018 => { day => 28, month => 8 },
905             2019 => { day => 27, month => 8 },
906             2020 => { day => 23, month => 9 }, # Technically "Thank you" day.
907             2021 => { day => 24, month => 8 },
908             2022 => { day => 23, month => 8 },
909             2023 => { day => 22, month => 8 },
910             );
911 32 100       102 if ( $year < 2015 ) {
    100          
912 19         109 return ();
913             }
914             elsif ( $grand_final_eve_day{$year} ) {
915 12         23 $day = $grand_final_eve_day{$year}{day};
916 12         18 $month = $grand_final_eve_day{$year}{month};
917             }
918             else {
919 1         275 Carp::croak(
920             q[Don't know how to calculate Grand Final Eve Day in VIC for this year]
921             );
922             }
923 12         81 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
924             }
925              
926             sub _compute_wa_labour_day { # first monday in march
927 31     31   62 my ($year) = @_;
928 31         47 my $day = 1;
929 31         42 my $month = 2;
930 31         78 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
931 31         1767 my $mondays = 0;
932 31         67 my ( $sec, $min, $hour, $wday, $yday, $isdst );
933 31         84 while ( $mondays < 1 ) {
934 134         7298 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
935             localtime $date;
936 134 100       447 if ( $wday == 1 ) {
937 31         48 $mondays += 1;
938             }
939 134 100       264 if ( $mondays < 1 ) {
940 103         146 $day += 1;
941 103         260 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
942             }
943             }
944 31         177 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
945             }
946              
947             sub _compute_nt_may_day { # first monday in may
948 15     15   33 my ($year) = @_;
949 15         24 my $day = 1;
950 15         19 my $month = 4;
951 15         42 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
952 15         795 my $mondays = 0;
953 15         27 my ( $sec, $min, $hour, $wday, $yday, $isdst );
954 15         40 while ( $mondays < 1 ) {
955 34         1600 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
956             localtime $date;
957 34 100       118 if ( $wday == 1 ) {
958 15         18 $mondays += 1;
959             }
960 34 100       92 if ( $mondays < 1 ) {
961 19         31 $day += 1;
962 19         48 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
963             }
964             }
965 15         82 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
966             }
967              
968             sub _compute_agfest { # friday following first thursday in may
969 2     2   6 my ($year) = @_;
970 2         6 my $day = 1;
971 2         5 my $month = 4;
972 2         8 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
973 2         109 my $thursdays = 0;
974 2         7 my ( $sec, $min, $hour, $wday, $yday, $isdst );
975 2         10 while ( $thursdays < 1 ) {
976 12         1546 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
977             localtime $date;
978 12 100       52 if ( $wday == 4 ) {
979 2         5 $thursdays += 1;
980             }
981 12 100       31 if ( $thursdays < 1 ) {
982 10         16 $day += 1;
983 10         34 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
984             }
985             }
986 2         20 return ( sprintf '%02d%02d', ( $month + 1 ), ( $day + 1 ) );
987             }
988              
989             sub _compute_burnie_show { # friday preceding first saturday in october
990 8     8   23 my ($year) = @_;
991 8         15 my $day = 1;
992 8         11 my $month = 9;
993 8         25 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
994 8         454 my $saturdays = 0;
995 8         17 my ( $sec, $min, $hour, $wday, $yday, $isdst );
996 8         21 while ( $saturdays < 1 ) {
997 15         601 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
998             localtime $date;
999 15 100       69 if ( $wday == 6 ) {
1000 8         15 $saturdays += 1;
1001             }
1002 15 100       37 if ( $saturdays < 1 ) {
1003 7         12 $day += 1;
1004 7         23 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1005             }
1006             }
1007 8 100       20 if ( $day == 1 ) {
1008 1         8 return ( sprintf '%02d%02d', $month, $days_in_month[ $month - 1 ] );
1009             }
1010             else {
1011 7         45 return ( sprintf '%02d%02d', ( $month + 1 ), ( $day - 1 ) );
1012             }
1013             }
1014              
1015             sub _compute_launceston_show { # thursday preceding second saturday in october
1016 1     1   4 my ($year) = @_;
1017 1         3 my $day = 1;
1018 1         3 my $month = 9;
1019 1         5 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1020 1         58 my $saturdays = 0;
1021 1         3 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1022 1         6 while ( $saturdays < 2 ) {
1023 9         577 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1024             localtime $date;
1025 9 100       30 if ( $wday == 6 ) {
1026 2         19 $saturdays += 1;
1027             }
1028 9 100       24 if ( $saturdays < 2 ) {
1029 8         13 $day += 1;
1030 8         22 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1031             }
1032             }
1033 1         9 return ( sprintf '%02d%02d', ( $month + 1 ), ( $day - 2 ) );
1034             }
1035              
1036             sub _compute_flinders_island_show { # friday preceding third saturday in october
1037 1     1   3 my ($year) = @_;
1038 1         4 my $day = 1;
1039 1         3 my $month = 9;
1040 1         4 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1041 1         56 my $saturdays = 0;
1042 1         4 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1043 1         6 while ( $saturdays < 3 ) {
1044 16         1015 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1045             localtime $date;
1046 16 100       55 if ( $wday == 6 ) {
1047 3         6 $saturdays += 1;
1048             }
1049 16 100       35 if ( $saturdays < 3 ) {
1050 15         35 $day += 1;
1051 15         38 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1052             }
1053             }
1054 1         9 return ( sprintf '%02d%02d', ( $month + 1 ), ( $day - 1 ) );
1055             }
1056              
1057             sub _compute_hobart_show { # thursday preceding fourth saturday in october
1058 3     3   9 my ($year) = @_;
1059 3         7 my $day = 1;
1060 3         5 my $month = 9;
1061 3         10 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1062 3         172 my $saturdays = 0;
1063 3         11 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1064 3         9 while ( $saturdays < 4 ) {
1065 69         4186 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1066             localtime $date;
1067 69 100       207 if ( $wday == 6 ) {
1068 12         22 $saturdays += 1;
1069             }
1070 69 100       222 if ( $saturdays < 4 ) {
1071 66         94 $day += 1;
1072 66         177 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1073             }
1074             }
1075 3         21 return ( sprintf '%02d%02d', ( $month + 1 ), ( $day - 2 ) );
1076             }
1077              
1078             sub _compute_nt_picnic_day { # first monday in august
1079 14     14   31 my ($year) = @_;
1080 14         21 my $day = 1;
1081 14         20 my $month = 7;
1082 14         45 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1083 14         770 my $mondays = 0;
1084 14         29 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1085 14         40 while ( $mondays < 1 ) {
1086 18         527 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1087             localtime $date;
1088 18 100       65 if ( $wday == 1 ) {
1089 14         24 $mondays += 1;
1090             }
1091 18 100       52 if ( $mondays < 1 ) {
1092 4         6 $day += 1;
1093 4         26 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1094             }
1095             }
1096 14         74 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
1097             }
1098              
1099             sub _compute_nsw_act_bank_holiday { # first monday in august
1100 4     4   8 my ($year) = @_;
1101 4         8 my $day = 1;
1102 4         5 my $month = 7;
1103 4         13 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1104 4         215 my $mondays = 0;
1105 4         7 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1106 4         13 while ( $mondays < 1 ) {
1107 10         433 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1108             localtime $date;
1109 10 100       35 if ( $wday == 1 ) {
1110 4         7 $mondays += 1;
1111             }
1112 10 100       27 if ( $mondays < 1 ) {
1113 6         8 $day += 1;
1114 6         21 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1115             }
1116             }
1117 4         23 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
1118             }
1119              
1120             sub _compute_nsw_sa_act_labour_day { # first monday in october
1121 28     28   61 my ($year) = @_;
1122 28         38 my $day = 1;
1123 28         41 my $month = 9;
1124 28         78 my $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1125 28         1814 my $mondays = 0;
1126 28         55 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1127 28         79 while ( $mondays < 1 ) {
1128 87         4161 ( $sec, $min, $hour, undef, undef, undef, $wday, $yday, $isdst ) =
1129             localtime $date;
1130 87 100       297 if ( $wday == 1 ) {
1131 28         42 $mondays += 1;
1132             }
1133 87 100       187 if ( $mondays < 1 ) {
1134 59         84 $day += 1;
1135 59         159 $date = Time::Local::timelocal( 0, 0, 0, $day, $month, $year );
1136             }
1137             }
1138 28         160 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
1139             }
1140              
1141             sub _compute_wa_royal_bday
1142             { # monday closest to 30 september??? Formula unknown. Seems to have a 9 day spread???
1143 31     31   56 my ($year) = @_;
1144 31         53 my ( $day, $month );
1145 31         735 my %wa_royal_bday = (
1146             2004 => { day => 4, month => 9 },
1147             2005 => { day => 26, month => 8 },
1148             2006 => { day => 2, month => 9 },
1149             2007 => { day => 1, month => 9 },
1150             2008 => { day => 29, month => 8 },
1151             2009 => { day => 28, month => 8 },
1152             2010 => { day => 27, month => 8 },
1153             2011 => { day => 28, month => 8 },
1154             2012 => { day => 1, month => 9 },
1155             2013 => { day => 30, month => 8 },
1156             2014 => { day => 29, month => 8 },
1157             2015 => { day => 28, month => 8 },
1158             2016 => { day => 26, month => 8 },
1159             2017 => { day => 25, month => 8 },
1160             2018 => { day => 24, month => 8 },
1161             2019 => { day => 30, month => 8 },
1162             2020 => { day => 28, month => 8 },
1163             2021 => { day => 27, month => 8 },
1164             2022 => { day => 26, month => 8 },
1165             2023 => { day => 25, month => 8 },
1166             2024 => { day => 23, month => 8 },
1167             );
1168 31 100       93 if ( $wa_royal_bday{$year} ) {
    100          
1169 29         49 $day = $wa_royal_bday{$year}{day};
1170 29         51 $month = $wa_royal_bday{$year}{month};
1171             }
1172             elsif ( $year <= 2022 ) {
1173 1         291 Carp::croak(
1174             q[Don't know how to calculate Queen's Birthday in WA for this year]
1175             );
1176             }
1177             else {
1178 1         128 Carp::croak(
1179             q[Don't know how to calculate King's Birthday in WA for this year]);
1180             }
1181 29         265 return ( sprintf '%02d%02d', ( $month + 1 ), $day );
1182             }
1183              
1184             sub _compute_easter {
1185 153     153   307 my ( $year, $state ) = @_;
1186 153         400 my ( $month, $day ) = Date::Easter::gregorian_easter($year);
1187 153         3056 my $date = Time::Local::timelocal( 0, 0, 0, $day, ( $month - 1 ), $year );
1188 153         8614 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1189 153         2365 ( $sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst ) =
1190             localtime $date;
1191 153         402 my @holidays;
1192              
1193             # good friday + easter saturday
1194 153 100       349 if ( $month == 2 ) { # march
1195 58         244 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day - 2 );
1196 58         159 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day - 1 );
1197             }
1198             else { # april
1199 95 100       239 if ( $day == 2 ) {
    100          
1200 1         12 push @holidays,
1201             sprintf '%02d%02d', $month, $days_in_month[ $month - 1 ];
1202 1         4 push @holidays, sprintf '%02d%02d', ( $month + 1 ), 1;
1203             }
1204             elsif ( $day == 1 ) {
1205 2         13 push @holidays,
1206             sprintf '%02d%02d', $month, ( $days_in_month[ $month - 1 ] - 1 );
1207 2         7 push @holidays,
1208             sprintf '%02d%02d', $month, ( $days_in_month[ $month - 1 ] );
1209             }
1210             else {
1211 92         375 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day - 2 );
1212 92         240 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day - 1 );
1213             }
1214             }
1215              
1216             # easter sunday
1217 153         359 push @holidays, sprintf '%02d%02d', ( $month + 1 ), $day;
1218              
1219             # easter monday
1220 153 100       276 if ( $month == 2 ) { # march
1221 58 100       155 if ( $day == $days_in_month[$month] ) {
1222 3         14 push @holidays, sprintf '%02d%02d', ( $month + 2 ), 1;
1223             }
1224             else {
1225 55         146 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day + 1 );
1226             }
1227             }
1228             else {
1229 95         206 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day + 1 );
1230             }
1231 153 100       377 if ( $state eq 'TAS' ) {
1232 40 100       74 if ( $month == 2 ) { # march
1233 5 100       26 if ( $day == $days_in_month[$month] ) {
    100          
1234 1         5 push @holidays, sprintf '%02d%02d', ( $month + 2 ), 2;
1235             }
1236             elsif ( ( $day + 1 ) == $days_in_month[$month] ) {
1237 1         3 push @holidays, sprintf '%02d%02d', ( $month + 2 ), 1;
1238             }
1239             else {
1240 3         11 push @holidays,
1241             sprintf '%02d%02d', ( $month + 1 ), ( $day + 2 );
1242             }
1243             }
1244             else {
1245 35         84 push @holidays, sprintf '%02d%02d', ( $month + 1 ), ( $day + 1 );
1246             }
1247             }
1248 153         638 return @holidays;
1249             }
1250              
1251             sub _compute {
1252 461     461   954 my ( $day, $month, $year, $params ) = @_;
1253 461         1299 my $date = Time::Local::timelocal( 0, 0, 0, $day, ( $month - 1 ), $year );
1254 461         27292 my ( $sec, $min, $hour, $wday, $yday, $isdst );
1255 461         0 my @holidays;
1256 461         1799 push @holidays, sprintf '%02d%02d', $month, $day;
1257 461 100       1179 if ( $params->{day_in_lieu} ) {
1258 375         5746 ( $sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst ) =
1259             localtime $date;
1260 375 100       1433 if ( $wday == 0 ) {
    100          
1261 37         66 $day += 1;
1262 37         132 push @holidays, sprintf '%02d%02d', ( $month + 1 ), $day;
1263             }
1264             elsif ( $wday == 6 ) {
1265 69         111 $day += 2;
1266 69         248 push @holidays, sprintf '%02d%02d', ( $month + 1 ), $day;
1267             }
1268             }
1269 461         1621 return (@holidays);
1270             }
1271              
1272             1;
1273              
1274             __END__