How do I get the current Unix time in milliseconds (i.e number of milliseconds since Unix epoch January 1 1970)?

14 Answers 14

up vote 239 down vote accepted

This:

date +%s 

will return the number of seconds since the epoch.

This:

date +%s%N

returns the seconds and current nanoseconds.

So:

date +%s%N | cut -b1-13

will give you the number of milliseconds since the epoch - current seconds plus the left three of the nanoseconds.


and from MikeyB - echo $(($(date +%s%N)/1000000)) (dividing by 1000 only brings to microseconds)

  • 32
    I wonder how many ms the cut adds :-) – Kyle Brandt Jun 14 '10 at 16:23
  • 13
    Or if you want to do it all in the shell, avoiding the expensive overhead of an additional process (actually, we're avoiding the problem when the number of digits in %+s+N changes): echo $(($(date +%s%N)/1000)) – MikeyB Jun 14 '10 at 16:38
  • 5
    It's the principle of the matter... avoid magic numbers and code what you actually mean. – MikeyB Jun 14 '10 at 18:02
  • 21
    I think it's worth noting that the man asked for Unix, not Linux, and the current top answer (date +%s%N) doesn't work on my AIX system. – Pete Oct 25 '11 at 16:52
  • 9
    @Pete +1 Same for OS X, and FreeBSD – ocodo May 19 '12 at 0:28

You may simply use %3N to truncate the nanoseconds to the 3 most significant digits (which then are milliseconds):

$ date +%s%3N
1397392146866

This works e.g. on my kubuntu 12.04.

But be aware, that %N may not be implemented depending on your target system. E.g. tested on an embedded system (buildroot rootfs, compiled using a non-HF arm cross toolchain) there was no %N:

$ date +%s%3N
1397392146%3N

(And also my (non rooted) Android tablet has no %N).

  • 1
    @warren: I saw that you edited and changed the 1397392146%3N to 1397392146%N, but the output of 1397392146%3N is that what I'd really seen on the busybox console of my android tablet. Could you explain your edit? – Joe Jun 25 '15 at 8:00
  • warren's comment from the history is "changed from 3 to 6, as 3 only takes you to microseconds". His edit seems entirely spurious; you should roll it back. – bukzor Dec 25 '15 at 0:27
  • This is a feature of GNU coreutils specifically. Ultimately, this is implemented in gnulib here: github.com/gagern/gnulib/blob/…. – telotortium Nov 6 '17 at 20:23
  • probably a dot in there makes sense. date +%s.%3N prints 1510718281.134. – darksky Nov 15 '17 at 4:01

date +%N doesn't work on OS X, but you could use one of

  • ruby: ruby -e 'puts Time.now.to_f'
  • python: python -c 'import time; print time.time()'
  • node.js: node -e 'console.log(Date.now())'
  • PHP: php -r 'echo microtime(TRUE);'
  • the internets: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N
  • or for milliseconds rounded to nearest second date +%s000
  • 1
    for completeness... node -e 'console.log(Date.now())' – slf Oct 10 '13 at 18:06
  • 1
    Using PHP: php -r 'echo microtime(TRUE);' – TachyonVortex Nov 22 '13 at 16:41
  • 7
    Sure, you just have to wait for those interpreters to warm up. This works, too: wget -qO- http://www.timeapi.org/utc/now?\\s.\\N – Camilo Martin Jun 23 '14 at 13:26
  • 6
    Or, if you don't actually need the milliseconds but just the correct format: date +%s000 – Lenar Hoyt Apr 22 '15 at 16:15
  • 1
    apple.stackexchange.com/questions/135742/… has instructions for doing this in OSX via Brew's coreutils – sameers Nov 17 '17 at 19:53

Just throwing this out there, but I think the correct formula with the division would be:

echo $(($(date +%s%N)/1000000))

My solution is not the best but worked for me.

date +%s000

I just needed to convert a date like 2012-05-05 to milliseconds.

  • Amazing hack, lol :) – k06a Mar 24 '16 at 11:16
  • 4
    You must be someone among my coworkers. – Nakilon May 15 '17 at 15:52

For the people that suggest running external programs to get the milliseconds... at that rate, you might as well do this:

wget -qO- http://www.timeapi.org/utc/now?\\s.\\N

Point being: before picking any answer from here, please keep in mind that not all programs will run under one whole second. Measure!

  • You're not asking the local system for the time. Which I guess is implied in the question. You also depend on a network connection. – orkoden Jan 29 '15 at 11:27
  • 2
    @orkoden The question explicitly asks for "number of milliseconds since Unix epoch January 1 1970". Also, I'm more of pointing out how you shouldn't ever fire up whole of Ruby or Python (or wget) just to get the time - either this is done through a fast channel or milliseconds don't matter. – Camilo Martin Jan 29 '15 at 11:57
  • 2
    Yes, I understood that you were giving a worse solution to highlight the bad solutions' flaws. I tried several solutions and measured the time. lpaste.net/119499 The results are kind of interesting. Even on a very fast i7 machine date takes 3 ms to run. – orkoden Jan 29 '15 at 12:38
  • @orkoden Nice testing! What OS? This might have to do with process spawning overhead. – Camilo Martin Jan 30 '15 at 13:18
  • 1
    @Nakilon and this is why one shouldn't rely on curl-able conveniences like those for anything production. – Camilo Martin May 17 '17 at 22:24

this solution works on macOS.

if you consider using a bash script and have python available, you could use this code:

#!/bin/bash

python -c 'from time import time; print int(round(time() * 1000))'
  • why the down vote? – Frank Thonig Feb 5 at 14:35
  • Doesn't seem particularly justified. The hint on the down arrow says "This answer is not useful", but IMO it's useful. Maybe they wanted you to make it a Python script instead. That would be simpler and also work fine as a bash command. – Andrew Schulman Feb 5 at 14:47
  • Don't worry too much about downvotes (it was not mine) ... especially if they are anonymous (from which one cannot learn what appears to be wrong, right?). Just to hlep you process it ... here goes another +1 ... guess what: YOU are also allowed to "vote" now, right? – Pierre.Vriens Feb 5 at 14:51
  • The downvote appears to have been caused by an issue with the system. It has since been removed, again by the system. – Michael Hampton Feb 5 at 20:52

If you are looking for a way to display the length of time your script ran, the following will provide a (not completely accurate) result:

As near the beginning of your script as you can, enter the following

basetime=$(date +%s%N)

This'll give you a starting value of something like 1361802943996000000

At the end of your script, use the following

echo "runtime: $(echo "scale=3;($(date +%s%N) - ${basetime})/(1*10^09)" | bc) seconds"

which will display something like

runtime: 12.383 seconds

Notes:

(1*10^09) can be replaced with 1000000000 if you wish

"scale=3" is a rather rare setting that coerces bc to do what you want. There are lots more!

I only tested this on Win7/MinGW... I don't have a proper *nix box to hand.

  • 3
    or you could just use time <script> – warren Apr 25 '14 at 13:32

Here is how to get time in milliseconds without performing division. Maybe it's faster...

# test=`date +%s%N`
# testnum=${#test}
# echo ${test:0:$testnum-6}
1297327781715

Update: Another alternative in pure bash that works only with bash 4.2+ is same as above but use printf to get the date. It will definitely be faster because no processes are forked off the main one.

printf -v test '%(%s%N)T' -1
testnum=${#test}
echo ${test:0:$testnum-6}

Another catch here though is that your strftime implementation should support %s and %N which is NOT the case on my test machine. See man strftime for supported options. Also see man bash to see printf syntax. -1 and -2 are special values for time.

  • Seems like my strftime(3) doesn't support %N so no way for printf to print nanoseconds. I am using Ubuntu 14.04. – haridsv Mar 21 '17 at 7:35
  • @haridsv, yeah, it's not in glibc. date seems like the more reliable option. – akostadinov Mar 22 '17 at 10:26

The most accurate timestamp we can get (at least for Mac OS X) is probably this:

python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'

1490665305.021699

But we need to keep in mind that it takes around 30 milliseconds to run. We can cut it to the scale of 2 digits fraction, and at the very beginning compute the average overhead of reading the time, and then remove it off the measurement. Here is an example:

function getTimestamp {
  echo `python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")' | cut -b1-13` 
}
function getDiff {
  echo "$2-$1-$MeasuringCost" | bc
}
prev_a=`getTimestamp`
acc=0
ITERATIONS=30
for i in `seq 1 $ITERATIONS`;do 
  #echo -n $i 
  a=`getTimestamp`
  #echo -n "   $a"
  b=`echo "$a-$prev_a" | bc`
  prev_a=$a
  #echo "  diff=$b"
  acc=`echo "$acc+$b" | bc`
done
MeasuringCost=`echo "scale=2; $acc/$ITERATIONS" | bc`
echo "average: $MeasuringCost sec"
t1=`getTimestamp`
sleep 2
t2=`getTimestamp`
echo "measured seconds: `getDiff $t1 $t2`"

You can uncomment the echo commands to see better how it works.

The results for this script are usually one of these 3 results:

measured seconds: 1.99
measured seconds: 2.00
measured seconds: 2.01

Using date and expr can get you there i.e.

X=$(expr \`date +%H\` \\* 3600 + \`date +%M\` \\* 60 + \`date +%S\`)
echo $X

Just expand on it to do whatever you want

I realise this does not give milliseconds since epoch, but it might still be useful as an answer for some of the cases, it all depends on what you need it for really, multiply by 1000 if you need a millisecond number :D

Simplest way would be to make a small executable (from C f.ex.) and make it available to the script.

  • There's a potential problem running date multiple times. In some cases, the date or time may change between runs as your command is written. It's better to run date once and parse the parts out and do your calculation. One of several ways to do that would be t=$(date +%H%M%S); (( x = ${t:0:2} * 3600 + ${t:2:2} * 60 + ${t:4:2} )); echo "$x". This uses Bash syntax since the question is tagged bash. As you allude, your answer (and my variation) only gives seconds for the current day so far and not since the Epoch and not in millis. – Dennis Williamson Nov 4 '15 at 0:17

(repeat from above) date +%N doesn't work on OS X, but you could use also :

Perl (requires Time::Format module). Perhaps not the best CPAN module to use but gets the job done. Time::Format is generally made available with distributions.

perl -w -e'use Time::Format; printf STDOUT ("%s.%s\n", time, $time{"mmm"})'
  • The OP specifically asked for ways to do it using bash. How is this bash, save as a method to launch something else? – MadHatter Mar 15 '16 at 10:48
  • I use this in my bash shell scripts ... under OSX. So, date can't be used and there is no bash-only commands that answer the need. – TVNshack Mar 15 '16 at 13:37
  • Fair enough. If you were to clarify why OSX's date can't be used as part of your answer, I'd remove my downvote. – MadHatter Mar 15 '16 at 13:43
  • This was explained a few answers above. I couldn't add as comment that command which was missing with the proposed list. So I've added it here. – TVNshack Mar 15 '16 at 14:56
  • Fair enough, I accept this is a useful addition to the canon. +1 from me! – MadHatter Mar 15 '16 at 15:32

Putting all together previous responses, when in OSX

ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G31+

you can do like

microtime() {
    python -c 'import time; print time.time()'
}
compute() {
    local START=$(microtime)
    #$1 is command $2 are args
    local END=$(microtime)
    DIFF=$(echo "$END - $START" | bc)
    echo "$1\t$2\t$DIFF"
}

If you want a simple shell elapsed computation, this is easy and portable, using the above answer:

now() {
    python -c 'import datetime; print datetime.datetime.now().strftime("%s.%f")'
}
seismo:~$ x=`now`
seismo:~$ y=`now`
seismo:~$ echo "$y - $x" | bc
5.212514

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.