feat(services): add generator for public holidays in cz

This commit is contained in:
2024-08-07 12:54:55 +02:00
parent ef937530af
commit 24f36c16d0
5 changed files with 155 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace App\Services\WorkingDays\PublicHolidays\Generator;
use Nubium\Exception\ThisShouldNeverHappenException;
/**
* Generates public holidays for a given year in Czech Republic.
*/
class PublicHolidaysCzechGenerator implements PublicHolidaysGenerator
{
// non-working days in Czech republic in format [month, day]
protected const array HOLIDAYS = [
[1, 1],
[5, 1],
[5, 8],
[7, 5],
[7, 6],
[9, 28],
[10, 28],
[11, 17],
[12, 24],
[12, 25],
[12, 26]
];
public function generatePublicHolidaysForYear(int $year): array
{
$result = [];
foreach (static::HOLIDAYS as $holiday) {
$formatedDate = sprintf("%d-%02d-%02d 00:00:00", $year, $holiday[0], $holiday[1]);
$date = \DateTimeImmutable::createFromFormat("Y-m-d h:i:s", $formatedDate);
if ($date == false) {
throw new ThisShouldNeverHappenException("Invalid date format: $formatedDate, self::HOLIDAYS or year is incorrect.");
}
$result[] = $date;
}
// Add easters
$easters = $this->getEasterDateTime($year);
$result[] = $easters->add(new \DateInterval("P1D")); // easter Monday
$result[] = $easters->sub(new \DateInterval("P2D")); // easter Friday
array_multisort($result, SORT_ASC);
return $result;
}
private function getEasterDateTime(int $year): \DateTimeImmutable
{
$base = new \DateTime("$year-03-21");
$days = \easter_days($year);
return \DateTimeImmutable::createFromInterface($base->add(new \DateInterval("P{$days}D")));
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\Services\WorkingDays\PublicHolidays\Generator;
/**
* Generates public holidays.
*/
interface PublicHolidaysGenerator
{
/**
* Generates public holidays for the given year.
* @param int $year
* @return \DateTimeImmutable[]
*/
public function generatePublicHolidaysForYear(int $year): array;
}

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace App\Services\WorkingDays\PublicHolidays;
use App\Services\WorkingDays\PublicHolidays\Generator\PublicHolidaysCzechGenerator;
use App\Services\WorkingDays\PublicHolidays\Generator\PublicHolidaysGenerator;
/**
* Factory for creating public holidays generators
*/
class PublicHolidaysGeneratorFactory
{
public function createPublicHolidaysGeneratorForCountry(string $countryCode): PublicHolidaysGenerator
{
return match ($countryCode) {
'CZ' => new PublicHolidaysCzechGenerator(),
default => throw new \RuntimeException('Unsupported country code'),
};
}
}