Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Australian Holidays #43

Merged
merged 5 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
parameters:
ignoreErrors:
-
message: "#^Cannot call method modify\\(\\) on Carbon\\\\CarbonImmutable\\|false\\.$#"
count: 1
path: src/Countries/Australia.php

-
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
count: 1
Expand Down
119 changes: 119 additions & 0 deletions src/Countries/Australia.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

namespace Spatie\Holidays\Countries;

use Carbon\CarbonImmutable;

class Australia extends Country
{
protected function __construct(
protected ?string $region = null,
) {
}

public function countryCode(): string
{
return 'au';
}

protected function allHolidays(int $year): array
{
return array_merge([
"New Year's Day" => '01-01',
'Australia Day' => '01-26',
'Anzac Day' => '04-25',
'Christmas Day' => '12-25',
'Boxing Day' => '12-26',
], $this->variableHolidays($year));
}

/** @return array<string, CarbonImmutable> */
protected function variableHolidays(int $year): array
{
$easter = $this->easter($year)->setTimezone('Australia/Sydney');

return [
'Good Friday' => $easter->subDays(2),
'Easter Monday' => $easter->addDay(),
// https://en.wikipedia.org/wiki/Public_holidays_in_Australia
...array_filter(match($this->region) {
'act' => [
'Canberra Day' => CarbonImmutable::parse("second monday of march {$year}"),
'Easter Saturday' => $easter->subDay(),
'Easter Sunday' => $easter,
'Reconciliation Day' => CarbonImmutable::create($year, 5, 27)->modify('monday'),
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("second monday of june {$year}"),
'Labour Day' => CarbonImmutable::parse("first monday of october {$year}"),
],
'nsw' => [
'Easter Saturday' => $easter->subDay(),
'Easter Sunday' => $easter,
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("second monday of june {$year}"),
'Labour Day' => CarbonImmutable::parse("first monday of october {$year}"),
],
'nt' => [
'Easter Saturday' => $easter->subDay(),
'May Day' => CarbonImmutable::parse("first monday of may {$year}"),
'Picnic Day' => CarbonImmutable::parse("first monday of august {$year}"),
],
'qld' => [
'The day after Good Friday' => $easter->subDay(),
'Easter Sunday' => $easter,
'Labour Day' => CarbonImmutable::parse("first monday of may {$year}"),
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("first monday of october {$year}"),
],
'sa' => [
'Adelaide Cup Day' => $year < 2006
? CarbonImmutable::parse("third monday of may {$year}")
: CarbonImmutable::parse("second monday of march {$year}"),
'The day after Good Friday' => $easter->subDay(),
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("second monday of june {$year}"),
'Labour Day' => CarbonImmutable::parse("first monday of october {$year}"),
],
'tas' => [
'Eight Hours Day' => CarbonImmutable::parse("second monday of march {$year}"),
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("second monday of june {$year}"),
],
'vic' => [
'Labour Day' => CarbonImmutable::parse("second monday of march {$year}"),
'Saturday before Easter Sunday' => $easter->subDay(),
'Easter Sunday' => $easter,
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("second monday of june {$year}"),
'Friday before AFL Grand Final' => $this->fridayBeforeAflGrandFinal($year),
'Melbourne Cup' => CarbonImmutable::parse("first tuesday of november {$year}"),
],
'wa' => [
'Labour Day' => CarbonImmutable::parse("first monday of march {$year}"),
'Easter Sunday' => $easter,
'Western Australia Day' => CarbonImmutable::parse("first monday of june {$year}"),
$this->sovereignBirthdayKey($year) => CarbonImmutable::parse("last monday of september {$year}"),
],
default => [],
}),
];
}

// https://business.vic.gov.au/business-information/public-holidays/victorian-public-holidays-2025
// https://en.wikipedia.org/wiki/List_of_VFL/AFL_premiers#VFL/AFL_premierships
protected function fridayBeforeAflGrandFinal(int $year): ?CarbonImmutable
{
if ($year < 2015) {
return null;
}

return match ($year) {
2015 => CarbonImmutable::parse('2015-10-02'),
2020 => CarbonImmutable::parse('2020-10-23'),
2022 => CarbonImmutable::parse('2022-09-23'),
default => CarbonImmutable::parse("last friday of september {$year}"),
};
}

protected function sovereignBirthdayKey(int $year): string
{
// https://www.abc.net.au/news/2022-09-22/queens-birthday-public-holiday-becomes-kings-birthday/101453408
$changeYear = $this->region === 'wa' ? 2022 : 2023;

return $year >= $changeYear ? "King's Birthday" : "Queen's Birthday";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"name": "New Year's Day",
"date": "2024-01-01"
},
{
"name": "Australia Day",
"date": "2024-01-26"
},
{
"name": "Good Friday",
"date": "2024-03-29"
},
{
"name": "Easter Monday",
"date": "2024-04-01"
},
{
"name": "Anzac Day",
"date": "2024-04-25"
},
{
"name": "Christmas Day",
"date": "2024-12-25"
},
{
"name": "Boxing Day",
"date": "2024-12-26"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"name": "New Year's Day",
"date": "2025-01-01"
},
{
"name": "Australia Day",
"date": "2025-01-26"
},
{
"name": "Good Friday",
"date": "2025-04-18"
},
{
"name": "Easter Monday",
"date": "2025-04-21"
},
{
"name": "Anzac Day",
"date": "2025-04-25"
},
{
"name": "Christmas Day",
"date": "2025-12-25"
},
{
"name": "Boxing Day",
"date": "2025-12-26"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[
{
"name": "New Year's Day",
"date": "2024-01-01"
},
{
"name": "Australia Day",
"date": "2024-01-26"
},
{
"name": "Labour Day",
"date": "2024-03-11"
},
{
"name": "Good Friday",
"date": "2024-03-29"
},
{
"name": "Saturday before Easter Sunday",
"date": "2024-03-30"
},
{
"name": "Easter Sunday",
"date": "2024-03-31"
},
{
"name": "Easter Monday",
"date": "2024-04-01"
},
{
"name": "Anzac Day",
"date": "2024-04-25"
},
{
"name": "King's Birthday",
"date": "2024-06-10"
},
{
"name": "Friday before AFL Grand Final",
"date": "2024-09-27"
},
{
"name": "Melbourne Cup",
"date": "2024-11-05"
},
{
"name": "Christmas Day",
"date": "2024-12-25"
},
{
"name": "Boxing Day",
"date": "2024-12-26"
}
]
130 changes: 130 additions & 0 deletions tests/Countries/AustraliaTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace Spatie\Holidays\Tests\Countries;

use Carbon\CarbonImmutable;
use Spatie\Holidays\Countries\Australia;
use Spatie\Holidays\Holidays;

it('can calculate australian holidays', function () {
CarbonImmutable::setTestNowAndTimezone('2024-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(country: 'au')->get();

expect($holidays)
->toBeArray()
->not()->toBeEmpty();

expect(formatDates($holidays))->toMatchSnapshot();
});

it('can calculate australian holidays for a specific year', function () {
CarbonImmutable::setTestNowAndTimezone('2024-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(country: 'au', year: 2025)->get();

expect($holidays)
->toBeArray()
->not()->toBeEmpty();

expect(formatDates($holidays))->toMatchSnapshot();
});

it('can calculate regional australian holidays', function () {
CarbonImmutable::setTestNowAndTimezone('2024-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(Australia::make('vic'))->get();

expect($holidays)
->toBeArray()
->not()->toBeEmpty();

expect(formatDates($holidays))->toMatchSnapshot();
});

it('can calculate the day before afl grand final', function () {
CarbonImmutable::setTestNowAndTimezone('2021-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(Australia::make('vic'))->get();

expect(findDate($holidays, 'Friday before AFL Grand Final'))
->toEqual(CarbonImmutable::create(2021, 9, 24));
});

it('can calculate the day before afl grand final during lockdown', function () {
CarbonImmutable::setTestNowAndTimezone('2020-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(Australia::make('vic'))->get();

expect(findDate($holidays, 'Friday before AFL Grand Final'))
->toEqual(CarbonImmutable::create(2020, 10, 23));
});

it('does not return the day before afl grand final before 2015', function () {
CarbonImmutable::setTestNowAndTimezone('2014-01-22', 'Australia/Melbourne');

$holidays = Holidays::for(Australia::make('vic'))->get();

expect(findDate($holidays, 'Friday before AFL Grand Final'))
->toBeNull();
});

it("returns queen's birthday before her death", function () {
CarbonImmutable::setTestNowAndTimezone('2021-01-22', 'Australia/Perth');

$holidays = Holidays::for(Australia::make('wa'))->get();

expect(findDate($holidays, "Queen's Birthday"))
->toEqual(CarbonImmutable::create(2021, 9, 27));

expect(findDate($holidays, "King's Birthday"))
->toBeNull();
});

it("returns king's birthday after her death", function () {
CarbonImmutable::setTestNowAndTimezone('2022-01-22', 'Australia/Perth');

$holidays = Holidays::for(Australia::make('wa'))->get();

expect(findDate($holidays, "Queen's Birthday"))
->toBeNull();

expect(findDate($holidays, "King's Birthday"))
->toEqual(CarbonImmutable::create(2022, 9, 26));
});

it('can calculate Adelaide Cup Day before 2006', function () {
CarbonImmutable::setTestNowAndTimezone('2005-01-22', 'Australia/Adelaide');

$holidays = Holidays::for(Australia::make('sa'))->get();

expect(findDate($holidays, 'Adelaide Cup Day'))
->toEqual(CarbonImmutable::create(2005, 5, 16));
});

it('can calculate Adelaide Cup Day after 2006', function () {
CarbonImmutable::setTestNowAndTimezone('2007-01-22', 'Australia/Adelaide');

$holidays = Holidays::for(Australia::make('sa'))->get();

expect(findDate($holidays, 'Adelaide Cup Day'))
->toEqual(CarbonImmutable::create(2007, 3, 12));
});

it('can calculate Reconciliation Day on 27 May', function () {
CarbonImmutable::setTestNowAndTimezone('2024-01-22', 'Australia/Canberra');

$holidays = Holidays::for(Australia::make('act'))->get();

expect(findDate($holidays, 'Reconciliation Day'))
->toEqual(CarbonImmutable::create(2024, 5, 27));
});

it('can calculate Reconciliation Day after 27 May', function () {
CarbonImmutable::setTestNowAndTimezone('2025-01-22', 'Australia/Canberra');

$holidays = Holidays::for(Australia::make('act'))->get();

expect(findDate($holidays, 'Reconciliation Day'))
->toEqual(CarbonImmutable::create(2025, 6, 2));
});
11 changes: 11 additions & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,14 @@ function formatDates(array $holidays): array

return $holidays;
}

function findDate(array $holidays, string $name): ?Carbon\CarbonImmutable
{
foreach ($holidays as $holiday) {
if ($holiday['name'] === $name) {
return $holiday['date'];
}
}

return null;
}
Loading