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