Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 386b48c

Browse files
committed
feat: added DateTime rule
1 parent b06a6e9 commit 386b48c

File tree

5 files changed

+110
-0
lines changed

5 files changed

+110
-0
lines changed

src/ChainedValidatorInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public function country(
3131
?string $message = null
3232
): ChainedValidatorInterface&Validator;
3333

34+
public function dateTime(
35+
string $format = 'Y-m-d H:i:s',
36+
?string $message = null
37+
): ChainedValidatorInterface&Validator;
38+
3439
public function eachKey(
3540
Validator $validator,
3641
?string $message = null
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
namespace ProgrammatorDev\Validator\Exception;
4+
5+
class DateTimeException extends ValidationException {}

src/Rule/DateTime.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace ProgrammatorDev\Validator\Rule;
4+
5+
use ProgrammatorDev\Validator\Exception\DateTimeException;
6+
use ProgrammatorDev\Validator\Exception\UnexpectedTypeException;
7+
8+
class DateTime extends AbstractRule implements RuleInterface
9+
{
10+
private string $message = 'The {{ name }} value is not a valid datetime.';
11+
12+
public function __construct(
13+
private readonly string $format = 'Y-m-d H:i:s',
14+
?string $message = null
15+
)
16+
{
17+
$this->message = $message ?? $this->message;
18+
}
19+
20+
public function assert(mixed $value, ?string $name = null): void
21+
{
22+
if (!\is_scalar($value) && !$value instanceof \Stringable) {
23+
throw new UnexpectedTypeException('string|\Stringable', get_debug_type($value));
24+
}
25+
26+
$value = (string) $value;
27+
28+
\DateTimeImmutable::createFromFormat($this->format, $value);
29+
30+
$errors = \DateTimeImmutable::getLastErrors();
31+
32+
if ($errors !== false && ($errors['error_count'] > 0 || $errors['warning_count'] > 0)) {
33+
throw new DateTimeException(
34+
message: $this->message,
35+
parameters: [
36+
'name' => $name,
37+
'value' => $value,
38+
'format' => $this->format
39+
]
40+
);
41+
}
42+
}
43+
}

src/StaticValidatorInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public static function country(
3030
?string $message = null
3131
): ChainedValidatorInterface&Validator;
3232

33+
public static function dateTime(
34+
string $format = 'Y-m-d H:i:s',
35+
?string $message = null
36+
): ChainedValidatorInterface&Validator;
37+
3338
public static function eachKey(
3439
Validator $validator,
3540
?string $message = null

tests/DateTimeTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace ProgrammatorDev\Validator\Test;
4+
5+
use ProgrammatorDev\Validator\Exception\DateTimeException;
6+
use ProgrammatorDev\Validator\Rule\DateTime;
7+
use ProgrammatorDev\Validator\Test\Util\TestRuleFailureConditionTrait;
8+
use ProgrammatorDev\Validator\Test\Util\TestRuleMessageOptionTrait;
9+
use ProgrammatorDev\Validator\Test\Util\TestRuleSuccessConditionTrait;
10+
use ProgrammatorDev\Validator\Test\Util\TestRuleUnexpectedValueTrait;
11+
12+
class DateTimeTest extends AbstractTest
13+
{
14+
use TestRuleUnexpectedValueTrait;
15+
use TestRuleFailureConditionTrait;
16+
use TestRuleSuccessConditionTrait;
17+
use TestRuleMessageOptionTrait;
18+
19+
public static function provideRuleUnexpectedValueData(): \Generator
20+
{
21+
$unexpectedTypeMessage = '/Expected value of type "string|\Stringable", "(.*)" given./';
22+
23+
yield 'invalid value type' => [new DateTime(), ['2024-01-01 00:00:00'], $unexpectedTypeMessage];
24+
}
25+
26+
public static function provideRuleFailureConditionData(): \Generator
27+
{
28+
$value = 'invalid';
29+
$exception = DateTimeException::class;
30+
$message = '/The (.*) value is not a valid datetime./';
31+
32+
yield 'invalid datetime' => [new DateTime(), $value, $exception, $message];
33+
yield 'invalid format' => [new DateTime(format: 'invalid'), '2024-01-01 00:00:00', $exception, $message];
34+
}
35+
36+
public static function provideRuleSuccessConditionData(): \Generator
37+
{
38+
yield 'datetime' => [new DateTime(), '2024-01-01 00:00:00'];
39+
yield 'format' => [new DateTime(format: 'Y-m-d'), '2024-01-01'];
40+
}
41+
42+
public static function provideRuleMessageOptionData(): \Generator
43+
{
44+
yield 'message' => [
45+
new DateTime(
46+
message: 'The {{ name }} datetime does not match the format {{ format }}.'
47+
),
48+
'2024-01-01',
49+
'The test datetime does not match the format "Y-m-d H:i:s".'
50+
];
51+
}
52+
}

0 commit comments

Comments
 (0)