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