93

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?

Marsellus Wallace
  • 17,991
  • 25
  • 90
  • 154
  • FROM_UNIXTIME(UNIX_TIMESTAMP(CONCAT(DATE(NOW()), ' ', CURTIME(3))); will create a timestamp with milliseconds. Adjust the parameter in curtime to alter the number of decimals. – user1119648 Aug 25 '16 at 13:18
  • @user1119648 - Which DB? Doesn't any DB with `CURTIME(3)` also support `NOW(3)`? So `CONCAT(DATE(NOW()), ' ', CURTIME(3))` could just be `NOW(3)`, at least in MySQL 5.6.4+ Also, `FROM_UNIXTIME` and `UNIX_TIMESTAMP` are inverse of each other, so `FROM_UNIXTIME( UNIX_TIMESTAMP( whatever ) )` results in `whatever`. Isn't your long expression the same as `NOW(3)`? – ToolmakerSteve Apr 13 '17 at 12:58

21 Answers21

75

For MySQL (5.6+) you can do this:

SELECT ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)

Which will return (e.g.):

1420998416685 --milliseconds
Claudio Holanda
  • 2,455
  • 4
  • 21
  • 25
  • 2
    Unreliable in a DST timezone! (Wrong for an hour every year) – Doin Nov 25 '18 at 00:39
  • @Doin that is not the case. This is GMT time, not susceptible to DST / ST anomalies. Although the time you may seen in a SELECT takes timezone into account, that is not a reflection on the value stored here. – Dennis Mar 29 '22 at 12:45
  • @Dennis, from the v8.0 manual: `CURTIME([fsp])`: Returns the current time as a value [...]. *The value is expressed in the session time zone*. And `UNIX_TIMESTAMP([date])`: If UNIX_TIMESTAMP() is called with a date argument [...]. The server interprets date *as a value in the session time zone* ... Thus if your session timezone has DST, you run into problems when the clocks roll back. – Doin Mar 30 '22 at 22:42
  • @Dennis, for open bug reports related to this and other DST issues, see: https://jira.mariadb.org/browse/MDEV-17824, https://jira.mariadb.org/browse/MDEV-22828, https://jira.mariadb.org/browse/MDEV-16422 & https://bugs.mysql.com/bug.php?id=93328, https://bugs.mysql.com/bug.php?id=95797, https://bugs.mysql.com/bug.php?id=105517, https://bugs.mysql.com/bug.php?id=105515, https://bugs.mysql.com/bug.php?id=80863, https://bugs.mysql.com/bug.php?id=64058 (It's a known bug that DST date handling is broken, but apparently neither MySQL nor MariaDB thinks it's a high priority to fix). – Doin Mar 30 '22 at 23:19
  • Interesting, @Doin but I must agree with MySQL on at least bugs.mysql.com/bug.php?id=93328. (And that's as far as I looked) It's not "wrong for an hour every year." While MET is not (or is no longer?) a valid TIME_ZONE, I do see that the concern in this bug is about the fact that 2AM and 3AM on a particular day both return the same value, and that if 2AM is stored, 3AM will be returned. This doesn't sound like an issue; it sounds like someone doesn't understand that there is no 2AM when the clocks roll forward. I'm not inclined to look further. – Dennis Mar 31 '22 at 15:53
  • @Dennis, it's not the hour the clocks roll *forward* that's the problem. It's when they roll *back*, and you get two consecutive hours that have the same local time. This means that any conversion from GMT -> local DST timezone -> GMT is actually lossy, in that times in one of those doubled hours will actually get re-mapped into the other one. And this answer involves just such a conversion. So as I said, if your session is in a DST timezone, the result will be wrong by an hour, 1 hour every year. – Doin Apr 01 '22 at 16:30
  • Yeah, I can see that. The suggestion of having a timezone parameter seems like a good solution to that problem where applicable. Some people run their systems in strictly GMT for that exact reason. I don't, but i do run specific processes in GMT, specifically my weather history gathering stuff. – Dennis Apr 03 '22 at 03:19
49

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() ) );
laurent
  • 88,262
  • 77
  • 290
  • 428
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • 35
    Isn't this accurate to the second? – Matt Esch Mar 08 '12 at 20:25
  • 1
    This is to the second. I Mis-read the question I think. I don't think MySQL returns milliseconds, but it should be able to handle them if you provide them: http://stackoverflow.com/questions/2572209/why-doesnt-mysql-support-millisecond-microsecond-precision – Billy Moon Mar 08 '12 at 20:34
  • Tested in postgreSQL, works but it returns a rounded value in seconds instead of a millisecond accurate value as bigint. See my answer for the solution in postgreSQL : http://stackoverflow.com/a/28760763/3197383 – Rémi Becheras Feb 27 '15 at 08:48
37

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

jbaylina
  • 4,408
  • 1
  • 30
  • 39
  • 5
    At first I laughed, but it's the only way I've found so far to get the exact time in MySQL 5.5... so thats the solution :) Cheers. – Elliot Chance Oct 29 '14 at 02:53
  • 1
    Wow - this is great! I hope they never **fix** this behaviour. – Billy Moon Dec 01 '15 at 21:32
  • if you need just the MICROSECONDS, then you can use: `SELECT SUBSTR( CONV( CONCAT( SUBSTR(uid,16,3), SUBSTR(uid,10,4), SUBSTR(uid,1,8)), 16, 10) DIV 10, -6) FROM (SELECT UUID() AS uid) AS alias;` – lsblsb Nov 03 '16 at 12:08
32

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
Igor
  • 608
  • 6
  • 11
17

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

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
Ahmed
  • 237
  • 2
  • 5
  • 4
    Note: This was also available in Mysql 5.6.4: https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html Also, `current_timestamp` is a synonym for `now`, so `now(6)` is a shorter way to get that value. – ToolmakerSteve Apr 13 '17 at 12:21
  • 1
    This does not actually work in v 5.7.26. It will run but return something like ''2019-06-24 12:05:50.931222" – thelastshadow Jun 24 '19 at 11:06
17

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 ;)

Arzet Ro
  • 487
  • 1
  • 5
  • 12
CompEng88
  • 1,336
  • 14
  • 25
7

Use:

Select curtime(4);

This will give you milliseconds.

Satpal
  • 132,252
  • 13
  • 159
  • 168
TanuAD
  • 656
  • 6
  • 12
6

Easiest way I found to receive current time in milliseconds in MySql:

SELECT (UNIX_TIMESTAMP(NOW(3)) * 1000)

Since MySql 5.6.

Yuval
  • 371
  • 4
  • 13
  • 1
    Anyone who downvoted, what's wrong with this answer? It works as far as I can tell, just be aware of the fact that it returns a decimal number ending with `.000` instead of an integer. – BenMorel Dec 19 '14 at 14:42
  • Gives incorrect results during the end of daylight savings, if in a DST timezone! – Doin Nov 24 '18 at 22:56
6

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.

Falco
  • 162
  • 8
  • Thanks Falco, sorry I wasn't clear but I actually needed the current timestamp in milliseconds.. See example – Marsellus Wallace Mar 09 '12 at 14:59
  • Your solution returns the number of milliseconds from the start of the day, not from 1970/01/17. See my answer for the solution in postgreSQL : http://stackoverflow.com/a/28760763/3197383 – Rémi Becheras Feb 27 '15 at 08:50
4

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).

Walter Mundt
  • 24,753
  • 5
  • 53
  • 61
  • 1
    `UNIX_TIMESTAMP(NOW())` will be incorrect for an hour at the end of daylight savings, if you're in a DST timezone. Just use `UNIX_TIMESTAMP()` instead and the answer works, although I'm not 100% sure what happens during leap-seconds. – Doin Nov 24 '18 at 22:59
4

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
Tobias Liefke
  • 8,637
  • 2
  • 41
  • 58
Rémi Becheras
  • 14,902
  • 14
  • 51
  • 81
3

In PostgreSQL you can use :

SELECT extract(epoch from now());

on MySQL :

SELECT unix_timestamp(now());
aleroot
  • 71,077
  • 30
  • 176
  • 213
2

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

Peter
  • 328
  • 3
  • 7
1

In MariaDB you can use

SELECT NOW(4);

To get milisecs. See here, too.

Community
  • 1
  • 1
Benvorth
  • 7,416
  • 8
  • 49
  • 70
1

In PostgreSQL we use this approach:

SELECT round(EXTRACT (EPOCH FROM now())::float*1000)
Chebevara
  • 184
  • 2
  • 7
1

For mysql:

SELECT (UNIX_TIMESTAMP() * 1000) AS unix_now_in_microseconds; --- 1600698677000
аlex
  • 5,426
  • 1
  • 29
  • 38
0

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)
Yaniv
  • 562
  • 1
  • 6
  • 18
  • 1
    In a daylight-savings timezone, your first example will be wrong (by an hour) one hour out of every year. Better to use `UNIX_TIMESTAMP()*1000+FLOOR(MICROSECONDS(UTC_TIME(3))*0.001)` – Doin Nov 25 '18 at 01:31
0

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)
Bazardshoxer
  • 545
  • 1
  • 5
  • 22
0

Mysql:

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

Malvin Lok
  • 116
  • 1
  • 3
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Yunnosch Jan 11 '22 at 06:59
-1

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

silviu
  • 179
  • 3
  • 10
  • After a round of refactoring I succeed to have way better performances than the builtin UNIX_TIMESTAMP function – silviu Jul 09 '16 at 19:40
  • Given that you are linking to code you've **copyrighted**, please clarify the license terms. Ideally, by adding a license file to your github repository. See https://github.com/blog/1530-choosing-an-open-source-license – ToolmakerSteve Apr 13 '17 at 12:34
  • 1
    Does this work more like NOW() or SYSDATE(), i.e. is it fixed over the duration of a statement, or does each reference to it (say when inserting into multiple rows) use an up-to-date value? – Doin Nov 25 '18 at 00:45
  • the reference does not exist. – g4ost Sep 03 '19 at 18:50
-1

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")
Justin Levene
  • 1,630
  • 19
  • 17