How to get milliseconds since Unix epoch?

With the GNU or ast-open implementation of date (or busybox' if built with the FEATURE_DATE_NANO option enabled), I would use:

$ date +%s%3N

which returns milliseconds since Unix epoch.


date +%s.%N will give you, eg., 1364391019.877418748. The %N is the number of nanoseconds elapsed in the current second. Notice it is 9 digits, and by default date will pad this with zeros if it is less than 100000000. This is actually a problem if we want to do math with the number, because bash treats numbers with a leading zero as octal. This padding can be disabled by using a hyphen in the field spec, so:

echo $((`date +%s`*1000+`date +%-N`/1000000))

would naively give you milliseconds since the epoch.

However, as Stephane Chazelas points out in comment below, that's two different date calls which will yield two slightly different times. If the second has rolled over in between them, the calculation will be an entire second off. So:

echo $(($(date +'%s * 1000 + %-N / 1000000')))

Or optimized (thanks to comments below, though this should have been obvious):

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

In case anyone is using other shells than bash, ksh93 and zsh have a floating point $SECONDS variable if you do a typeset -F SECONDS which can be handy to measure time with accuracy:

$ typeset -F SECONDS=0
$ do-something
something done
$ echo "$SECONDS seconds have elapsed"
18.3994340000 seconds have elapsed

Since version 4.3.13 (2011) zsh has a $EPOCHREALTIME special floating point variable in the zsh/datetime module:

$ zmodload zsh/datetime
$ echo $EPOCHREALTIME
1364401642.2725396156
$ printf '%d\n' $((EPOCHREALTIME*1000))
1364401755993

Note that that's derived from the two integers (for seconds and nanoseconds) returned by clock_gettime(). On most systems, that's more precision than a single C double floating point number can hold, so you'll lose precision when you use it in arithmetic expressions (except for dates in the first few months of 1970).

$ t=$EPOCHREALTIME
$ echo $t $((t))
1568473231.6078064442 1568473231.6078064

To compute high precision time differences (though I doubt you'd need more than millisecond precision), you may want to use the $epochtime special array instead (which contains the seconds and nanoseconds as two separate elements).

Since version 5.7 (2018) the strftime shell builtin also supports a %N nanosecond format à la GNU date and a %. to specify the precision, so the number of milliseconds since the epoch can also be retrieved with:

zmodload zsh/datetime
strftime %s%3. $epochtime

(or stored in a variable with -s var)