Skip to content

Commit

Permalink
Create "DateTimeDiff" rule
Browse files Browse the repository at this point in the history
Co-authored-by: Gabriel Goulart <[email protected]>
  • Loading branch information
henriquemoody and gvieiragoulart committed Nov 26, 2024
1 parent ea3f81f commit cf03f8a
Show file tree
Hide file tree
Showing 25 changed files with 598 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/08-list-of-rules-by-category.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@

- [Date](rules/Date.md)
- [DateTime](rules/DateTime.md)
- [DateTimeDiff](rules/DateTimeDiff.md)
- [LeapDate](rules/LeapDate.md)
- [LeapYear](rules/LeapYear.md)
- [MaxAge](rules/MaxAge.md)
Expand Down Expand Up @@ -323,6 +324,7 @@
- [CurrencyCode](rules/CurrencyCode.md)
- [Date](rules/Date.md)
- [DateTime](rules/DateTime.md)
- [DateTimeDiff](rules/DateTimeDiff.md)
- [Decimal](rules/Decimal.md)
- [Digit](rules/Digit.md)
- [Directory](rules/Directory.md)
Expand Down
1 change: 1 addition & 0 deletions docs/rules/Date.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Version | Description
See also:

- [DateTime](DateTime.md)
- [DateTimeDiff](DateTimeDiff.md)
- [LeapDate](LeapDate.md)
- [LeapYear](LeapYear.md)
- [MaxAge](MaxAge.md)
Expand Down
1 change: 1 addition & 0 deletions docs/rules/DateTime.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ See also:
- [BetweenExclusive](BetweenExclusive.md)
- [Callback](Callback.md)
- [Date](Date.md)
- [DateTimeDiff](DateTimeDiff.md)
- [LeapDate](LeapDate.md)
- [LeapYear](LeapYear.md)
- [MinAge](MinAge.md)
Expand Down
53 changes: 53 additions & 0 deletions docs/rules/DateTimeDiff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# DateTimeDiff

- `DateTimeDiff(string $type, Validatable $rule)`
- `DateTimeDiff(string $type, Validatable $rule, string $format)`

Validates the difference of date/time against a specific rule.

The `$format` argument should follow PHP's [date()][] function. When the `$format` is not given, this rule accepts
[Supported Date and Time Formats][] by PHP (see [strtotime()][]).

```php
v::dateTimeDiff('years', v::equals(7))->validate('7 years ago'); // true
v::dateTimeDiff('years', v::equals(7))->validate('7 years ago + 1 minute'); // false

v::dateTimeDiff('years', v::greaterThan(18), 'd/m/Y')->validate('09/12/1990'); // true
v::dateTimeDiff('years', v::greaterThan(18), 'd/m/Y')->validate('09/12/2023'); // false

v::dateTimeDiff('months', v::between(1, 18))->validate('5 months ago'); // true
```

The supported types are:

* `years`
* `months`
* `days`
* `hours`
* `minutes`
* `seconds`
* `microseconds`

## Categorization

- Date and Time

## Changelog

| Version | Description |
| ------: |--------------------------------------------|
| 3.0.0 | Created from `Age`, `MinAge`, and `MaxAge` |

***
See also:

- [Date](Date.md)
- [DateTime](DateTime.md)
- [Max](Max.md)
- [Min](Min.md)
- [Time](Time.md)

[date()]: http://php.net/date
[DateTimeInterface]: http://php.net/DateTimeInterface
[strtotime()]: http://php.net/strtotime
[Supported Date and Time Formats]: http://php.net/datetime.formats
1 change: 1 addition & 0 deletions docs/rules/Max.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ See also:

- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [DateTimeDiff](DateTimeDiff.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [IterableType](IterableType.md)
Expand Down
1 change: 1 addition & 0 deletions docs/rules/Min.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ See also:

- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [DateTimeDiff](DateTimeDiff.md)
- [Each](Each.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
Expand Down
1 change: 1 addition & 0 deletions docs/rules/Time.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ See also:

- [Date](Date.md)
- [DateTime](DateTime.md)
- [DateTimeDiff](DateTimeDiff.md)
- [LeapDate](LeapDate.md)
- [LeapYear](LeapYear.md)
37 changes: 37 additions & 0 deletions library/Helpers/CanExtractRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
namespace Respect\Validation\Helpers;

use Respect\Validation\Exceptions\ComponentException;
use Respect\Validation\Rules\Core\Composite;
use Respect\Validation\Rules\Not;
use Respect\Validation\Validatable;
use Respect\Validation\Validator;
use Throwable;

use function array_map;
use function count;
Expand All @@ -37,6 +40,40 @@ private function extractSingle(Validatable $rule, string $class): Validatable
return $rule;
}

private function extractSiblingSuitableRule(Validatable $rule, Throwable $throwable): Validatable
{
$this->assertSingleRule($rule, $throwable);

if ($rule instanceof Validator) {
return $rule->getRules()[0];
}

return $rule;
}

private function assertSingleRule(Validatable $rule, Throwable $throwable): void
{
if ($rule instanceof Not) {
$this->assertSingleRule($rule->getRule(), $throwable);

return;
}

if ($rule instanceof Validator) {
if (count($rule->getRules()) !== 1) {
throw $throwable;
}

$this->assertSingleRule($rule->getRules()[0], $throwable);

return;
}

if ($rule instanceof Composite) {
throw $throwable;
}
}

/**
* @param array<Validatable> $rules
*
Expand Down
14 changes: 10 additions & 4 deletions library/Helpers/CanValidateDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ trait CanValidateDateTime
{
private function isDateTime(string $format, string $value): bool
{
$exceptionalFormats = [
'c' => 'Y-m-d\TH:i:sP',
'r' => 'D, d M Y H:i:s O',
];
$exceptionalFormats = $this->getExceptionalFormats();

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

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

return checkdate($info['month'] ?: 1, 1, $info['year'] ?: 1);
}

/** @return array<string, string> */
private function getExceptionalFormats(): array
{
return [
'c' => 'Y-m-d\TH:i:sP',
'r' => 'D, d M Y H:i:s O',
];
}
}
12 changes: 12 additions & 0 deletions library/Mixins/ChainedKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

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

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

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function keyDateTimeDiff(
int|string $key,
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function keyDecimal(int|string $key, int $decimals): ChainedValidator;

public function keyDigit(int|string $key, string ...$additionalChars): ChainedValidator;
Expand Down
11 changes: 11 additions & 0 deletions library/Mixins/ChainedNot.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface ChainedNot
Expand Down Expand Up @@ -91,6 +92,16 @@ public function notDate(string $format = 'Y-m-d'): ChainedValidator;

public function notDateTime(?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function notDateTimeDiff(
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function notDecimal(int $decimals): ChainedValidator;

public function notDigit(string ...$additionalChars): ChainedValidator;
Expand Down
11 changes: 11 additions & 0 deletions library/Mixins/ChainedNullOr.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface ChainedNullOr
Expand Down Expand Up @@ -91,6 +92,16 @@ public function nullOrDate(string $format = 'Y-m-d'): ChainedValidator;

public function nullOrDateTime(?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function nullOrDateTimeDiff(
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function nullOrDecimal(int $decimals): ChainedValidator;

public function nullOrDigit(string ...$additionalChars): ChainedValidator;
Expand Down
12 changes: 12 additions & 0 deletions library/Mixins/ChainedProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface ChainedProperty
Expand Down Expand Up @@ -115,6 +116,17 @@ public function propertyDate(string $propertyName, string $format = 'Y-m-d'): Ch

public function propertyDateTime(string $propertyName, ?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function propertyDateTimeDiff(
string $propertyName,
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function propertyDecimal(string $propertyName, int $decimals): ChainedValidator;

public function propertyDigit(string $propertyName, string ...$additionalChars): ChainedValidator;
Expand Down
11 changes: 11 additions & 0 deletions library/Mixins/ChainedUndefOr.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface ChainedUndefOr
Expand Down Expand Up @@ -95,6 +96,16 @@ public function undefOrDate(string $format = 'Y-m-d'): ChainedValidator;

public function undefOrDateTime(?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function undefOrDateTimeDiff(
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function undefOrDecimal(int $decimals): ChainedValidator;

public function undefOrDigit(string ...$additionalChars): ChainedValidator;
Expand Down
11 changes: 11 additions & 0 deletions library/Mixins/ChainedValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface ChainedValidator extends
Expand Down Expand Up @@ -100,6 +101,16 @@ public function date(string $format = 'Y-m-d'): ChainedValidator;

public function dateTime(?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public function dateTimeDiff(
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public function decimal(int $decimals): ChainedValidator;

public function digit(string ...$additionalChars): ChainedValidator;
Expand Down
12 changes: 12 additions & 0 deletions library/Mixins/StaticKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface StaticKey
Expand Down Expand Up @@ -111,6 +112,17 @@ public static function keyDate(int|string $key, string $format = 'Y-m-d'): Chain

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

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public static function keyDateTimeDiff(
int|string $key,
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public static function keyDecimal(int|string $key, int $decimals): ChainedValidator;

public static function keyDigit(int|string $key, string ...$additionalChars): ChainedValidator;
Expand Down
11 changes: 11 additions & 0 deletions library/Mixins/StaticNot.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Mixins;

use DateTimeImmutable;
use Respect\Validation\Validatable;

interface StaticNot
Expand Down Expand Up @@ -95,6 +96,16 @@ public static function notDate(string $format = 'Y-m-d'): ChainedValidator;

public static function notDateTime(?string $format = null): ChainedValidator;

/**
* @param "years"|"months"|"days"|"hours"|"minutes"|"seconds"|"microseconds" $type
*/
public static function notDateTimeDiff(
string $type,
Validatable $rule,
?string $format = null,
?DateTimeImmutable $now = null,
): ChainedValidator;

public static function notDecimal(int $decimals): ChainedValidator;

public static function notDigit(string ...$additionalChars): ChainedValidator;
Expand Down
Loading

0 comments on commit cf03f8a

Please sign in to comment.