CURRENT_TIMESTAMP in milliseconds - mysql

Is there any way to get milliseconds out of a timestamp in MySql or PostgreSql (or others just out of curiosity)?
SELECT CURRENT_TIMESTAMP
--> 2012-03-08 20:12:06.032572
Is there anything like this:
SELECT CURRENT_MILLISEC
--> 1331255526000
or the only alternative is to use the DATEDIFF from the era?

For MySQL (5.6+) you can do this:
SELECT ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)
Which will return (e.g.):
1420998416685 --milliseconds

To get the Unix timestamp in seconds in MySQL:
select UNIX_TIMESTAMP();
Details: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_unix-timestamp
Not tested PostgreSQL, but according to this site it should work: http://www.raditha.com/postgres/timestamp.php
select round( date_part( 'epoch', now() ) );

In mysql, it is possible to use the uuid function to extract milliseconds.
select conv(
concat(
substring(uid,16,3),
substring(uid,10,4),
substring(uid,1,8))
,16,10)
div 10000
- (141427 * 24 * 60 * 60 * 1000) as current_mills
from (select uuid() uid) as alias;
Result:
+---------------+
| current_mills |
+---------------+
| 1410954031133 |
+---------------+
It also works in older mysql versions!
Thank you to this page: http://rpbouman.blogspot.com.es/2014/06/mysql-extracting-timstamp-and-mac.html

The main misunderstanding in MySQL with timestamps is that MySQL by default both returns and stores timestamps without a fractional part.
SELECT current_timestamp() => 2018-01-18 12:05:34
which can be converted to seconds timestamp as
SELECT UNIX_TIMESTAMP(current_timestamp()) => 1516272429
To add fractional part:
SELECT current_timestamp(3) => 2018-01-18 12:05:58.983
which can be converted to microseconds timestamp as
SELECT CAST( 1000*UNIX_TIMESTAMP(current_timestamp(3)) AS UNSIGNED INTEGER) ts => 1516272274786
There are few tricks with storing in tables. If your table was created like
CREATE TABLE `ts_test_table` (
`id` int(1) NOT NULL,
`not_fractional_timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
than MySQL will NOT store fractional part within it:
id, not_fractional_timestamp
1, 2018-01-18 11:35:12
If you want to add fractional part into your table, you need to create your table in another way:
CREATE TABLE `ts_test_table2` (
`id` int(1) NOT NULL,
`some_data` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`fractional_timestamp` timestamp(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
that leads to required result:
id, some_data, fractional_timestamp
1, 8, 2018-01-18 11:45:40.811
current_timestamp() function is allowed to receive value up to 6, but I've found out (at least in my installed MySQL 5.7.11 version on Windows) that fraction precision 6 leads to the same constant value of 3 digits at the tail, in my case 688
id, some_data, fractional_timestamp
1, 2, 2018-01-18 12:01:54.167688
2, 4, 2018-01-18 12:01:58.893688
That means that really usable timestamp precision of MySQL is platform-dependent:
on Windows: 3
on Linux: 6

In Mysql 5.7+ you can execute
select current_timestamp(6)
for more details
https://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html

Poster is asking for an integer value of MS since Epoch, not a time or S since Epoch.
For that, you need to use NOW(3) which gives you time in fractional seconds to 3 decimal places (ie MS precision): 2020-02-13 16:30:18.236
Then UNIX_TIMESTAMP(NOW(3)) to get the time to fractional seconds since epoc:
1581611418.236
Finally, FLOOR(UNIX_TIMESTAMP(NOW(3))*1000) to get it to a nice round integer, for ms since epoc:
1581611418236
Make it a MySQL Function:
CREATE FUNCTION UNIX_MS() RETURNS BIGINT DETERMINISTIC
BEGIN
RETURN FLOOR(UNIX_TIMESTAMP(NOW(3))*1000);
END
Now run SELECT UNIX_MS();
Note: this was all copied by hand so if there are mistakes feel free to fix ;)

Use:
Select curtime(4);
This will give you milliseconds.

The correct way of extracting miliseconds from a timestamp value on PostgreSQL accordingly to current documentation is:
SELECT date_part('milliseconds', current_timestamp);
--OR
SELECT EXTRACT(MILLISECONDS FROM current_timestamp);
with returns: The seconds field, including fractional parts, multiplied by 1000. Note that this includes full seconds.

Easiest way I found to receive current time in milliseconds in MySql:
SELECT (UNIX_TIMESTAMP(NOW(3)) * 1000)
Since MySql 5.6.

None of these responses really solve the problem in postgreSQL, i.e :
getting the unix timestamp of a date field in milliseconds
I had the same issue and tested the different previous responses without satisfying result.
Finally, I found a really simple way, probably the simplest :
SELECT ROUND(EXTRACT (EPOCH FROM <date_column>::timestamp)::float*1000) as unix_tms
FROM <table>
namely :
We extract the pgSQL EPOCH, i.e. unix timestamp in floatting seconds from our column casted in timestamp prudence (in some complexe queries, pgSQL could trow an error if this cast isn't explicit. See )
then we cast it in float and multiply it by 1000 to get the value in milliseconds
then we round it to drop the fractional part

In PostgreSQL you can use :
SELECT extract(epoch from now());
on MySQL :
SELECT unix_timestamp(now());

Here's an expression that works for MariaDB and MySQL >= 5.6:
SELECT (UNIX_TIMESTAMP(NOW()) * 1000000 + MICROSECOND(NOW(6))) AS unix_now_in_microseconds;
This relies on the fact that NOW() always returns the same time throughout a query; it's possible that a plain UNIX_TIMESTAMP() would work as well, I'm not sure based on the documentation. It also requires MySQL >= 5.6 for the new precision argument for NOW() function (MariaDB works too).

Postgres: SELECT (extract(epoch from now())*1000)::bigint;

In MariaDB you can use
SELECT NOW(4);
To get milisecs. See here, too.

In PostgreSQL we use this approach:
SELECT round(EXTRACT (EPOCH FROM now())::float*1000)

For mysql:
SELECT (UNIX_TIMESTAMP() * 1000) AS unix_now_in_microseconds; --- 1600698677000

I felt the need to continue to refine, so in MySQL:
Current timestamp in milliseconds:
floor(unix_timestamp(current_timestamp(3)) * 1000)
Timestamp in milliseconds from given datetime(3):
floor(unix_timestamp("2015-04-27 15:14:55.692") * 1000)
Convert timestamp in milliseconds to datetime(3):
from_unixtime(1430146422456 / 1000)
Convert datetime(3) to timestamp in milliseconds:
floor(unix_timestamp("2015-04-27 14:53:42.456") * 1000)

For everyone here, just listen / read the comments of Doin very good! The UNIX_TIMESTAMP() function will, when a datatime-string is given, contact a local time, based on the timezone of the MySQL Connection or the server, to a unix timestamp. When in a different timezone and dealing with daylight savings, one hour per year, this will go wrong!
For example, in the Netherlands, the last Sunday of October, a second after reaching 02:59:59 for the first time, the time will be set back to 02:00:00 again. When using the NOW(), CURTIME() or SYSDATE()-functions from MySQL and passing it to the UNIX_TIMESTAMP() function, the timestamps will be wrong for a whole our.
For example, on Satudray 27th of October 2018, the time and timestamps went like this:
Local time | UTC Time | Timestamp | Timestamp using MYSQL's UNIX_TIMESTAMP(NOW(4))
----------------------------------+---------------------------+--------------+-----------------------------------------------------
2018-10-27 01:59:59 CET (+02:00) | 2018-10-26 23:59:59 UTC | 1540598399 | 1540598399
2018-10-27 02:00:00 CET (+02:00) | 2018-10-27 00:00:00 UTC | 1540598400 | 1540598400 + 1 second
2018-10-27 02:59:59 CET (+02:00) | 2018-10-27 00:59:59 UTC | 1540601999 | 1540601999
2018-10-27 03:00:00 CET (+02:00) | 2018-10-27 01:00:00 UTC | 1540602000 | 1540602000 + 1 second
2018-10-27 03:59:59 CET (+02:00) | 2018-10-27 01:59:59 UTC | 1540605599 | 1540605599
2018-10-27 04:00:00 CET (+02:00) | 2018-10-27 02:00:00 UTC | 1540605600 | 1540605600 + 1 second
But on Sunday 27th of October 2019, when we've adjusted the clock one hour. Because the local time, doensn't include information whether it's +02:00 or +01:00, converting the time 02:00:00 the first time and the second time, both give the same timestamp (from the second 02:00:00) when using MYSQL's UNIX_TIMESTAMP(NOW(4)) function. So, when checking the timestamps in the database, it did this: +1 +1 +3601 +1 +1 ... +1 +1 -3599 +1 +1 etc.
Local time | UTC Time | Timestamp | Timestamp using MYSQL's UNIX_TIMESTAMP(NOW(4))
----------------------------------+---------------------------+--------------+-----------------------------------------------------
2019-10-27 01:59:59 CET (+02:00) | 2019-10-26 23:59:59 UTC | 1572134399 | 1572134399
2019-10-27 02:00:00 CET (+02:00) | 2019-10-27 00:00:00 UTC | 1572134400 | 1572138000 + 3601 seconds
2019-10-27 02:59:59 CET (+02:00) | 2019-10-27 00:59:59 UTC | 1572137999 | 1572141599
2019-10-27 02:00:00 CET (+01:00) | 2019-10-27 01:00:00 UTC | 1572138000 | 1572138000 - 3599 seconds
2019-10-27 02:59:59 CET (+01:00) | 2019-10-27 01:59:59 UTC | 1572141599 | 1572141599
2019-10-27 03:00:00 CET (+01:00) | 2019-10-27 02:00:00 UTC | 1572141600 | 1572141600 + 1 second
Relaying on the UNIX_TIMESTAMP()-function from MySQL when converting local times, unfortunately, is very unreliable! Instead of using SELECT UNIX_TIMESTAMP(NOW(4)), we're now using the code below, which seams to solve the issue.
SELECT ROUND(UNIX_TIMESTAMP() + (MICROSECOND(UTC_TIME(6))*0.000001), 4)

Mysql:
SELECT REPLACE(unix_timestamp(current_timestamp(3)),'.','');

I faced the same issue recently and I created a small github project that contains a new mysql function UNIX_TIMESTAMP_MS() that returns the current timestamp in milliseconds.
Also you can do the following :
SELECT UNIX_TIMESTAMP_MS(NOW(3)) or SELECT UNIX_TIMESTAMP_MS(DateTimeField)
The project is located here : https://github.com/silviucpp/unix_timestamp_ms
To compile you need to Just run make compile in the project root.
Then you need to only copy the shared library in the /usr/lib/mysql/plugin/ (or whatever the plugin folder is on your machine.)
After this just open a mysql console and run :
CREATE FUNCTION UNIX_TIMESTAMP_MS RETURNS INT SONAME 'unix_timestamp_ms.so';
I hope this will help,
Silviu

Do as follows for milliseconds:
select round(date_format(CURTIME(3), "%f")/1000)
You can get microseconds by the following:
select date_format(CURTIME(6), "%f")

Related

MySQL DateTime select with interval

I am trying to select from a table where a DateTime field is older than 15 minutes. The query seemed to be working fine till just after midnight. Not sure how to make MySQL distinguish between AM and PM. Any help in the right direction would be helpful.
Example:
Current time: 11:50 (AM)
last_successful_run: 12:02 (AM)
This should be selected b/c 12:02 (AM) is over 15 older than 11:50 (am)
Insert in the format "yyyy-MM-dd hh:mm:ss"
last_successful_run is type DATETIME Default/Expression = NULL
Table
ID | last_successful_run
1 | 2019-02-07 12:06:37
2 | 2019-02-07 12:05:15
3 | 2019-02-07 12:00:12
4 | 2019-02-07 12:10:37
SELECT QRY
SELECT `ID`
FROM reports.tests
WHERE `last_successful_run` < DATE_SUB(NOW(), INTERVAL 15 MINUTE)
One possibility could be that you are checking it against your local machine time and MySQL installed on another machine with different time.
The issue was on the insert to the database. By changing the insert format of the string from "yyyy-MM-dd hh:mm:ss" to "yyyy-MM-dd HH:mm:ss", this allows inserts transition from 2018-02-23 02:24:24 to 2018-02-23 14:24:24.

mysql getting epoch time

I am using a table with:
CREATE TABLE tv (
datetime datetime NOT NULL,
value int(4),
metric varchar(25),
PRIMARY KEY (datetime)
);
My system is in CET so I get this from a select:
select * from tv;
+---------------------+-------+----------+
| datetime | value | metric |
+---------------------+-------+----------+
| 2017-08-09 14:17:27 | 0 | TV power |
| 2017-08-09 14:20:04 | 0 | TV power |
| 2017-08-09 14:40:04 | 0 | TV power |
| 2017-08-09 14:45:03 | 0 | TV power |
When I try to graph it (in grafana), I use:
SELECT
UNIX_TIMESTAMP(datetime) as time_sec,
value,
metric
FROM tv
ORDER BY datetime
And it works fine except that it writes everything with 2 hours more in the future. So I guess this is because the UNIX_TIMESTAMP is thinking that the datetime is in UTC and looking at the system value, as it is CET, it is doing a +02:00 before converting to epoch or something like this.
I get this also:
SELECT ##global.time_zone;
+--------------------+
| ##global.time_zone |
+--------------------+
| SYSTEM |
+--------------------+
1 row in set (0.00 sec)
Meaning it is using the system timezone which is CET.
How can I get my UNIX_TIMESTAMP to convert correctly to the CET?
Thanks.
Here is what the documentation has to say about UNIX_TIMESTAMP:
If UNIX_TIMESTAMP() is called with a date argument, it returns the value of the argument as seconds since '1970-01-01 00:00:00' UTC.
From what I understand, MySQL is shifting the input timestamp to UTC time, doing the calculation, and then returning the offset still in UTC time. One option to correct for this would be to shift your timestamps from "UTC" time to "CET" time before calling UNIX_TIMESTAMP. I use quotes here, because your timestamps are already in the desired CET timezone, but we have to spoof MySQL by countering its own efforts to be smart and convert everything to UTC.
Something along these lines should work:
SELECT
UNIX_TIMESTAMP(CONVERT_TZ(datetime, 'UTC', 'CET')) AS time_sec,
value,
metric
FROM tv
ORDER BY datetime
Once again, we are shifting your timestamps from UTC to CET time, to offset UNIX_TIMESTAMP() which will be doing the opposite of that.
If the call above to CONVERT_TZ() does not work for you, you may have to spend some time configuring your MySQL timezone tables. Here is a SO question which will get you started:
Database returned an invalid value in QuerySet.dates()
As a final comment, I think the best long term solution for you would be to just store your timestamps in UTC time. Then, you only need to convert for incoming and outgoing dates, but not for internal MySQL calculations. Storing all timestamp information in UTC time is a common database practice.

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

Better way to safely insert UTC time value into mySQL TIMESTAMP variable?

My application wants to insert a timestamp value into a TIMESTAMP variable in a mySQL database. The timestamp value is a UTC time in the usual "YYYY-MM-DD HH:MM:SS" format. The problem is that my SQL server is set to use SYSTEM time (SELECT ##global.time_zone says SYSTEM), and the system timezone is Europe/London (the server is running Ubuntu 14.04), so mySQL does a daylight-saving conversion and stores the value one hour off from what it ought to be. (I guess if I was in another timezone e.g. CST then I'd have an unwanted timezone offset as well as the daylight saving hour).
To get mySQL to do The Right Thing it appears that I need to covert the UTC timestamp into system time before I insert it so that mySQL can convert it from system time to UTC time before it stores it internally. This bit of code has the desired effect:-
mysql> select timestamp("2015-05-06 12:34:56")+CURRENT_TIMESTAMP-UTC_TIMESTAMP;
+------------------------------------------------------------------+
| timestamp("2015-05-06 12:34:56")+CURRENT_TIMESTAMP-UTC_TIMESTAMP |
+------------------------------------------------------------------+
| 20150506133456.000000 |
+------------------------------------------------------------------+
I'm going to run with this for now, but it seems like a bit of a palaver, so is there a better way?
[edit] Another round of RTFM'ing gave me this idea...
mysql> select CONVERT_TZ("2015-05-06 12:34:56", "+00:00", "SYSTEM");
+-------------------------------------------------------+
| CONVERT_TZ("2015-05-06 12:34:56", "+00:00", "SYSTEM") |
+-------------------------------------------------------+
| 2015-05-06 13:34:56 |
+-------------------------------------------------------+
That looks a lot cleaner. Any better ideas?
You can probably use the CONVERT_TZ function which uses the specified timezone to parse the date instead of system timezone:
SELECT CONVERT_TZ('2015-05-06 12:34:56','+00:00','SYSTEM') AS `Local Time`,
UNIX_TIMESTAMP(CONVERT_TZ('2015-05-06 12:34:56', '+00:00', 'SYSTEM')) AS `UNIX Timestamp`;
+---------------------+----------------+
| Local Time | UNIX Timestamp |
+---------------------+----------------+
| 2015-05-06 17:34:56 | 1430915696 |
+---------------------+----------------+
The local time value will differ depending on which system the query is run. However, the UNIX timestamp value will be same.
You can then insert the local time value in the timestamp column; MySQL will store the value after conversion.

Mysql Unix_timestamp function

In oracle converting this date 2012-07-03 11:38:41 to unix_timestamp we get
select (to_date('2012-07-03 11:38:41','YYYY-MM-DD HH24:MI:SS') -
to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS'))*86400 as unix_timestamp
from dual
SQL> /
UNIX_TIMESTAMP
--------------
1341315521
But when i try the same on mysql server
select UNIX_TIMESTAMP('2012-07-03 11:38:41')
1341311921
Server Settings are something like this
**mysql**> select current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2012-07-26 15:27:31 |
+---------------------+
1 row in set (0.00 sec)
**Unix** >Thu Jul 26 15:27:56 BST 2012
**oracle**>select current_timestamp from dual;
CURRENT_TIMESTAMP
------------------------------------
26-JUL-12 15.27.16.967258 +01:00
How do i make sure oracle and mysql give me the same values ?
The difference between the two values you show is 3600 seconds, i.e. 1 hour.
Most likely, the two servers' timezone settings vary by one hour.
See https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html for time zone info in the mySQL server. Here is some in-depth info for Oracle's handling of time zones.
I used this trick
unix_timestamp(cast(sys_extract_utc(systimestamp) as date
And then i also wrote a function called unix_timestamp
create or replace
function unix_timestamp(in_date date)
return number DETERMINISTIC PARALLEL_ENABLE AS
l_date date;
begin
return trunc((in_date -to_date ( '01-jan-1970', 'dd-mon-yyyy' ))*86400);
end;
/