Refactor RollingDateConverter to use ClockInterface

Introduced ClockInterface for better time mocking and handling, replacing default instantiation with dependency injection. Adjusted RollingDate logic to accept nullable pivot dates and updated related tests for improved flexibility and accuracy.
This commit is contained in:
Julien Fastré 2025-04-02 11:08:01 +02:00
parent 9124fa68e8
commit 89aed74355
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
3 changed files with 46 additions and 25 deletions

View File

@ -72,7 +72,7 @@ class RollingDate
public function __construct(
private readonly string $roll,
private readonly ?\DateTimeImmutable $fixedDate = null,
private readonly \DateTimeImmutable $pivotDate = new \DateTimeImmutable('now'),
private readonly ?\DateTimeImmutable $pivotDate = null,
) {}
public function getFixedDate(): ?\DateTimeImmutable
@ -80,7 +80,7 @@ class RollingDate
return $this->fixedDate;
}
public function getPivotDate(): \DateTimeImmutable
public function getPivotDate(): ?\DateTimeImmutable
{
return $this->pivotDate;
}

View File

@ -11,8 +11,16 @@ declare(strict_types=1);
namespace Chill\MainBundle\Service\RollingDate;
class RollingDateConverter implements RollingDateConverterInterface
use Symfony\Component\Clock\ClockInterface;
final readonly class RollingDateConverter implements RollingDateConverterInterface
{
function __construct(private readonly ClockInterface $clock)
{
}
public function convert(?RollingDate $rollingDate): ?\DateTimeImmutable
{
if (null === $rollingDate) {
@ -21,43 +29,43 @@ class RollingDateConverter implements RollingDateConverterInterface
switch ($rollingDate->getRoll()) {
case RollingDate::T_MONTH_CURRENT_START:
return $this->toBeginOfMonth($rollingDate->getPivotDate());
return $this->toBeginOfMonth($rollingDate->getPivotDate() ?? $this->clock->now());
case RollingDate::T_MONTH_NEXT_START:
return $this->toBeginOfMonth($rollingDate->getPivotDate()->add(new \DateInterval('P1M')));
return $this->toBeginOfMonth(($rollingDate->getPivotDate() ?? $this->clock->now())->add(new \DateInterval('P1M')));
case RollingDate::T_MONTH_PREVIOUS_START:
return $this->toBeginOfMonth($rollingDate->getPivotDate()->sub(new \DateInterval('P1M')));
return $this->toBeginOfMonth(($rollingDate->getPivotDate() ?? $this->clock->now())->sub(new \DateInterval('P1M')));
case RollingDate::T_QUARTER_CURRENT_START:
return $this->toBeginOfQuarter($rollingDate->getPivotDate());
return $this->toBeginOfQuarter($rollingDate->getPivotDate()?? $this->clock->now());
case RollingDate::T_QUARTER_NEXT_START:
return $this->toBeginOfQuarter($rollingDate->getPivotDate()->add(new \DateInterval('P3M')));
return $this->toBeginOfQuarter(($rollingDate->getPivotDate() ?? $this->clock->now())->add(new \DateInterval('P3M')));
case RollingDate::T_QUARTER_PREVIOUS_START:
return $this->toBeginOfQuarter($rollingDate->getPivotDate()->sub(new \DateInterval('P3M')));
return $this->toBeginOfQuarter(($rollingDate->getPivotDate() ?? $this->clock->now())->sub(new \DateInterval('P3M')));
case RollingDate::T_WEEK_CURRENT_START:
return $this->toBeginOfWeek($rollingDate->getPivotDate());
return $this->toBeginOfWeek($rollingDate->getPivotDate() ?? $this->clock->now());
case RollingDate::T_WEEK_NEXT_START:
return $this->toBeginOfWeek($rollingDate->getPivotDate()->add(new \DateInterval('P1W')));
return $this->toBeginOfWeek(($rollingDate->getPivotDate() ?? $this->clock->now())->add(new \DateInterval('P1W')));
case RollingDate::T_WEEK_PREVIOUS_START:
return $this->toBeginOfWeek($rollingDate->getPivotDate()->sub(new \DateInterval('P1W')));
return $this->toBeginOfWeek(($rollingDate->getPivotDate() ?? $this->clock->now())->sub(new \DateInterval('P1W')));
case RollingDate::T_YEAR_CURRENT_START:
return $this->toBeginOfYear($rollingDate->getPivotDate());
return $this->toBeginOfYear($rollingDate->getPivotDate() ?? $this->clock->now());
case RollingDate::T_YEAR_PREVIOUS_START:
return $this->toBeginOfYear($rollingDate->getPivotDate()->sub(new \DateInterval('P1Y')));
return $this->toBeginOfYear(($rollingDate->getPivotDate() ?? $this->clock->now())->sub(new \DateInterval('P1Y')));
case RollingDate::T_YEAR_NEXT_START:
return $this->toBeginOfYear($rollingDate->getPivotDate()->add(new \DateInterval('P1Y')));
return $this->toBeginOfYear(($rollingDate->getPivotDate() ?? $this->clock->now())->add(new \DateInterval('P1Y')));
case RollingDate::T_TODAY:
return $rollingDate->getPivotDate();
return $rollingDate->getPivotDate() ?? $this->clock->now();
case RollingDate::T_FIXED_DATE:
if (null === $rollingDate->getFixedDate()) {
@ -75,7 +83,7 @@ class RollingDateConverter implements RollingDateConverterInterface
{
return \DateTimeImmutable::createFromFormat(
'Y-m-d His',
sprintf('%s-%s-01 000000', $date->format('Y'), $date->format('m'))
sprintf('%s-%s-01 000000', $date->format('Y'), $date->format('m')),
);
}
@ -90,7 +98,7 @@ class RollingDateConverter implements RollingDateConverterInterface
return \DateTimeImmutable::createFromFormat(
'Y-m-d His',
sprintf('%s-%s-01 000000', $date->format('Y'), $month)
sprintf('%s-%s-01 000000', $date->format('Y'), $month),
);
}

View File

@ -14,6 +14,7 @@ namespace Services\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Clock\MockClock;
/**
* @internal
@ -22,11 +23,9 @@ use PHPUnit\Framework\TestCase;
*/
final class RollingDateConverterTest extends TestCase
{
private RollingDateConverter $converter;
protected function setUp(): void
private function buildConverter(\DateTimeImmutable|string $pivot = 'now'): RollingDateConverter
{
$this->converter = new RollingDateConverter();
return new RollingDateConverter(new MockClock($pivot));
}
public static function generateDataConversionDate(): iterable
@ -66,7 +65,7 @@ final class RollingDateConverterTest extends TestCase
$this->assertEquals(
'2022-01-01',
$this->converter->convert($rollingDate)->format('Y-m-d')
$this->buildConverter()->convert($rollingDate)->format('Y-m-d')
);
}
@ -74,7 +73,7 @@ final class RollingDateConverterTest extends TestCase
{
$rollingDate = new RollingDate(RollingDate::T_YEAR_PREVIOUS_START);
$actual = $this->converter->convert($rollingDate);
$actual = $this->buildConverter()->convert($rollingDate);
$this->assertEquals(
(int) (new \DateTimeImmutable('now'))->format('Y') - 1,
@ -94,7 +93,21 @@ final class RollingDateConverterTest extends TestCase
$this->assertEquals(
\DateTime::createFromFormat($format, $expectedDateTime),
$this->converter->convert($rollingDate)
$this->buildConverter()->convert($rollingDate)
);
}
/**
* @dataProvider generateDataConversionDate
*/
public function testConvertOnClock(string $roll, string $expectedDateTime, string $format)
{
$pivot = \DateTimeImmutable::createFromFormat('Y-m-d His', '2022-11-07 000000');
$rollingDate = new RollingDate($roll, null);
$this->assertEquals(
\DateTime::createFromFormat($format, $expectedDateTime),
$this->buildConverter($pivot)->convert($rollingDate)
);
}
}