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

update ukraine holidays #202

Merged
merged 6 commits into from
Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions src/Yasumi/Holiday.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php

declare(strict_types=1);
/**
* This file is part of the Yasumi package.
*
Expand Down Expand Up @@ -76,7 +78,7 @@ class Holiday extends DateTime implements JsonSerializable
/**
* @var string Locale (i.e. language) in which the holiday information needs to be displayed in. (Default 'en_US')
*/
protected $displayLocale;
public $displayLocale;

/**
* Creates a new Holiday.
Expand Down
136 changes: 115 additions & 21 deletions src/Yasumi/Provider/Ukraine.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php

declare(strict_types=1);
/**
* This file is part of the Yasumi package.
*
Expand All @@ -15,6 +17,7 @@
use Yasumi\Exception\InvalidDateException;
use Yasumi\Exception\UnknownLocaleException;
use Yasumi\Holiday;
use Yasumi\SubstituteHoliday;

/**
* Provider for all holidays in Ukraine.
Expand All @@ -35,6 +38,13 @@ class Ukraine extends AbstractProvider
*/
public const ID = 'UA';

/**
* Type definition for postponed holidays due to weekend holidays.
* Normally holidays on a weekend will be postponed to monday.
* These mondays will get this type.
*/
public const TYPE_POSTPONED = 'postponed';

/**
* Initialize holidays for Ukraine.
*
Expand All @@ -48,7 +58,8 @@ public function initialize(): void
$this->timezone = 'Europe/Kiev';

// Add common holidays
$this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale));
// New Years Day will not be postponed 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));

Expand All @@ -58,11 +69,85 @@ public function initialize(): void

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

/**
* 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
* of holidays of this country.
* @param bool $postpone Holidays on a weekend will be postponed to the next monday.
* @param bool $addOnlyPostpone If $postpone is true add holidays on a weekend on the postponed day.
*/
public function addHoliday(Holiday $holiday, bool $postpone = true, bool $addOnlyPostpone = false): void
{
if (!$postpone || !$this->isWeekendDay($holiday)) {
parent::addHoliday($holiday);
return;
}

// Special case: Holiday on a weekend and should be postpone to monday.

// Add original holiday.
if (!$addOnlyPostpone) {
parent::addHoliday($holiday);
}

// Create postponed holiday.
$postponed = new Holiday(
$holiday->shortName . 'Postponed',
$holiday->translations,
$holiday,
$holiday->displayLocale,
self::TYPE_POSTPONED
);

// Holidays on weekends will be postponed to monday.
do {
$postponed->modify('+1 days');
} while ($this->isWeekendDay($postponed));

// Create add holiday.
parent::addHoliday($postponed);
}

/**
* Returns the number of defined holidays (for the given country and the given year).
* In case a holiday is substituted (e.g. observed), the holiday is only counted once.
*
* @param bool $ignorePostponedHolidays Do not count postponed holidays.
*
* @return int number of holidays
*/
public function count(bool $ignorePostponedHolidays = true): int
{
$names = \array_reduce(
$this->getHolidays(),
static function (&$carry, &$holiday) use (&$ignorePostponedHolidays) {
// Ignore postponed holidays.
if ($ignorePostponedHolidays) {
if ($holiday->getType() == self::TYPE_POSTPONED) {
return $carry;
}
}

if ($holiday instanceof SubstituteHoliday) {
$carry[] = $holiday->substitutedHoliday->shortName;
return $carry;
}

$carry[] = $holiday->shortName;
return $carry;
},
[]
);

return \count(\array_unique($names));
}

/**
Expand All @@ -83,24 +168,6 @@ private function calculateChristmasDay(): void
));
}

/**
* International Workers' Day.
*
* @link https://en.wikipedia.org/wiki/International_Workers%27_Day#Ukraine
*
* @throws InvalidDateException
* @throws \InvalidArgumentException
* @throws UnknownLocaleException
* @throws \Exception
*/
private function calculateSecondInternationalWorkersDay(): void
{
$this->addHoliday(new Holiday('secondInternationalWorkersDay', [
'uk' => 'День міжнародної солідарності трудящих',
'ru' => 'День международной солидарности трудящихся',
], new \DateTime("$this->year-05-02", new \DateTimeZone($this->timezone)), $this->locale));
}

/**
* Victory Day over Nazism in World War II
*
Expand Down Expand Up @@ -222,4 +289,31 @@ public function calculateEaster(int $year, string $timezone): \DateTime
{
return $this->calculateOrthodoxEaster($year, $timezone);
}

/**
* Catholic Christmas Day.
* (since 2017 instead of International Workers' Day 2. May)
*
* @link https://en.wikipedia.org/wiki/Christmas_in_Ukraine
*
* @throws InvalidDateException
* @throws \InvalidArgumentException
* @throws UnknownLocaleException
* @throws \Exception
*/
private function calculateCatholicChristmasDay(): void
{
$this->addHoliday(
new Holiday(
'catholicChristmasDay',
[
'uk' => 'Католицький день Різдва',
'ru' => 'Католическое рождество',
],
new \DateTime("$this->year-12-25", new \DateTimeZone($this->timezone)),
$this->locale
),
false // Catholic Christmas Day will not be postponed to an monday if it's on a weekend!
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php declare(strict_types=1);
<?php

declare(strict_types=1);
/**
* This file is part of the Yasumi package.
*
Expand All @@ -19,15 +21,15 @@
use Yasumi\tests\YasumiTestCaseInterface;

/**
* Class SecondInternationalWorkersDayTest
* Class CatholicChristmasDayTest
* @package Yasumi\tests\Ukraine
*/
class SecondInternationalWorkersDayTest extends UkraineBaseTestCase implements YasumiTestCaseInterface
class CatholicChristmasDayTest extends UkraineBaseTestCase implements YasumiTestCaseInterface
{
/**
* The name of the holiday
*/
public const HOLIDAY = 'secondInternationalWorkersDay';
public const HOLIDAY = 'catholicChristmasDay';

/**
* Tests International Workers' Day.
Expand All @@ -54,7 +56,7 @@ public function testTranslation(): void
self::REGION,
self::HOLIDAY,
$this->generateRandomYear(),
[self::LOCALE => 'День міжнародної солідарності трудящих']
[self::LOCALE => 'Католицький день Різдва']
);
}

Expand All @@ -75,6 +77,6 @@ public function testHolidayType(): void
*/
public function SecondInternationalWorkersDayDataProvider(): array
{
return $this->generateRandomDates(5, 2, self::TIMEZONE);
return $this->generateRandomDates(12, 25, self::TIMEZONE);
}
}
Loading