feat(services): add generator for public holidays in cz
This commit is contained in:
parent
ef937530af
commit
24f36c16d0
@ -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")));
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Unit\Services\WorkingDays\PublicHolidays\Generator;
|
||||||
|
|
||||||
|
use App\Services\WorkingDays\PublicHolidays\Generator\PublicHolidaysCzechGenerator;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class PublicHolidaysCzechGeneratorTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCzechPublicHolidays(): void
|
||||||
|
{
|
||||||
|
$czechNWD = new PublicHolidaysCzechGenerator();
|
||||||
|
// generate non-working days for 2025 and assert the results
|
||||||
|
$czechNWD = $czechNWD->generatePublicHolidaysForYear(2025);
|
||||||
|
$this->assertEquals([
|
||||||
|
new \DateTimeImmutable("2025-01-01"),
|
||||||
|
new \DateTimeImmutable("2025-04-18"),
|
||||||
|
new \DateTimeImmutable("2025-04-21"),
|
||||||
|
new \DateTimeImmutable("2025-05-01"),
|
||||||
|
new \DateTimeImmutable("2025-05-08"),
|
||||||
|
new \DateTimeImmutable("2025-07-05"),
|
||||||
|
new \DateTimeImmutable("2025-07-06"),
|
||||||
|
new \DateTimeImmutable("2025-09-28"),
|
||||||
|
new \DateTimeImmutable("2025-10-28"),
|
||||||
|
new \DateTimeImmutable("2025-11-17"),
|
||||||
|
new \DateTimeImmutable("2025-12-24"),
|
||||||
|
new \DateTimeImmutable("2025-12-25"),
|
||||||
|
new \DateTimeImmutable("2025-12-26"),
|
||||||
|
], $czechNWD);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Unit\Services\WorkingDays;
|
||||||
|
|
||||||
|
use App\Services\WorkingDays\PublicHolidays\Generator\PublicHolidaysCzechGenerator;
|
||||||
|
use App\Services\WorkingDays\PublicHolidays\PublicHolidaysGeneratorFactory;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class PublicHolidaysGeneratorFactoryTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testPublicHolidaysGeneratorFactoryWillReturnCzechGeneratorForCZ(): void
|
||||||
|
{
|
||||||
|
$factory = new PublicHolidaysGeneratorFactory();
|
||||||
|
$this->assertInstanceOf(PublicHolidaysCzechGenerator::class, $factory->createPublicHolidaysGeneratorForCountry('CZ'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRuntimeExceptionGeneratedForUnknownState(): void
|
||||||
|
{
|
||||||
|
$factory = new PublicHolidaysGeneratorFactory();
|
||||||
|
$this->expectException(\RuntimeException::class);
|
||||||
|
$factory->createPublicHolidaysGeneratorForCountry('XZ');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user