I want to do a bash script that measures the launch time of a browser for that I am using an html which gets the time-stamp on-load in milliseconds using JavaScript.
In the shell script just before i call the browser I get the time-stamp with:
date +%s
The problem is that it gets the time-stamp in seconds, and I need it in milliseconds since sometimes when ran a second time the browser starts in under a second and I need to be able to measure that time precisely using milliseconds instead of seconds.
How can I get the time-stamp in milliseconds from a bash script?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
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));
Method 3
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 '%dn' $((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)
Method 4
To avoid calculations to get the milliseconds, command line JavaScript interpreters may help:
bash-4.2$ node -e 'console.log(new Date().getTime())' # node.js 1364391220596 bash-4.2$ js60 -e 'print(new Date().getTime())' # SpiderMonkey 1364391220610 bash-4.2$ jsc -e 'print(new Date().getTime())' # WebKit 1364391220622 bash-4.2$ seed -e 'new Date().getTime()' # GNOME object bridge 1364391220669
Packages containing those interpreters on Ubuntu Eoan:
- node.js: nodejs
- SpiderMonkey: libmozjs-60-dev
- WebKit: libjavascriptcoregtk-4.0-bin
- GNOME object bridge: seed-webkit2
Method 5
In bash 5+ there is a variable with micro-second granularity: $EPOCHREALTIME.
So:
$ echo "$(( ${EPOCHREALTIME//.} / 1000 ))"
1568385422635
Prints time since epoch (1/1/70) in miliseconds.
Failing that, you must use date. Either the GNU date:
echo "$(date +'%s%3N')"
One of the alternatives listed in https://serverfault.com/a/423642/465827
Or brew install coreutils for OS X
Or, if everything else fails, compile (gcc epochInµsec.c) this c program (adjust as needed):
#include <stdio.h>
#include <sys/time.h>
int main(void)
{
struct timeval time_now;
gettimeofday(&time_now,NULL);
printf ("%ld secs, %ld usecsn",time_now.tv_sec,time_now.tv_usec);
return 0;
}
Note that calling any external program needs time to be read and loaded from disk, started, run and finally to print the output. That will take several milliseconds. That is the minimum precision that could be achieved with any external tool (including date).
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0