Framework: Validator won't accept specific date and time for datetime.

Created on 16 Feb 2018  路  10Comments  路  Source: laravel/framework

  • Laravel Version: 5.6.3
  • PHP Version: 7.2.1
  • Database Driver & Version:

Description:

If i try to validate this datetime "2018-03-25 02:00" it don't pass:
>>> Validator::make(['date' => '2018-03-25 02:00'], ['date' => 'date_format:Y-m-d H:i'])->passes();
=> false

If i try with 01:00 instead, it passes:
>>> Validator::make(['date' => '2018-03-25 01:00'], ['date' => 'date_format:Y-m-d H:i'])->passes()
=> true

Don't know if it matter, but my local timezone is: Europe/Copenhagen (+01:00)

Steps To Reproduce:

Paste the following two sentences in artisan tinker:
Validator::make(['date' => '2018-03-25 02:00'], ['date' => 'date_format:Y-m-d H:i'])->passes();
Validator::make(['date' => '2018-03-25 01:00'], ['date' => 'date_format:Y-m-d H:i'])->passes();

Most helpful comment

That is because on 25th March 2018 daylight savings starts in Europe / Copenhagen.

So at 2018-03-25 01:59:59 the clocks then go forward to 2018-03-25 03:00:00

In other words the 02:00 is invalid on that specific date, which is why its failing.

https://www.timeanddate.com/time/change/denmark/copenhagen

edit: I feel like this is my Jon Skeet moment in life.

All 10 comments

That is because on 25th March 2018 daylight savings starts in Europe / Copenhagen.

So at 2018-03-25 01:59:59 the clocks then go forward to 2018-03-25 03:00:00

In other words the 02:00 is invalid on that specific date, which is why its failing.

https://www.timeanddate.com/time/change/denmark/copenhagen

edit: I feel like this is my Jon Skeet moment in life.

Should that reflect the date_format? Because the format is correct. I don't care about timezones and daylight savings.

The format is not correct though. 2018-03-25 02:00 Europe/Copenhagen is not a valid time. It simply does not exist. It is therefore an invalid format.

If you dont care about timezones or daylight savings - you should be running your application in UTC timezone to avoid issues like this.

Well, not exactly right?, date_format should check format, and even though its a (pretty edge-case) wrong value, the format is right, as it follows Y-m-d H:i.

Wouldn't it make sense to always make the TimeZone (+0) to prevent this from happening, as you're checking the format and not the value?

By that logic - then 2018-02-30 should return true, because it is the right "format" but the wrong "value".

Ultimately this boils down to PHP and not Laravel. This is how PHP handles it. A valid format is a valid date/time.

Wouldn't it make sense to always make the TimeZone (+0) to prevent this from happening, as you're checking the format and not the value?

No, not as a deault. What's the point of having a correct format if it is totally invalid? You might as well have 3023-40-20 26:43 - it means the same thing as it is equally as invalid as the other example, because neither can be parsed into a "real" time.

However you are able to change this in your application by changing the timezone on the fly before the validation. But you need to consider the consequences - what will you do with the time "after" the validation, if it is not really valid? The reality is the original time literally doesnt exist in that timezone. Yes, it "looks" normal - but it is literally invalid (in that timezone).

So passing it through your system could lead to other issues down the path if they are timezone based.

That makes sense for sure, i can definitely get behind that.

But lets say i'm gonna use OP's application from the US or where-ever, and i'm gonna fill a date of 2018-02-03 02:00 for my high speed always on time on the minute package delivery, in this case it is valid, yet the Validator will tell me its not, if the timezone would be defaulted to +00:00 this wont show up anymore right? and 2018-02-30 wont be valid still. Thus removing the edge-case.

But maybe i'm just overthinking and its pretty much a non-issue and the front-end input should prevent inserting this invalid date.

The way to think about it is - it is not 2018-02-03 02:00

It is 2018-02-03 02:00 Europe/Copenhagen - which doesnt exist.

The OP can change it to 2018-02-03 02:00 UTC - which is fine.

But if he then tries to do some calcuations with other times in his system (which are Europe/Copenhagen) - he might get strange results.

Ultimately it is up to the OP how he wants to handle it. Personally this is where I think apps should always run in UTC - then display/format timezones to users at the display level. We have the same issues with schedulers/crons that run in a timezone, they sometimes skip a run (or run twice) during daylight savings causing edge cases like this.

At the end of the day this is a PHP issue for the OP to decide how he wants to handle it, so the issue can be closed here.

Personally this is where I think apps should always run in UTC

Solid advice

Well. I already handle time zones in the system.
Thats why i'm validating the date_format and not date. The format needs to be correct. In the interface i have, we don't care about timezones as this is taken from a geography point of view.
I really don't think date_format should care about timezones and daylight savings. It should check the format. And not the actual date.

As I mentioned - it's how PHP handles it - not Laravel.

Laravel essentually just uses this: http://php.net/manual/en/datetime.format.php

It returns false on times that are invalid.

If your not worried abour timezones - then set it to UTC prior to the validation.

Was this page helpful?
0 / 5 - 0 ratings