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.
Related
Can't figure out why the following returns false:
$timestamp = '1535552942';
if (time() <= strtotime((int)$timestamp + 10))) // time() = 1535553866
The current time IS greater than the timestamp + 10 s!!! I've checked in logs!
What's wrong with this?
Quoting the docs:
strtotime
Parse about any English textual datetime description into a Unix timestamp
In other words, you pass something that makes sense in English into this function - and expect timestamp as a result.
Instead you pass timestamp into the function, and strtotime just fails to get what you want from it. For example, this online demo shows int(31009790155) as result of strtotime((int)$timestamp + 10)) - which is in the future far far away.
Perhaps you meant it to be implemented this way:
$timestamp = '1535552942';
if ( time() <= strtotime('+10 seconds', $timestamp) ) { ... }
... but actually I fail to see why you can't just add 10 (as a number) to timestamp and then compare it against time() directly. These are the numbers, in the end.
According to the official website of PHP, the definition of function strtotime is....
strtotime
Parse about any English textual datetime description into
a Unix timestamp
What this definition says that you can provide Only English textual datetime. And you are providing it an Integer whereas this strtotime is looking for English textual.
When you will print return value of strtotime it will show your current timestamp.
$timestamp = 'now';
echo strtotime($timestamp);
But when you will try to print its return value with an integer argument, then it will nothing, as given below...
$timestamp = 1535552942;
echo strtotime($timestamp);
Because this function return timestamp on success otherwise return false.
When you will provide it English textual value and try to add one in argument, it will generate a warning...
$timestamp = 'now';
echo strtotime($timestamp+1);
Warning: A non-numeric value encountered in
Because, according to the PHP generates errors or warning on arithmetics with invalid strings.
New E_WARNING and E_NOTICE errors have been introduced when invalid
strings are coerced using operators expecting numbers or their assignment equivalents. An E_NOTICE is emitted when the string begins with a numeric value but contains trailing
non-numeric characters, and an E_WARNING is emitted when the string
does not contain a numeric value.
Whereas above-given snippet fulfill this condition.
So, now just change your value of $timestamp to "now" or any other valid English textual and remove int from your if condition, then it will work perfectly.
$timestamp = "now";
if (time() <= strtotime($timestamp)){
echo "it works";
}
What is the equivalent of this function of php in mysql:
$cba=date_diff($cb,$ca);
$cba->format('%R%a.%h');
output: Date: 1.12 //that's 1day and 12 hours
Here's where I'm going to use it for:
DATEDIFF(q2.adate, q1.deact) AS ND,
Can i do the same process in mysql alone, Thanks
Try this using TIMEDIFF
SELECT CONCAT(
FLOOR(HOUR(TIMEDIFF(q2.adate, q1.deact)) / 24), ' days, ',
MOD(HOUR(TIMEDIFF(q2.adate, q1.deact)), 24), ' hours, '
)
AS ND
MySQL TIMEDIFF() returns the differences between two time or datetime
expressions. It is to be noted that two expressions must be of same
type.
From MySQL Docs:
DATEDIFF() returns expr1 − expr2 expressed as a value in days from one date to the other. expr1 and expr2 are date or date-and-time expressions. Only the date parts of the values are used in the calculation.
You can use TIMEDIFF instead:
TIMEDIFF() returns expr1 − expr2 expressed as a time value. expr1 and expr2 are time or date-and-time expressions, but both must be of the same type.
So the result of TIMEDIFF is like:
-00:00:00.000000 // Negative times
00:00:00.000000 // Positive times
or TIMESTAMPDIFF:
TIMESTAMPDIFF() returns datetime_expr2 − datetime_expr1, where datetime_expr1 and datetime_expr2 are date or datetime expressions. One expression may be a date and the other a datetime; a date value is treated as a datetime having the time part '00:00:00' where necessary. The unit for the result (an integer) is given by the unit argument. The legal values for unit are the same as those listed in the description of the TIMESTAMPADD() function.
So:
SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');
will return 128885 (minutes).
See more about MySQL Date and Time Functions
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.
I have two query conditions here, and I would think that these queries would result in the same data, but they don't.
// 1st Condition:
WHERE month(jurnal.time) >= '01'
AND month(jurnal.time) <= '06'
AND year(jurnal.time) = '2012'
// 2nd Condition:
WHERE jurnal.time > '2012-01-01'
AND jurnal.time <= '2012-06-30'
I want the first condition to result in the same data as the second conditions.
Thanks in advance.
Your first version includes jurnal.time = '2012-01-01', whereas your second condition does not (owing to the use of > rather than >=).
It isn't clear from your question what is the data type of the jurnal.time column:
if it's DATETIME or TIMESTAMP, your second example will not have included any time after 00:00:00 on June 30 so one must instead either take only the date part:
WHERE DATE(jurnal.time) BETWEEN '2012-01-01' AND '2012-06-30'
or else ensure that the comparisons include all times of the day:
WHERE jurnal.time BETWEEN '2012-01-01 00:00:00' AND '2012-06-30 23:59:59'
if it's DATE, this point will not have affected your examples but one can nevertheless simplify your second example to:
WHERE jurnal.time BETWEEN '2012-01-01' AND '2012-06-30'
I recommend the BETWEEN comparison operator with CASTs:
WHERE jurnal.time BETWEEN CAST('2012-01-01' AS DATE) AND CAST ('2012-06-30' AS DATE)
Be sure to cast the stings to the same type as the column of jurnal.time.
Your conditonals in the first query are trying to compare as if they were numbers the values returned from the date parsing functions, but i think they are just strings. '01' and '06' are interperted by sql as plain strings, not the numbers 1 and 6.
The second is sql is smart enough to convert the full date string representation into a date to use in the comparison.
My Queries looks like this
WHERE `Project`.`user_id` = 9
AND `Project`.`project_status` = 1
AND `Project`.`project_type_id` = 4
AND `Project`.`approval_date` >= '01/08/2012'
AND `Project`.`approval_date` <= '01/12/2012'
I do have a record that matches this criteria, I actually created the query based on one of the records but it does not return. I really do not want to use the BETWEEN because the application can either use start date or end date
You should convert '01/08/2012' and '01/12/2012' to MySQL date/time values using STR_TO_DATE()
e.g.
STR_TO_DATE('01/08/2012', '%d/%m/%Y')
Well that's really only part of the query -- any, "between" works differently than you imply - here's an excerpt from the MySQL manual:
•expr BETWEEN min AND max If expr is greater than or equal to min and
expr is less than or equal to max, BETWEEN returns 1, otherwise it
returns 0. This is equivalent to the expression (min <= expr AND expr
<= max) if all the arguments are of the same type. Otherwise type
conversion takes place according to the rules described in Section
11.2, “Type Conversion in Expression Evaluation”, but applied to all the three arguments.
All that aside what is the datatype of the "approval_date" column?
This looks as if it should work on first glance, however the values you have supplied are not valid datetimes. Try this instead
WHERE `Project`.`user_id` = 9
AND `Project`.`project_status` = 1
AND `Project`.`project_type_id` = 4
AND `Project`.`approval_date` >= '2012-01-08 00:00:00'
AND `Project`.`approval_date` <= '2012-01-12 00:00:00'
you can still use BETWEEN
WHERE `Project`.`user_id` = 9
AND `Project`.`project_status` = 1
AND `Project`.`project_type_id` = 4
AND (`Project`.`approval_date` BETWEEN '2012-01-08 00:00:00' AND '2012-01-12 23:59:59')
My main problem was getting the string to format into datetime. kissmyface was correct on just structuring it correctly so mysql could understand. So I used php to convert it before sending it out.
"Project.approval_date >= '".date("Y-m-d H:i:s", strtotime($start))."'";
"Project.approval_date <= '".date("Y-m-d H:i:s",strtotime($end))."'";
this was pretty much my solution. unless anyone knows away to do the exact same thing on mysql side.