Skip to content

Commit cf03f8a

Browse files
Create "DateTimeDiff" rule
Co-authored-by: Gabriel Goulart <vieirabiel2009@hotmail.com>
1 parent ea3f81f commit cf03f8a

25 files changed

+598
-4
lines changed

docs/08-list-of-rules-by-category.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575

7676
- [Date](rules/Date.md)
7777
- [DateTime](rules/DateTime.md)
78+
- [DateTimeDiff](rules/DateTimeDiff.md)
7879
- [LeapDate](rules/LeapDate.md)
7980
- [LeapYear](rules/LeapYear.md)
8081
- [MaxAge](rules/MaxAge.md)
@@ -323,6 +324,7 @@
323324
- [CurrencyCode](rules/CurrencyCode.md)
324325
- [Date](rules/Date.md)
325326
- [DateTime](rules/DateTime.md)
327+
- [DateTimeDiff](rules/DateTimeDiff.md)
326328
- [Decimal](rules/Decimal.md)
327329
- [Digit](rules/Digit.md)
328330
- [Directory](rules/Directory.md)

docs/rules/Date.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Version | Description
4545
See also:
4646

4747
- [DateTime](DateTime.md)
48+
- [DateTimeDiff](DateTimeDiff.md)
4849
- [LeapDate](LeapDate.md)
4950
- [LeapYear](LeapYear.md)
5051
- [MaxAge](MaxAge.md)

docs/rules/DateTime.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ See also:
7474
- [BetweenExclusive](BetweenExclusive.md)
7575
- [Callback](Callback.md)
7676
- [Date](Date.md)
77+
- [DateTimeDiff](DateTimeDiff.md)
7778
- [LeapDate](LeapDate.md)
7879
- [LeapYear](LeapYear.md)
7980
- [MinAge](MinAge.md)

docs/rules/DateTimeDiff.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# DateTimeDiff
2+
3+
- `DateTimeDiff(string $type, Validatable $rule)`
4+
- `DateTimeDiff(string $type, Validatable $rule, string $format)`
5+
6+
Validates the difference of date/time against a specific rule.
7+
8+
The `$format` argument should follow PHP's [date()][] function. When the `$format` is not given, this rule accepts
9+
[Supported Date and Time Formats][] by PHP (see [strtotime()][]).
10+
11+
```php
12+
v::dateTimeDiff('years', v::equals(7))->validate('7 years ago'); // true
13+
v::dateTimeDiff('years', v::equals(7))->validate('7 years ago + 1 minute'); // false
14+
15+
v::dateTimeDiff('years', v::greaterThan(18), 'd/m/Y')->validate('09/12/1990'); // true
16+
v::dateTimeDiff('years', v::greaterThan(18), 'd/m/Y')->validate('09/12/2023'); // false
17+
18+
v::dateTimeDiff('months', v::between(1, 18))->validate('5 months ago'); // true
19+
```
20+
21+
The supported types are:
22+
23+
* `years`
24+
* `months`
25+
* `days`
26+
* `hours`
27+
* `minutes`
28+
* `seconds`
29+
* `microseconds`
30+
31+
## Categorization
32+
33+
- Date and Time
34+
35+
## Changelog
36+
37+
| Version | Description |
38+
| ------: |--------------------------------------------|
39+
| 3.0.0 | Created from `Age`, `MinAge`, and `MaxAge` |
40+
41+
***
42+
See also:
43+
44+
- [Date](Date.md)
45+
- [DateTime](DateTime.md)
46+
- [Max](Max.md)
47+
- [Min](Min.md)
48+
- [Time](Time.md)
49+
50+
[date()]: http://php.net/date
51+
[DateTimeInterface]: http://php.net/DateTimeInterface
52+
[strtotime()]: http://php.net/strtotime
53+
[Supported Date and Time Formats]: http://php.net/datetime.formats

docs/rules/Max.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ See also:
3939

4040
- [Between](Between.md)
4141
- [BetweenExclusive](BetweenExclusive.md)
42+
- [DateTimeDiff](DateTimeDiff.md)
4243
- [GreaterThan](GreaterThan.md)
4344
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
4445
- [IterableType](IterableType.md)

docs/rules/Min.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ See also:
3939

4040
- [Between](Between.md)
4141
- [BetweenExclusive](BetweenExclusive.md)
42+
- [DateTimeDiff](DateTimeDiff.md)
4243
- [Each](Each.md)
4344
- [GreaterThan](GreaterThan.md)
4445
- [GreaterThanOrEqual](GreaterThanOrEqual.md)

docs/rules/Time.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ See also:
4949

5050
- [Date](Date.md)
5151
- [DateTime](DateTime.md)
52+
- [DateTimeDiff](DateTimeDiff.md)
5253
- [LeapDate](LeapDate.md)
5354
- [LeapYear](LeapYear.md)

library/Helpers/CanExtractRules.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
namespace Respect\Validation\Helpers;
1111

1212
use Respect\Validation\Exceptions\ComponentException;
13+
use Respect\Validation\Rules\Core\Composite;
14+
use Respect\Validation\Rules\Not;
1315
use Respect\Validation\Validatable;
1416
use Respect\Validation\Validator;
17+
use Throwable;
1518

1619
use function array_map;
1720
use function count;
@@ -37,6 +40,40 @@ private function extractSingle(Validatable $rule, string $class): Validatable
3740
return $rule;
3841
}
3942

43+
private function extractSiblingSuitableRule(Validatable $rule, Throwable $throwable): Validatable
44+
{
45+
$this->assertSingleRule($rule, $throwable);
46+
47+
if ($rule instanceof Validator) {
48+
return $rule->getRules()[0];
49+
}
50+
51+
return $rule;
52+
}
53+
54+
private function assertSingleRule(Validatable $rule, Throwable $throwable): void
55+
{
56+
if ($rule instanceof Not) {
57+
$this->assertSingleRule($rule->getRule(), $throwable);
58+
59+
return;
60+
}
61+
62+
if ($rule instanceof Validator) {
63+
if (count($rule->getRules()) !== 1) {
64+
throw $throwable;
65+
}
66+
67+
$this->assertSingleRule($rule->getRules()[0], $throwable);
68+
69+
return;
70+
}
71+
72+
if ($rule instanceof Composite) {
73+
throw $throwable;
74+
}
75+
}
76+
4077
/**
4178
* @param array<Validatable> $rules
4279
*

library/Helpers/CanValidateDateTime.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ trait CanValidateDateTime
2121
{
2222
private function isDateTime(string $format, string $value): bool
2323
{
24-
$exceptionalFormats = [
25-
'c' => 'Y-m-d\TH:i:sP',
26-
'r' => 'D, d M Y H:i:s O',
27-
];
24+
$exceptionalFormats = $this->getExceptionalFormats();
2825

2926
$format = $exceptionalFormats[$format] ?? $format;
3027

@@ -75,4 +72,13 @@ private function isDateInformation(array $info): bool
7572

7673
return checkdate($info['month'] ?: 1, 1, $info['year'] ?: 1);
7774
}
75+
76+
/** @return array<string, string> */
77+
private function getExceptionalFormats(): array
78+
{
79+
return [
80+
'c' => 'Y-m-d\TH:i:sP',
81+
'r' => 'D, d M Y H:i:s O',
82+
];
83+
}
7884
}

library/Mixins/ChainedKey.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace Respect\Validation\Mixins;
1111

12+
use DateTimeImmutable;
1213
use Respect\Validation\Validatable;
1314

1415
interface ChainedKey
@@ -107,6 +108,17 @@ public function keyDate(int|string $key, string $format = 'Y-m-d'): ChainedValid
107108

108109
public function keyDateTime(int|string $key, ?string $format = null): ChainedValidator;
109110

111+
/**
112+
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
113+
*/
114+
public function keyDateTimeDiff(
115+
int|string $key,
116+
string $type,
117+
Validatable $rule,
118+
?string $format = null,
119+
?DateTimeImmutable $now = null,
120+
): ChainedValidator;
121+
110122
public function keyDecimal(int|string $key, int $decimals): ChainedValidator;
111123

112124
public function keyDigit(int|string $key, string ...$additionalChars): ChainedValidator;

0 commit comments

Comments
 (0)