Fix wrong behavior of "Date" rule

The validation was considering "99" as a valid month and neither
date_parse_from_format() [1] or DateTime::createFromFormat() [2] would
complain about that.

The solution for that was to use checkdate() [3] to verify whether the
date is valid or not. Also, an extra step was added to the validation
that a date that only contains a day would return false since a day
without a month and year is impossible to validate.

Apparently, there is no problem while validation when it comes to time,
therefore nothing needed to be added for this validation.

[1]: http://php.net/date_parse_from_format
[2]: http://php.net/datetime.createFromFormat
[3]: http://php.net/checkdate

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
Henrique Moody 2018-08-29 21:04:17 +02:00
parent 52614d600d
commit a039d6d4b9
No known key found for this signature in database
GPG key ID: 221E9281655813A6
2 changed files with 86 additions and 2 deletions

View file

@ -49,8 +49,39 @@ class Date extends AbstractRule
$this->format = $exceptionalFormats[$this->format];
}
$info = date_parse_from_format($this->format, $inputString);
return $this->isValidForFormatProvided($input);
}
private function isValidForFormatProvided($input)
{
$info = date_parse_from_format($this->format, $input);
if (!$this->isParsable($info)) {
return false;
}
if ($this->hasDateFormat()) {
return $this->hasValidDate($info);
}
return true;
}
private function isParsable(array $info)
{
return ($info['error_count'] === 0 && $info['warning_count'] === 0);
}
private function hasDateFormat()
{
return preg_match('/[djSFmMnYy]/', $this->format) > 0;
}
private function hasValidDate(array $info)
{
if ($info['day']) {
return checkdate((int) $info['month'], $info['day'], (int) $info['year']);
}
return checkdate($info['month'] ?: 1, $info['day'] ?: 1, $info['year'] ?: 1);
}
}

View file

@ -19,7 +19,7 @@ use DateTimeImmutable;
* @covers Respect\Validation\Rules\Date
* @covers Respect\Validation\Exceptions\DateException
*/
class DateTest extends \PHPUnit_Framework_TestCase
class DateTest extends RuleTestCase
{
protected $dateValidator;
@ -150,4 +150,57 @@ class DateTest extends \PHPUnit_Framework_TestCase
['UTC', 'z', 320],
];
}
/**
* {@inheritdoc}
*/
public function providerForValidInput()
{
return [
[new Date(), 'now'],
[new Date(), 'today'],
[new Date(), 'tomorrow'],
[new Date(), 'yesterday'],
[new Date(), '+1 day'],
[new Date(), 'next Thursday'],
[new Date(), '+1 week 2 days 4 hours 2 seconds'],
[new Date(), 2018],
[new Date(), new DateTime()],
[new Date('Y-m-d'), '2009-09-09'],
[new Date('d/m/Y'), '23/05/1987'],
[new Date('c'), '2004-02-12T15:19:21+00:00'],
[new Date('r'), 'Thu, 29 Dec 2005 01:02:03 +0000'],
[new Date('U'), 1464658596],
[new Date('h'), 6],
[new Date('z'), 320],
[new Date('Ym'), 202302],
[new Date('m'), 12],
[new Date('Y'), 2000],
];
}
/**
* {@inheritdoc}
*/
public function providerForInvalidInput()
{
return [
[new Date(), 'not-a-date'],
[new Date(), []],
[new Date(), true],
[new Date(), false],
[new Date(), null],
[new Date(), ''],
[new Date('Y-m-d'), '2009-12-00'],
[new Date('Y-m-d'), '2018-02-29'],
[new Date('h'), 24],
[new Date(), '2014-99'],
[new Date('d'), 1],
[new Date('Y-m'), '2014-99'],
[new Date('m'), '99'],
[new Date('H'), '24'],
[new Date('i'), '60'],
[new Date('s'), '60'],
];
}
}