Framework: Dates with year > 10000 are not validated correctly

Created on 8 Apr 2019  路  8Comments  路  Source: laravel/framework

  • Laravel Version: 5.8.8
  • PHP Version: 7.3.1
  • Database Driver & Version: MySQL 5.7.25

Description:

MySQL DATE and DATETIME columns only support year values up to 9999, so it makes sense to validate incoming dates. But dates with year > 10000 still pass all validation checks. This is because the date is passed to PHP strtotime(), and strtotime() ignores the first 4 digits if year has more than 4 digits, e.g. '10001-01-01' is interpreted as '1-01-01'.

Steps To Reproduce:

$ php artisan tinker
Validator::make(['date'=>'10001-01-01'], ['date' => 'date|before:9999-12-31'])->passes()
=> true
Expected result: false

bug

All 8 comments

This is because the date is passed to PHP strtotime(), and strtotime() ignores the first 4 digits if year has more than 4 digits, e.g. '10001-01-01' is interpreted as '1-01-01'.

...so that's a PHP bug then? I dont see what Laravel can do here, the docs clearly start the date validation is using PHP strtotime under the hood...?

From the PHP docs:

For 64-bit versions of PHP, the valid range of a timestamp is effectively infinite, as 64 bits can represent approximately 293 billion years in either direction.

So it should technically work on 64 bit systems. But since it fails on https://3v4l.org/45etH I assume it's indeed a limitation of strtotime. 3v4l probably uses a 32 bit system and if that's the common one I don't believe we can do much about this.

I would like to see that as a problem in the year 9999

This is because the date is passed to PHP strtotime(), and strtotime() ignores the first 4 digits if year has more than 4 digits, e.g. '10001-01-01' is interpreted as '1-01-01'.

...so that's a PHP bug then? I dont see what Laravel can do here, the docs clearly start the date validation is using PHP strtotime under the hood...?

The field under validation must be a valid, non-relative date according to the strtotime PHP function.

According to https://www.php.net/manual/en/datetime.formats.date.php, '10001-01-01' is not a valid date. But passing it to strtotime does not fail, but results in a wrong timestamp instead. I was under the assumption, date validation was supposed to check wether the input is a valid date, not wether strtotime returns false.

@lkreher I do agree with you on that point but it's extremely hard to check on this because there are so many formats that needs to be taken into account. It's hard to know if the the date being passed in question contains a year and that this year is of a value higher than 9999.

@lkreher I do agree with you on that point but it's extremely hard to check on this because there are so many formats that needs to be taken into account. It's hard to know if the the date being passed in question contains a year and that this year is of a value higher than 9999.

I now see what's happening: strtotime is interpreting '10001-01-01' as '10:00 1-01-01'. Maybe I can find some workaround by appending 00:00 to each date field. So yes, this is definitely a PHP bug (or undocumented feature).
For now I wrote my own date validation that checks for 5 digits leading up to a dash before calling the original date validation. Other formats are working as expected, it's just the dash-format that seems to be misinterpreted by strtotime.

What is the reason of closing the bug without taking any step to fix it? I disagree with @laurencei on the note what is being used under the hood. It is not mandatory to use that php function to validate date.

I found the issue on the log while MySQL rejected the value. @driesvints can you please let me know if there is any solution of this issue or are you suggesting to stop using the date rule?

@nasirkhan

I disagree with laurencei on the note what is being used under the hood. It is not mandatory to use that php function to validate date.

Please feel free to submit a PR that you believe will solve the issue if you have an option. But the point is that the date validation is what PHP itself supports - so is it a bug in PHP?

Was this page helpful?
0 / 5 - 0 ratings