Mysql Timestamp difference results - mysql

I have a table with a TIMESTAMP field (lastHonored).
I ran this query:
SELECT NOW(), lastHonored,
TIMESTAMPDIFF(SECOND, lastHonored, NOW()), NOW()-lastHonored
FROM db.table
I get the result:
NOW() | lastHonored | DIFF | SUBTRACT
2014-10-27 14:07:22 | 2014-10-26 19:49:51 | 65851 | 945771
Where DIFF is the result of the TIMESTAMPDIFF function, and SUBTRACT is the result of the NOW()-lastHonored expresssion.
DIFF looks right, but can anyone tell me what NOW()-lastHonored calculates? It is not the right order of magnitude, and I'm stumped.

One would think that NOW() returns a datetime or similar type. But no. For some historical reason, NOW() returns either a number or a string. To quote the documentation:
Returns the current date and time as a value in 'YYYY-MM-DD HH:MM:SS'
or YYYYMMDDHHMMSS format, depending on whether the function is used in
a string or numeric context. The value is expressed in the current
time zone.
That means that NOW() gets converted to a value based on its context. The - suggests a numeric context, so NOW() is a number whose digits are YYYYMMDDHHMMSS. My guess is that lastHonored gets similarly converted, so the result is the difference between two numbers.

You can see why by running:
SELECT CAST(NOW() AS UNSIGNED), CAST('2014-10-26 19:49:51' AS UNSIGNED);
By doing simple subtraction, MySQL is turning both values into numbers. NOW() the DATETIME becomes 20141027141923, but 2014-10-26 19:49:51 the STRING becomes 2014.
If you first cast the date to a DATETIME it gives you results more along the lines of what you expect:
SELECT CAST(NOW() AS UNSIGNED), CAST(CAST('2014-10-26 19:49:51' AS DATETIME) AS UNSIGNED);

You can't subtract dates like you are with NOW()-lastHonored. Dates/datetimes are not directly "subtractable":
MariaDB [test]> select '2014-10-27 08:18:00' - '2014-10-27 08:17:00';
+-----------------------------------------------+
| '2014-10-27 08:18:00' - '2014-10-27 08:17:00' |
+-----------------------------------------------+
| 0 |
+-----------------------------------------------+
1 row in set, 2 warnings (0.00 sec)
MariaDB [test]> show warnings;
+---------+------+---------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '2014-10-27 08:18:00' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '2014-10-27 08:17:00' |
+---------+------+---------------------------------------------------------+
2 rows in set (0.00 sec)
Note the warnings. You'll get results, but they almost always be totally useless/incorrect results, because MySQL is casting the date values as doubles.

They do different things, substraction does not take into account that you are dealing with times.
If you do:
SELECT NOW(), lastHonored,
TIMESTAMPDIFF(SECOND, lastHonored, NOW()) THE_DIFF, NOW()-lastHonored THE_SUBSTRACTION,
NOW()+0 NOW_NUMBER_REPRESNTATION,
lastHonored+0 lastHonored_NUMBER_REPRESENTATION
FROM db.table
You will see the numeric difference is represented with the substraction and the time differente with TIMESTAMPDIFF.

Related

unable to extract date in Mysql when using in where clause in the imdb dataset

This code is ending up with 0 values:
SELECT count(m.id), median_rating
FROM movie as m
INNER JOIN ratings as r ON m.id=r.movie_id
where median_rating=8
AND date_published between str_to_date('01-04-2018','%d-%m-%y')
AND str_to_date('2019-04-01','%y-%m-%d');
Also for Column: date_published Definition is: date_published date
So I want to extract the date in date format from the texts so that I can use it while filtering but its not working,
I tried with string format of dates and the code is working ( WHERE median_rating = 8 AND date_published BETWEEN '2018-04-01' AND '2019-04-01' )
but its not working when I try to extract the dates and compare :/
See https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format
%Y Year, numeric, four digits
%y Year, numeric (two digits)
Using the code for two-digit years does not match your input values.
Demo:
select str_to_date('01-04-2018','%d-%m-%y') as date;
+------------+
| date |
+------------+
| 2020-04-01 |
+------------+
1 row in set, 1 warning (0.00 sec)
Warning (Code 1292): Truncated incorrect date value: '01-04-2018'
select str_to_date('2019-04-01','%y-%m-%d');
+--------------------------------------+
| str_to_date('2019-04-01','%y-%m-%d') |
+--------------------------------------+
| NULL |
+--------------------------------------+
1 row in set, 1 warning (0.00 sec)
Warning (Code 1411): Incorrect datetime value: '2019-04-01' for function str_to_date
Both dates can be parsed if you use the format code for four-digit year, %Y.

Error: Update Varchar values to Datetime in MySQL

DB DETAIL Table name(KK)-
id name date(varchar(50))
1 Ayush 2020-04-19T18:56:09.774Z
I am using this query to convert -
update KK set date=DATE_FORMAT(STR_TO_DATE( KK.date, '%Y-%m-%dT%H:%i:%s' ), '%Y-%m-%d %T') where id=1;
Getting this error
Error Code: 1292. Truncated incorrect datetime value: '2020-04-19T18:56:09.774Z'
Your current date string has .774Z following the seconds, but your STR_TO_DATE() format string doesn't account for it. So it's warning you that there are extra characters at the end of the string that weren't parsed.
If you use '%Y-%m-%dT%H:%i:%s.%fZ' the warning stops.
The times have two parts your format is missing: milliseconds, the .774 part, and the "zulu" time zone Z.
select STR_TO_DATE('2020-04-19T18:56:09.774Z', '%Y-%m-%dT%H:%i:%s.%fZ');
However, since you're truncating them anyway, I'd use the less restrictive format and just ignore the warning.
Since the string is already in ISO 8601 format, you can skip the str_to_date.
mysql> select DATE_FORMAT('2020-04-19T18:56:09.774Z', '%Y-%m-%d %T');
+--------------------------------------------------------+
| DATE_FORMAT('2020-04-19T18:56:09.774Z', '%Y-%m-%d %T') |
+--------------------------------------------------------+
| 2020-04-19 18:56:09 |
+--------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
The MySQL warning is because it doesn't seem to understand that Z is a valid time zone designator.
Note that this will account for a time zone. This may or may not be what you want.
-- date_format will display in the current time zone.
-- I'm in -07:00, so a +00:00 (UTC) date is displayed -7 hours.
mysql> select DATE_FORMAT('2020-04-19T18:56:09.777+00:00', '%Y-%m-%d %T');
+-------------------------------------------------------------+
| DATE_FORMAT('2020-04-19T18:56:09.777+00:00', '%Y-%m-%d %T') |
+-------------------------------------------------------------+
| 2020-04-19 11:56:09 |
+-------------------------------------------------------------+
1 row in set (0.00 sec)
And, finally, consider altering that column to be a datetime type. Then everything is stored in UTC and these conversion problems go away.

Is CURRENT_TIMESTAMP - updated_time same as TIMESTAMPDIFF(SECOND, updated_time, CURRENT_TIMESTAMP )

I wrote a sql to calculate time diff between now and last updated time. Firstly I just use CURRENT_TIMESTAMP - updated_time and found the result looks like correct in time unit second. But it wasn't stable, sometimes the result went to much bigger that correct one. And then I changed to TIMESTAMPDIFF(SECOND, updated_time, CURRENT_TIMESTAMP ) , everything is OK. My question is what's the difference of tow expressions?
The CURRENT_TIMESTAMP() or CURRENT_TIMESTAMP are synonyms for NOW() which gives your current time.
Edit2:
After your additional comment I understood what you are asking. (I have deleted the first edit) which was incomplete and somewhat incorrect.
The question is: "To explain inner workings of CURRENT_TIMESTAMP - updated_time."
The explanation (I went way deeper):
The CURRENT_TIMESTAMP can return date and time in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS format.
What maybe confused you is that it can return either string or numeric value based on the context.
Here you have a numeric context as you have the - (minus) operator.
`String context`
SELECT CURRENT_TIMESTAMP();
-> '2017-07-04 08:50:26'
OR
`numeric context`
SELECT NOW() + 0;
-> 20170704085026
The - (minus) operator only appears to work:
mysql> insert into temp (first, second)
-> VALUES ('2017-07-01 03:00:00', '2017-07-01 03:01:00');
Query OK, 1 row affected (0.00 sec)
mysql> select first, second, second - first from temp;
+---------------------+---------------------+----------------+
| first | second | first - second |
+---------------------+---------------------+----------------+
| 2017-07-01 03:00:00 | 2017-07-01 03:00:37 | 37.000000 |
| 2017-07-01 03:00:00 | 2017-07-01 03:01:00 | 100.000000 |
+---------------------+---------------------+----------------+
2 rows in set (0.00 sec)
Oh nice! 100 seconds in a minute? I don't think so! :).
To correctly subtract your time (if updated_time is in seconds):
The TIME_TO_SEC is needed: TIME_TO_SEC(CURRENT_TIMESTAMP) - updated_time

Possibly Mysql 5.6.20 bug. Date - now()?

date_newOrd, now(), date_newOrd-now() AS `time`
this is my query. date_newOrd is type date. I try to calculate the time remaining for next arrival of order. I better show you the screenshot:
the result is doesn't make any sense. What am i supposed to do>
You cannot subtract dates like that:
mysql> select '2015-06-01 18:20:03' - now();
+-------------------------------+
| '2015-06-01 18:20:03' - now() |
+-------------------------------+
| -20150602073525 |
+-------------------------------+
While that may look (vaguely) like a date, it's really an integer, and can't be used for further date math without extra processing.
You have to use datediff() or timediff():
mysql> select timediff('2015-06-01 18:20:03', now()) as td, datediff('2015-06-01 18:20:03', now()) as dd;
+-----------+------+
| td | dd |
+-----------+------+
| -13:37:47 | -1 |
+-----------+------+
note that datediff deals only with DATES, and timediff deals with datetime values.
When you do a subtraction, MySQL is going to evaluate NOW() in a numeric context, it returns a numeric value.
SELECT NOW()+0
20150602135210.000000
So, your statement is doing a subtraction of numbers, not doing a DATE calculation.
Some possibilities:
You could convert the datetime values into unix_timestamp values, (UNIX_TIMESTMAP() function) and then do a subtraction of those to get a difference in integer seconds.
The DATEDIFF() function would get you a difference in integer days. (That operates only on the date portion, it ignores the time... so that probably doesn't give you the resolution you are looking for.)
The TIMESTAMPDIFF() and TIMEDIFF() functions are also available. (The TIMEDIFF functions returns a TIME datatype value; the maximum value of that datatype is 838:59:59, so that's limited to just under 35 days elapsed).
For example:
SELECT UNIX_TIMESTAMP('2015-06-03') - UNIX_TIMESTAMP(NOW()) AS secs
secs
-------
35856

MySQL TIMEDIFF(DATE, DATETIME)

I have two columns in MySQL database.
One is in DATE format like 2014-01-26, another one is in DATETIME format: 2014-01-25 17:19:07.
I need to apply TIMEDIFF(2014-01-26, 2014-01-25 17:19:07) function, but it requires both variables are in DATETIME format. How can I convert 2014-01-26 to 2014-01-26 00:00:00?
You can always cast a Date to a datetime
select timediff(cast(<yourDateColumn> as Datetime), <yourDatetimeColumn>)
But I'm not even really sure that you need to cast (depending on your mysql version), I may misunderstand the doc, but we can read
Prior to MySQL 5.1.18, when DATE values are compared with DATETIME
values, the time portion of the DATETIME value is ignored, or the
comparison could be performed as a string compare. Starting from MySQL
5.1.18, a DATE value is coerced to the DATETIME type by adding the time portion as '00:00:00'. To mimic the old behavior, use the CAST()
function to cause the comparison operands to be treated as previously.
For example:
You can use date_format()
mysql> select
TIMEDIFF(date_format('2014-01-26','%Y-%m-%d %H:%i:%s'), '2014-01-25 17:19:07')
as diff;
+----------+
| diff |
+----------+
| 06:40:53 |
+----------+
1 row in set (0.00 sec)
mysql> select date_format('2014-01-26','%Y-%m-%d %H:%i:%s') as date;
+---------------------+
| date |
+---------------------+
| 2014-01-26 00:00:00 |
+---------------------+
1 row in set (0.00 sec)