convert negative unixtimestamp to normal datetime - mysql

There is a problem when using Mysql to extract data: negative timestamp cannot pass FROM_ UNIXTIME method converted to normal date:
FROM_UNIXTIME(-2641363543)
Null
I know the correct date corresponding to this timestamp is: 1886-04-20 00:00:00. I searched for it, and some people suggested that can be calculated in a relative way:
DATE_ADD(FROM_UNIXTIME(0), INTERVAL -2641363543 SECOND)
1886-04-19 23:54:17
But there is a few minutes gap between the calculated period and the correct value. I don't know what the problem is and what the correct method should be.

It's pretty clear just from looking at it that -2641363543 is not midnight. If subtracted from 1970-01-01 00:00:00 it would need to end with a zero.
According to both Ruby and Perl it is 1886-04-19 15:54:17 UTC.
> Time.at(-2641363543).utc
=> 1886-04-19 15:54:17 UTC
You want -2641334400.
> Time.gm(1886, 4, 20).to_i
=> -2641334400
And the technique does work.
mysql> set time_zone = '+00:00';
Query OK, 0 rows affected (0.01 sec)
mysql> select FROM_UNIXTIME(0) + INTERVAL -2641334400 SECOND;
+------------------------------------------------+
| FROM_UNIXTIME(0) + INTERVAL -2641334400 SECOND |
+------------------------------------------------+
| 1886-04-20 00:00:00 |
+------------------------------------------------+
Which brings us to perhaps the real problem...
the correct date corresponding to this timestamp is: 1886-04-20 00:00:00
Correct for which time zone?

Related

Select a record based on timestamp

I have a table that has a column row filled with a Javascript's, Date.now() function.
The column name is update_time, and its sample value is 1571152209099.
How can I make a Select for all rows that have todays date (taking into account only year, month and a day)?
I have tried something like this, but it get's me nowhere.
Select *
from program_end
where workout_rate between 0 and 1
AND FROM_UNIXTIME(update_time, '%YYYY-%MM-%DD') = CURDATE()
I also tried changing the time format:
Select *
from program_end
where FROM_UNIXTIME(update_time, '%Y-%m-%d') = CURDATE()
But no result whatsoever.
Any insight is appreciated.
For insight, consider:
SELECT '1970-01-01' + INTERVAL ( 1571152209099 /1000) SECOND
returns:
_dt
--------------------------
2019-10-15 15:10:09.099000
We recognize that the 1571152209099 value from JavaScipt Date.now() is integer milliseconds from the beginning of the era (Jan 1, 1970 midnight UTC).
Also consider:
SELECT TIMESTAMPDIFF(SECOND,'1970-01-01 00:00','2019-10-15 00:00')*1000 AS _dt_1
, TIMESTAMPDIFF(SECOND,'1970-01-01 00:00','2019-10-16 00:00')*1000 AS _dt_2
returns:
_dt_1 _dt_2
------------- --------------
1571097600000 1571184000000
The TIMESTAMPDIFF function is returning a difference in seconds; we multiply by 1000 to get milliseconds.
We recognize that any JavaScript Date.now() milliseconds value that is greater than or equal to _dt_1 and is less than _dt_2 occurs sometime "on" the date '2109-10-15'
So, given update_time is milliseconds since the beginning of the era...
In a query, I would compare the bare update_time column to two literal values:
WHERE update_time >= 1571097600000
AND update_time < 1571184000000
Referencing the bare column has the advantage that MySQL can make use of an efficient range scan operation, with a suitable index available.
To derive those millisecond values from a given date value, we can do a calculation in an expression, like this:
WHERE update_time >= TIMESTAMPDIFF(SECOND,'1970-01-01', '2019-10-15' )*1000
AND update_time < TIMESTAMPDIFF(SECOND,'1970-01-01', '2019-10-15' + INTERVAL 1 DAY)*1000
^^^^^^^^^^
Those expressions on the right side get evaluated just one time at the start of the statement execution.
Note that if we wrap update_time in a function, then that function has to be evaluated for every value of update_time, for every row in the table (that isn't filtered out by some other predicate.)
If you don't have dates in the future, you can simply do:
WHERE update_time >= UNIX_TIMESTAMP(CURDATE())
This will happily use an existing index on update_time.
If you have dates in the future that you need to exclude from the resultset, then:
WHERE
update_time >= UNIX_TIMESTAMP(CURDATE())
AND update_time < UNIX_TIMESTAMP(CURDATE() + INTERVAL 1 DAY)
Javascript's Date.now is giving you milliseconds, whereas MySQL's FROM_UNIXTIME expects seconds.
Unable to understand the epoch timestamp in milliseconds, FROM_UNIXTIME is returning NULL, which is of course failing to match the current date.
mysql> SELECT FROM_UNIXTIME(1571152209099);
+------------------------------+
| FROM_UNIXTIME(1571152209099) |
+------------------------------+
| NULL | -- THIS IS YOUR PROBLEM
+------------------------------+
1 row in set (0.00 sec)
mysql> SELECT FROM_UNIXTIME(1571152209099/1000);
+-----------------------------------+
| FROM_UNIXTIME(1571152209099/1000) |
+-----------------------------------+
| 2019-10-15 10:10:09.0990 |
+-----------------------------------+
1 row in set (0.00 sec)
Try this:
FROM_UNIXTIME(FLOOR(update_time/1000), format...)

How can I convert MySQL date stored as negative (signed) bigint to date format?

I have birth dates stored in a MySQL database that I need converted to a readable date format yyyy-mm-dd hh:mm:ss. I cannot use the MySQL's From_Unix function as many birth dates are before 1970 and the function returns NULL. (i.e. -866138400000 which is 07/21/1942)
I have tried to use ticks but that is also returning NULL:
(FROM_DAYS(365 + (req.PATIENTDOB / 864000000000)) + INTERVAL (req.PATIENTDOB % 864000000000) / 10000000 SECOND) AS ptDob
Any advance would be greatly appreciated. Thank you.
I have no idea why you're making things so complicated. Just divide by 1000 to get seconds instead of microseconds and subtract that from 1970-01-01.
mysql > select '1970-01-01' + interval -866138400000/1000 second;
+---------------------------------------------------+
| '1970-01-01' + interval -866138400000/1000 second |
+---------------------------------------------------+
| 1942-07-22 06:00:00 |
+---------------------------------------------------+
1 row in set (0.00 sec)
So your query would actually be this of course:
select '1970-01-01' + interval your_column / 1000 second from your_table;
This query proves, that your assumption, that it would be 1942-07-21 is wrong. 1942-07-22 is correct.
mysql > select timestampdiff(second, '1942-07-21', '1970-01-01');
+---------------------------------------------------+
| timestampdiff(second, '1942-07-21', '1970-01-01') |
+---------------------------------------------------+
| 866246400 |
+---------------------------------------------------+
Found an answer while researching Negative Epochs. I was able to use the From_Unixtime function after all!
select date_format((DATE_ADD(FROM_UNIXTIME(0), interval -866138400000/ 1000 second)),'%Y-%m-%d') as ptdate;
-> "1942-07-21"
Link to Reference > Look under Negative Epochs section

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

Mysql DATETIME evaluation: Get all records whose value is before midnight of the current day (basically yesterday and before

This is really simple yet I always struggle with it. I need help getting records before midnight:
AND last_checked < date('2013-06-25 00:00:00'))
This obviously doesn't work, since its string evaluation. I do not want to restrict it to this year and put a between in the code. Any help is extremely appreciated :)
You can also do this in a generic way
AND last_checked < ( DATE(NOW()) + INTERVAL 0 SECOND );
Watch this:
mysql> SELECT DATE(NOW()) + INTERVAL 0 SECOND Midnight;
+---------------------+
| Midnight |
+---------------------+
| 2013-06-25 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
mysql>
You should be able to just do
AND last_checked < '2013-06-25 00:00:00'
Using the date() function just extracts the date part of the argument.
If last_checked is of datetime data type, then your WHERE clause will look like this:
WHERE ...
AND cast (last_checked as date) = '2013-06-25'
CAST (datetime as date) drops time part, so you can easily get all data between 00h:00m:00s and 23h:59m:59s .

Date time comparisons

I have a date column for ex: 03/08/2011 & i need to make that as end of the day ie. 03/08/2011 12:00:00 in UTC time format & then add some integer value in minutes say for ex:10 (in mins)-> 03/08/2011 12:10:00. This value is used as end value.
There will be some start value like for ex: 03/07/2011 22:10:00 & i need to get current date time in UTC, do a comparison to see & return 1 if current date time falls between start & end value else return 0.
All in a single select query in mysql.
Thanks.
It's not clear exactly what you need, but I'll give you a couple of specific examples that should help.
1) Converting a MM/DD/YYYY string to a date and adding 10 minutes to it:
mysql> SELECT STR_TO_DATE('03/08/2011', '%m/%d/%Y') + INTERVAL 10 MINUTE;
+------------------------------------------------------------+
| STR_TO_DATE('03/08/2011', '%m/%d/%Y') + INTERVAL 10 MINUTE |
+------------------------------------------------------------+
| 2011-03-08 00:10:00 |
+------------------------------------------------------------+
1 row in set (0.00 sec)
2) Getting the current timestamp in UTC:
mysql> SELECT UTC_TIMESTAMP();
+---------------------+
| UTC_TIMESTAMP() |
+---------------------+
| 2011-03-08 20:33:53 |
+---------------------+
1 row in set (0.00 sec)