PHP compare date without strtotime - php

I am amazed. I forgot to include strtotime but realized that it works in any case. Why does this work?
if($_POST['active_to'] == '' || $_POST['active_to'] >= '2038-01-19'){
$postproduct->active_to = '2025-07-31';
}else{
$postproduct->active_to = $_POST['active_to'];
}

Because YYYY-MM-DD format happens to sort in the same order when using string comparison.
If you were using, say, DD-MM-YYYY format, it wouldn't have worked. Similarly, if you were using YYYY-M-D format (where a leading zero isn't required), it also wouldn't work (because "2010-5-10" comes after "2010-12-10" in string ordering).
"2010-10-05" is greater than "2000-10-05" not because 2010 > 2000, but because "20" = "20" and "1" > "0". The first character that differs between the two strings happens to sort in the right order.

Because the string will be compared lexically character by character.
is 2 larger than 2?
if no, is 0 larger than 0?
if no, ...

You can directly compare the dates only for greater then less then or equal as it is a string.
As long as you have date in YYYY-MM-DD format only. Because YYYY-MM-DD will always change in increment format.
Please keep in mind about the format. Otherwise you have to use strtotime function.

You compare strings. In this operation, strings are converted to the numbers. If you have format Y-m-d, it works well because first is year which is the biggest value (Y*365 days) then month, and then days.
Result can be invalid in some cases because of not equal values of days in month, etc.
Ref: http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.types

IT works because you are doing a string comparison which will work in an or condition, so long as that condition is true.

Related

php 7.4 how to expect date format "ddmmYYYY"

I need to force the users to enter a date like this "ddmmYYYY" e.g : 14012022
The problem I'm facing is that I can't force this format just using this :
DateTime::createFromFormat('dmY', '14012022');
For example, DateTime::createFromFormat('dmY', '212022') for "02012022", it will not return false, although the date will still be wrong at the end.
Is there a way to force the user to pass the exact format that I expect, which is "ddmmYYYY" ?
I need 2 digits for the day, 2 digits for the month, and 4 digits for the year imperatively.
Thanks
How about an addition check by converting the date back to string?
$inputDate = '212022';
$date = DateTime::createFromFormat('dmY', $inputDate);
$valid = $date && $date->format('dmY') == $inputDate;
Since the manual says,
Letters that are used for parsing numbers allow a wide range of values, outside of what the logical range would be.
So string like '32132022' is valid input for createFromFormat, the above method will help you to avoid such date string.

php date("d-m-Y") show 11-09-2017 but I need the date without 0 (11-9-2017)

php date("d-m-Y") code show 11-09-2017. I change it to string and need to compare it to other string, 11-9-2017. How can I change the php date("") to return a result with no 0.
for example change:
08-09-2017 -> 8-9-2017
Thank for the answer.
You used the wrong flags to format the date, you need j and n to meet your criteria as per the documentation.
j Day of the month without leading zeros 1 to 31
n Numeric representation of a month, without leading zeros 1 through 12
Therefore your code becomes,
date("j-n-Y");
You can use n in place of m date("d-n-Y");
date("j-n-Y"); to have it without leading zeros day/month
User strtotime() function convert dates to time and then compare this two dates. date("j-n-Y"); will also work to get exact date.

Create empty date for specific format in PHP

I would like to get date string filled with zeros for specified date format. I want to use it in case when there is no date given by external API.
Example:
define('DATE_FORMAT', 'Y-m-d H:i:s');
[...]
$date = SomeExternalApi::get_date();
// if date is given it's simple
if(!empty($date)){
$date_obj = DateTime::createFromFormat(SomeExternalApi::SOME_DATE_FORMAT, $date_string);
return $date_obj->format(DATE_FORMAT);
}else{
// SO UGLY BELOW! :( How to use DATE_FORMAT in this case?
return '0000-00-00 00:00:00';
}
I don't want to hardcode "zero string" like in example, because when I change DATE_FORMAT I would like to get zeros formatted new way.
Probably there is no simple way to format "zero string" of date, but maybe someone from this great community has better idea? :)
The best answer for my question is: DON'T GO THIS WAY.
You will never need empty date with zeros - it's super uncommon. The only one place where you can find it is database date field - if there is no date, you will get zeros format. But this will be always the same format, so you can define it as constant and condition as string.
Zeros as I asked are BAD because if you send such zeros through some API to any client like mobile app it has no chance to parse it - it will crash the app without catching errors.
Instead of having zeros date presentation use:
[when saving] put empty string in database, you can set date field to empty string and this will become zeros, do it with UPDATE mytable SET date = "" WHERE id = 2; and mytable.date field is MySQL timestamp in this example,
[when getting] you will get zeros with SELECT date FROM mytable WHERE id = 2;, so define it in your code as constant string 0000-00-00 00:00:00 and equal with returning value from db,
[when response of API] if date is empty return false instead of zeros. Mobile app can check if it's false and try to parse it in any other case. It's the best way to keep empty date and is super simple to check in any format by any language. Lot of simpler than trying to parse some strange zeros format.
Generally if I find date by condition like in example I return false and every single client using this API is happy with it:
if(empty($date)){return false;}
Dates and times in PHP are represented with a UNIX timestamp. The range of possible dates this can represent is not capable of representing the timestamp '0000-00-00 00:00:00' on a 32-bit system (it's over 2000 years ago). Also, actually creating a DateTime representing this single timestamp is probably pretty pointless, the values it represents are unchanging.
However, you could do this by defining absolute values for every sensible format character and using strtr() to convert them to their specific values.
Short example using your example input format:
$placeholders = array(
'Y' => '0000',
'm' => '00',
'd' => '00',
'H' => '00',
'i' => '00',
's' => '00'
);
return strtr(DATE_FORMAT, $placeholders);
However, this could start to get messy when you are dealing with the format elements that represent textual elements such as D. Personally I'd probably pick a default format and use that, as your code in the question shows.

Mysql date comparision (greater than equal) without leading zeros

I had to do some date comparision and return a dataset. PHP sent the current date time, with a time with non leading zeros (8:00:00) for 8 am instead of (08:00:00). The case where there were no leading zeros, was giving wrong results. Can someone explain why ?
To test, run this SELECT IF(DATE_ADD('2011-03-20', INTERVAL '08:05:00' HOUR_SECOND) >= '2011-03-20 8:00:00',"yes","No")
result: No
AND
SELECT IF(DATE_ADD('2011-03-20', INTERVAL '08:05:00' HOUR_SECOND) >= '2011-03-20 08:00:00',"yes","No")
result: Yes
shouldn't both give the result : "Yes"
Is it doing string comparison for a non leading zero ?
I think this is to do with MySQL's rather dodgy date / time handling in som ecases MySQL converts to a numeric and in other cases it uses string comparisons.
From the manual
http://dev.mysql.com/doc/refman/5.0/en/using-date.html
When you compare a DATE, TIME, DATETIME, or TIMESTAMP to a constant string with the <, <=, =, >=, >, or BETWEEN operators, MySQL normally converts the string to an internal long integer for faster comparison (and also for a bit more “relaxed” string checking). However, this conversion is subject to the following exceptions:
When you compare two columns
When you compare a DATE, TIME, DATETIME, or TIMESTAMP column to an expression
When you use any other comparison method than those just listed, such as IN or STRCMP().
For these exceptional cases, the comparison is done by converting the objects to strings and performing a string comparison.
Strictly speaking, you are comparing against strings (not dates) and relying on automatic casting. Try this instead:
SELECT
IF(DATE_ADD('2011-03-20', INTERVAL '08:05:00' HOUR_SECOND) >= STR_TO_DATE('2011-03-20 8:00:00', '%Y-%m-%d %H:%i:%s'), 'Yes', 'No'),
IF(DATE_ADD('2011-03-20', INTERVAL '08:05:00' HOUR_SECOND) >= STR_TO_DATE('2011-03-20 08:00:00', '%Y-%m-%d %H:%i:%s'), 'Yes', 'No')
Update:
According to the manual, DATE_ADD() can return a date or a string:
The return value depends on the
arguments:
DATETIME if the first argument is a DATETIME (or TIMESTAMP) value,
or if the first argument is a DATE and the unit value uses HOURS,
MINUTES, or SECONDS.
String otherwise.
To ensure that the result is DATETIME,
you can use CAST() to convert the
first argument to DATETIME.
So the left operand of the >= comparison is a string thus you're getting string comparisons. Try the CAST('2011-03-21' AS DATE) suggestion.

Shortest way to compare 2 dates in dd/mm/yyyy format

can anyone suggest the neatest way to do this comparison? I need to test if a date provided in dd/mm/yyyy format is less than a fixed date, e.g 01/05/2009 - I know I can convert these to unix time format using strtotime, then make the comparison, but I'm curious if there is a quicker way to do it - many thanks, just looking for a hint to improve my code!
One option is just to reverse the format - create a string of the form
yyyy/mm/dd
That's a sortable format, so you can just do an ordinal string comparison. Of course, this means you won't detect invalid data etc.
There's probably not a shorter way code wise, and I wouldn't bother optimizing this unless you're sure it's a bottleneck.
However, as long as you're sure it will always be the exact same format (including 2 digits for month and day and with 0s) you should be able to reorder the string to put the year first, then the month, and then the day, and then just compare the strings.
However, I'm not sure this would be faster than just letting the libraries convert to unix time and then comparing those.
If you can change the format that the dates are stored in, you could define them as yyyy/mm/dd and then just compare the strings.
I think that your solution of converting it to Epoch then doing a comparison is as fast and as clean as your going to get.
if you want to improve your code, I would suggest you to use DateTime class. It's been introduced in php 5.2.0 (so, it still might not be supported on all servers)
in php 5.3.0 you can write something like this:
$d1 = DateTime::createFromFormat('d/m/Y', '02/03/2009');
$d2 = DateTime::createFromFormat('d/m/Y', '02/05/2009');
$interval = $d1->diff($d2);
echo $interval->format('%R%d days');
Well, you could use the PHP date class, but I am not sure it would be any better than you current solution...
http://php.net/manual/en/book.datetime.php
use this method
yearmonthday
you have 01.05.2010 and 03.07.2010
and to compare : 20100501 <= or => 20100703
$fixedDate = '01/05/2009';
$variableDate = '28/04/2010';
// Now we do our timestamping magic!
$fixedDate = implode('', array_reverse(explode('/', $fixedDate)));
$variableDate = implode('', array_reverse(explode('/', $variableDate)));
if ($variableDate < $fixedDate) // 20100428 < 20090501
{
// there you go
}

Categories