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

Actual holidays for Ukraine #319

Closed
wants to merge 1 commit into from
Closed
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
121 changes: 106 additions & 15 deletions src/Yasumi/Provider/Ukraine.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,22 @@ public function initialize(): void
// Add common holidays
// New Years Day will not be substituted to an monday if it's on a weekend!
$this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale), false);
$this->addHoliday($this->internationalWorkersDay($this->year, $this->timezone, $this->locale));
$this->addHoliday($this->internationalWomensDay($this->year, $this->timezone, $this->locale));

// Add Christian holidays
$this->addHoliday($this->easter($this->year, $this->timezone, $this->locale));
$this->addHoliday($this->pentecost($this->year, $this->timezone, $this->locale));

// Add other holidays
$this->calculateInternationalWorkersDay();
$this->calculateChristmasDay();
$this->calculateSecondInternationalWorkersDay();
$this->calculateVictoryDay();
$this->calculateConstitutionDay();
$this->calculateIndependenceDay();
$this->calculateDefenderOfUkraineDay();
$this->calculateCatholicChristmasDay();
$this->calculateStatehoodDay();
}

public function getSources(): array
Expand All @@ -79,9 +80,9 @@ public function getSources(): array
/**
* Adds a holiday to the holidays providers (i.e. country/state) list of holidays.
*
* @param Holiday $holiday holiday instance (representing a holiday) to be added to the internal list
* @param Holiday $holiday holiday instance (representing a holiday) to be added to the internal list
* of holidays of this country
* @param bool $substitutable holidays on a weekend will be substituted to the next monday
* @param bool $substitutable holidays on a weekend will be substituted to the next monday
*
* @throws UnknownLocaleException
* @throws \InvalidArgumentException
Expand All @@ -91,7 +92,7 @@ public function addHoliday(Holiday $holiday, bool $substitutable = true): void
{
parent::addHoliday($holiday);

if (! $substitutable) {
if (!$substitutable) {
return;
}

Expand Down Expand Up @@ -123,16 +124,84 @@ protected function calculateEaster(int $year, string $timezone): \DateTimeInterf
/**
* Christmas Day.
*
* @see https://en.wikipedia.org/wiki/Christmas_in_Ukraine
*
* @throws \InvalidArgumentException
* @throws UnknownLocaleException
* @throws \Exception
*/
private function calculateChristmasDay(): void
{
if ($this->year >= 1991 && $this->year <= 2023) {
$substitutable = true;
$type = Holiday::TYPE_OFFICIAL;
} else {
$substitutable = false;
$type = Holiday::TYPE_OTHER;
}

$this->addHoliday(new Holiday(
'christmasDay',
[],
[
'uk' => 'Різдво Христове (за юліанським календарем)',
'ru' => 'Рождество Христово (по юлианскому календарю)'
],
new \DateTime("{$this->year}-01-07", new \DateTimeZone($this->timezone)),
$this->locale,
$type,
), $substitutable);
}

/**
* International Workers' Day.
*
* @see https://en.wikipedia.org/wiki/International_Workers%27_Day#Ukraine
*
* @throws \InvalidArgumentException
* @throws UnknownLocaleException
* @throws \Exception
*/
private function calculateInternationalWorkersDay(): void
{
if ($this->year < 2017) {
$holidayTranslation = ['uk' => 'День міжнародної солідарності трудящих', 'ru' => 'День международной солидарности трудящихся'];
} else {
$holidayTranslation = ['uk' => 'День праці', 'ru' => 'День труда'];
}

$this->addHoliday(new Holiday(
'internationalWorkersDay',
$holidayTranslation,
new \DateTime("{$this->year}-05-01", new \DateTimeZone($this->timezone)),
$this->locale
));
}

/**
* Statehood Day.
*
* @see https://en.wikipedia.org/wiki/Statehood_Day_(Ukraine)
*
* @throws \InvalidArgumentException
* @throws UnknownLocaleException
* @throws \Exception
*/
private function calculateStatehoodDay(): void
{
if ($this->year < 2021) {
return;
}

if ($this->year === 2022) {
$date = new \DateTime("{$this->year}-07-28", new \DateTimeZone($this->timezone));
} else {
$date = new \DateTime("{$this->year}-07-15", new \DateTimeZone($this->timezone));
}

$this->addHoliday(new Holiday(
'statehoodDay',
['uk' => 'День Української Державності', 'ru' => 'День украинской государственности'],
$date,
$this->locale
));
}
Expand Down Expand Up @@ -176,12 +245,21 @@ private function calculateSecondInternationalWorkersDay(): void
*/
private function calculateVictoryDay(): void
{
$this->addHoliday(new Holiday(
'victoryDay',
['uk' => 'День перемоги', 'ru' => 'День победы'],
new \DateTime("{$this->year}-05-09", new \DateTimeZone($this->timezone)),
$this->locale
));
if ($this->year >= 2015) {
$this->addHoliday(new Holiday(
'victoryDay',
['uk' => 'День перемоги над нацизмом у Другій світовій війні', 'ru' => 'День победы над нацизмом во Второй мировой войне'],
new \DateTime("{$this->year}-05-08", new \DateTimeZone($this->timezone)),
$this->locale
));
} else {
$this->addHoliday(new Holiday(
'victoryDay',
['uk' => 'День перемоги', 'ru' => 'День победы'],
new \DateTime("{$this->year}-05-09", new \DateTimeZone($this->timezone)),
$this->locale
));
}
}

/**
Expand Down Expand Up @@ -243,6 +321,7 @@ private function calculateIndependenceDay(): void
* is a state holiday in Ukraine celebrated annually on October 14.
* Its first celebration was in 2015.
* Starting from 2015, this day is considered a public holiday (this is thus a day off in Ukraine)
* Starting from 2023, this holiday is celebrated on October 1.
*
* @see https://en.wikipedia.org/wiki/Defender_of_Ukraine_Day
*
Expand All @@ -256,10 +335,16 @@ private function calculateDefenderOfUkraineDay(): void
return;
}

if ($this->year < 2023) {
$date = new \DateTime("{$this->year}-10-14", new \DateTimeZone($this->timezone));
} else {
$date = new \DateTime("{$this->year}-10-01", new \DateTimeZone($this->timezone));
}

$this->addHoliday(new Holiday(
'defenderOfUkraineDay',
['uk' => 'День захисника України', 'ru' => 'День Защитника Украины'],
new \DateTime("{$this->year}-10-14", new \DateTimeZone($this->timezone)),
$date,
$this->locale
));
}
Expand All @@ -280,17 +365,23 @@ private function calculateCatholicChristmasDay(): void
return;
}

if ($this->year < 2024) {
$substitutable = false; // Catholic Christmas Day will not be substituted to an monday if it's on a weekend until 2023!
} else {
$substitutable = true;
}

$this->addHoliday(
new Holiday(
'catholicChristmasDay',
[
'uk' => 'Католицький день Різдва',
'ru' => 'Католическое рождество',
'uk' => 'Різдво Христове (за григоріанським календарем)',
'ru' => 'Рождество Христово (по григорианскому календарю)',
],
new \DateTime("{$this->year}-12-25", new \DateTimeZone($this->timezone)),
$this->locale
),
false // Catholic Christmas Day will not be substituted to an monday if it's on a weekend!
$substitutable
);
}
}
2 changes: 1 addition & 1 deletion tests/Ukraine/CatholicChristmasDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function testTranslation(): void
self::REGION,
self::HOLIDAY,
$this->generateRandomYear(2017),
[self::LOCALE => 'Католицький день Різдва']
[self::LOCALE => 'Різдво Христове (за григоріанським календарем)']
);
}

Expand Down
5 changes: 3 additions & 2 deletions tests/Ukraine/ChristmasDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function testTranslation(): void
self::REGION,
self::HOLIDAY,
$this->generateRandomYear(),
[self::LOCALE => 'Різдво']
[self::LOCALE => 'Різдво Христове (за юліанським календарем)']
);
}

Expand All @@ -74,6 +74,7 @@ public function testTranslation(): void
*/
public function testHolidayType(): void
{
$this->assertHolidayType(self::REGION, self::HOLIDAY, $this->generateRandomYear(), Holiday::TYPE_OFFICIAL);
$year = $this->generateRandomYear();
$this->assertHolidayType(self::REGION, self::HOLIDAY, $year, ($year >= 1991 && $year <= 2023 ? Holiday::TYPE_OFFICIAL : Holiday::TYPE_OTHER));
}
}
4 changes: 2 additions & 2 deletions tests/Ukraine/DefenderOfUkraineDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ class DefenderOfUkraineDayTest extends UkraineBaseTestCase implements HolidayTes
*/
public function testHoliday(): void
{
$year = 2020;
$year = $this->generateRandomYear(2015);
$this->assertHoliday(
self::REGION,
self::HOLIDAY,
$year,
new \DateTime("{$year}-10-14", new \DateTimeZone(self::TIMEZONE))
new \DateTime(($year >= 2015 && $year < 2023 ? "{$year}-10-14" : "{$year}-10-01"), new \DateTimeZone(self::TIMEZONE))
);
}

Expand Down
5 changes: 3 additions & 2 deletions tests/Ukraine/InternationalWorkersDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ public function testInternationalWorkersDay(int $year, \DateTimeInterface $expec
*/
public function testTranslation(): void
{
$year = $this->generateRandomYear();
$this->assertTranslatedHolidayName(
self::REGION,
self::HOLIDAY,
$this->generateRandomYear(),
[self::LOCALE => 'День міжнародної солідарності трудящих']
$year,
[self::LOCALE => ($year < 2017 ? 'День міжнародної солідарності трудящих' : 'День праці')]
);
}

Expand Down
32 changes: 28 additions & 4 deletions tests/Ukraine/SubstitutedHolidayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ class SubstitutedHolidayTest extends UkraineBaseTestCase implements HolidayTestC
*/
public function testSaturdaySubstitution(): void
{
// 2020-05-09 victoryDay (День перемоги)
$year = 2020;
// 2021-05-08 victoryDay (День перемоги над нацизмом у Другій світовій війні)
$year = 2021;
$holiday = 'victoryDay';

$this->assertHolidayWithSubstitution(
self::REGION,
$holiday,
$year,
new \DateTime("{$year}-05-09", new \DateTimeZone(self::TIMEZONE)),
new \DateTime("{$year}-05-11", new \DateTimeZone(self::TIMEZONE))
new \DateTime("{$year}-05-08", new \DateTimeZone(self::TIMEZONE)),
new \DateTime("{$year}-05-10", new \DateTimeZone(self::TIMEZONE))
);

unset($year, $holiday);
Expand Down Expand Up @@ -159,6 +159,30 @@ public function testCatholicChristmasDayNoSubstitution(): void
unset($year, $holiday);
}

/**
* Tests the substitution of Catholic Christmas Day (25. December) on a weekend.
* Special: no substitution at Catholic Christmas Day (25. December) on a weekend.
*
* @throws \Exception
* @throws \ReflectionException
*/
public function testCatholicChristmasDaySubstitution(): void
{
// 2027-12-25 (Sunday) catholicChristmasDay (Католицький день Різдва)
$year = 2027;
$holiday = 'catholicChristmasDay';

$this->assertHolidayWithSubstitution(
self::REGION,
$holiday,
$year,
new \DateTime("{$year}-12-25", new \DateTimeZone(self::TIMEZONE)),
new \DateTime("{$year}-12-27", new \DateTimeZone(self::TIMEZONE))
);

unset($year, $holiday);
}

/**
* Dummy: Tests the translated name of the holiday defined in this test.
*/
Expand Down
9 changes: 8 additions & 1 deletion tests/Ukraine/UkraineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public function testOfficialHolidays(): void
$holidays = [
'newYearsDay',
'internationalWorkersDay',
'christmasDay',
'easter',
'pentecost',
'internationalWomensDay',
Expand All @@ -73,6 +72,14 @@ public function testOfficialHolidays(): void
$holidays[] = 'catholicChristmasDay';
}

if ($this->year >= 1991 && $this->year <= 2023) {
$holidays[] = 'christmasDay';
}

if ($this->year >= 2022) {
$holidays[] = 'statehoodDay';
}

$this->assertDefinedHolidays(
$holidays,
self::REGION,
Expand Down
29 changes: 12 additions & 17 deletions tests/Ukraine/VictoryDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,17 @@ class VictoryDayTest extends UkraineBaseTestCase implements HolidayTestCase
public const HOLIDAY = 'victoryDay';

/**
* @dataProvider HolidayDataProvider
* Tests Victory Day.
*/
public function testHoliday(int $year, \DateTimeInterface $expected): void
public function testHoliday(): void
{
$this->assertHoliday(self::REGION, self::HOLIDAY, $year, $expected);
}

/**
* Returns a list of random test dates used for assertion of the holiday defined in this test.
*
* @return array<array> list of test dates for the holiday defined in this test
*
* @throws \Exception
*/
public function HolidayDataProvider(): array
{
return $this->generateRandomDates(5, 9, self::TIMEZONE);
$year = 2017;
$this->assertHoliday(
self::REGION,
self::HOLIDAY,
$year,
new \DateTime("{$year}-5-8", new \DateTimeZone(self::TIMEZONE))
);
}

/**
Expand All @@ -54,11 +48,12 @@ public function HolidayDataProvider(): array
*/
public function testTranslation(): void
{
$year = $this->generateRandomYear();
$this->assertTranslatedHolidayName(
self::REGION,
self::HOLIDAY,
$this->generateRandomYear(),
[self::LOCALE => 'День перемоги']
$year,
[self::LOCALE => ($year < 2015 ? 'День перемоги' : 'День перемоги над нацизмом у Другій світовій війні')]
);
}

Expand Down
Loading