123

How can I get the most accurate time stamp in Node.js?

ps My version of Node.js is 0.8.X and the node-microtime extension doesn't work for me (crash on install)

Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
NiLL
  • 13,645
  • 14
  • 46
  • 59

15 Answers15

203

In Node.js, "high resolution time" is made available via process.hrtime. It returns a array with first element the time in seconds, and second element the remaining nanoseconds.

To get current time in microseconds, do the following:

var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)

(Thanks to itaifrenkel for pointing out an error in the conversion above.)

In modern browsers, time with microsecond precision is available as performance.now. See https://developer.mozilla.org/en-US/docs/Web/API/Performance/now for documentation.

I've made an implementation of this function for Node.js, based on process.hrtime, which is relatively difficult to use if your solely want to compute time differential between two points in a program. See http://npmjs.org/package/performance-now . Per the spec, this function reports time in milliseconds, but it's a float with sub-millisecond precision.

In Version 2.0 of this module, the reported milliseconds are relative to when the node process was started (Date.now() - (process.uptime() * 1000)). You need to add that to the result if you want a timestamp similar to Date.now(). Also note that you should bever recompute Date.now() - (process.uptime() * 1000). Both Date.now and process.uptime are highly unreliable for precise measurements.

To get current time in microseconds, you can use something like this.

var loadTimeInMS = Date.now()
var performanceNow = require("performance-now")
console.log((loadTimeInMS + performanceNow()) * 1000)

See also: Does JavaScript provide a high resolution timer?

Community
  • 1
  • 1
Myrne Stol
  • 11,222
  • 4
  • 40
  • 48
  • 37
    It should be noted that to do a benchmark you can pass the result of a previous call to `process.hrtime()` to get a diff. e.g. `var startTime = process.hrtime();` and then `var diff = process.hrtime(startTime);`. – Justin Warkentin Feb 28 '14 at 16:58
  • 5
    Please check the time units when converting seconds to microseconds. console.log(hrTime[0] * 1000000 + hrTime[1] / 1000) – itaifrenkel May 05 '14 at 16:05
  • Thanks for pointing out this error, itaifrenkel! I've corrected the conversion code. – Myrne Stol May 05 '14 at 16:39
  • 2
    Shouldn't `require("performance.now")` be `require("performance-now")`? – UpTheCreek Sep 04 '14 at 10:33
  • 8
    `process.hrtime()` does not return the current time. –  Jul 28 '17 at 07:43
  • 1
    Node also has a built-in implementation of the `performance` api in the [`perf_hooks`](https://nodejs.org/api/perf_hooks.html) module. – janispritzkau May 08 '20 at 16:32
131

node v10 and later: you should be using process.hrtime.bigint(), which yields a single BigInt number rather than an array. process.hrtime() has been marked "legacy"

Older than node v10: As stated by vaughan, process.hrtime() is available within Node.js - its resolution are nanoseconds and therefore its much higher. This function returns an array [seconds, nanoseconds] containing the current real-time high-resolution value, but note that it is not tied to any specific clock, meaning the difference in two successive values tells you how much time passed, but individual values tell you nothing meaningful.

Other JS environments: new Date().getTime()? This gives you a timestamp in milliseconds. Update:

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 1
    @Esailija Anything smaller than milliseconds becomes notoriously less reliable. – TheZ Jul 30 '12 at 16:36
  • I need more accurate time then simple timestamp – NiLL Jul 30 '12 at 16:37
  • what do you mean? More accurate than a timestamp? (in milliseconds) – Dominic Barnes Jul 30 '12 at 17:15
  • 5
    I have to agree. This answer is completely wrong. See below answer by @Meryn Stol for correct answer. – Justin Warkentin Feb 28 '14 at 16:40
  • 20
    process.hrtime() These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift. The primary use is for measuring performance between intervals. So it doesn t give the current time – Alex Nov 26 '16 at 18:52
  • 16
    All of the top answers are wrong. `process.hrtime()` does not return the current time. –  Jul 28 '17 at 07:43
  • It is `process.hrtime.bigint()` in node v18 see docs here https://nodejs.org/dist/latest-v18.x/docs/api/process.html#processhrtimebigint – Luckylooke Sep 01 '22 at 05:46
25
now('milli'); //  120335360.999686
now('micro') ; // 120335360966.583
now('nano') ; //  120335360904333

Known that now is :

const now = (unit) => {
  
  const hrTime = process.hrtime();
  
  switch (unit) {
    
    case 'milli':
      return hrTime[0] * 1000 + hrTime[1] / 1000000;
      
    case 'micro':
      return hrTime[0] * 1000000 + hrTime[1] / 1000;
      
    case 'nano':
    default:
      return hrTime[0] * 1000000000 + hrTime[1];
  }
  
};
PRS
  • 672
  • 8
  • 18
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 27
    `process.hrtime()` does not return the current time. –  Jul 28 '17 at 07:43
  • which Os you have ? – Abdennour TOUMI Jul 28 '17 at 10:42
  • Warning: "micro" and "nano" both look like they will overflow Number. For those to work, you may have to convert them to BigInt first. – DoomGoober Sep 19 '20 at 03:48
  • @user2609094 is right. From the [docs](https://nodejs.org/api/process.html#processhrtimetime): "These times are relative to an arbitrary time in the past [...]. The primary use is for measuring performance between intervals" (i.e. _not_ current time). See [this answer](https://stackoverflow.com/a/56598077) too. – Alex Apr 29 '23 at 17:23
20

The BigInt data type is supported since Node.js 10.7.0. (see also the blog post announcement). For these supported versions of Node.js, the process.hrtime([time]) method is now regarded as 'legacy', replaced by the process.hrtime.bigint() method.

The bigint version of the process.hrtime() method returning the current high-resolution real time in a bigint.

const start = process.hrtime.bigint();
// 191051479007711n

setTimeout(() => {
  const end = process.hrtime.bigint();
  // 191052633396993n

  console.log(`Benchmark took ${end - start} nanoseconds`);
  // Benchmark took 1154389282 nanoseconds
}, 1000);

tl;dr

  • Node.js 10.7.0+ - Use process.hrtime.bigint()
  • Otherwise - Use process.hrtime()
d4nyll
  • 11,811
  • 6
  • 54
  • 68
  • i found process.hrtime.bigint() not returning the correct time, looks like is not a unix and the year is 2043 e.g 2325734153489354 – Matan Tubul Mar 21 '23 at 09:53
  • @MatanTubul Straight from the documentation (https://nodejs.org/api/process.html#processhrtimetime) "These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift. The primary use is for measuring performance between intervals" – d4nyll Mar 21 '23 at 11:02
10

There's also https://github.com/wadey/node-microtime:

> var microtime = require('microtime')
> microtime.now()
1297448895297028
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • OP stated that they tried this package and could not get it to install. – Cameron Tacklind Sep 14 '19 at 23:30
  • @CameronTacklind Ah they did indeed - they called it an 'extension'; which made me miss this. Since a lot of people come to this article via the question - which is how to do a microtime on node - the answer is still useful. – mikemaccana Sep 23 '19 at 09:08
9

You can also use performance API that works both in NodeJS and Browser:

var start = performance.timing ?
    performance.timing.navigationStart :
    performance.timeOrigin;

var time = (performance.now() + start) * 1000;

The Performance API stores value in floating-point number and the fraction is microseconds.

EDIT: with modern JavaScript you can use this code:

const start = performance?.timing ?? performance.timeOrigin;
const time = (performance.now() + start) * 1000;
jcubic
  • 61,973
  • 54
  • 229
  • 402
3

Node.js nanotimer

I wrote a wrapper library/object for node.js on top of the process.hrtime function call. It has useful functions, like timing synchronous and asynchronous tasks, specified in seconds, milliseconds, micro, or even nano, and follows the syntax of the built in javascript timer so as to be familiar.

Timer objects are also discrete, so you can have as many as you'd like, each with their own setTimeout or setInterval process running.

It's called nanotimer. Check it out!

krb686
  • 1,726
  • 9
  • 26
  • 46
1

To work with more precision than Date.now(), but with milliseconds in float precision:

function getTimeMSFloat() {
    var hrtime = process.hrtime();
    return ( hrtime[0] * 1000000 + hrtime[1] / 1000 ) / 1000;
}
Wing
  • 8,438
  • 4
  • 37
  • 46
Ross
  • 14,266
  • 12
  • 60
  • 91
  • 3
    process.hrtime() does not return the current time – Marc J. Schmidt May 21 '18 at 12:46
  • You're right. From the docs: "These times are relative to an arbitrary time in the past, and not related to the time of day and therefore not subject to clock drift. The primary use is for measuring performance between intervals" https://nodejs.org/api/process.html#process_process_hrtime_time – Ross May 21 '18 at 16:31
1

Edit:

Use jcubic's or Alexandr's answers below : https://stackoverflow.com/a/69870775/2550964 https://stackoverflow.com/a/72741299/2550964


I'm not so proud about this solution but you can have timestamp in microsecond or nanosecond in this way:

const microsecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3,6))
const nanosecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3))

// usage
microsecond() // return 1586878008997591
nanosecond()  // return 1586878009000645600

// Benchmark with 100 000 iterations
// Date.now: 7.758ms
// microsecond: 33.382ms
// nanosecond: 31.252ms

Know that:

  • This solution works exclusively with node.js,
  • This is about 3 to 10 times slower than Date.now()
  • Weirdly, it seems very accurate, hrTime seems to follow exactly js timestamp ticks.
  • You can replace Date.now() by Number(new Date()) to get timestamp in milliseconds

Edit:

Here a solution to have microsecond with comma, however, the number version will be rounded natively by javascript. So if you want the same format every time, you should use the String version of it.

const microsecondWithCommaString = () => (Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))
const microsecondWithComma = () => Number(Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))

microsecondWithCommaString() // return "1586883629984.8997"
microsecondWithComma() // return 1586883629985.966
pirs
  • 2,410
  • 2
  • 18
  • 25
  • This will not work. Imagine hrtime is currently at 999.999 microseconds. You call Date.now(), getting 1234567890. Now you call hrtime, but it has rolled over to 0, so now instead of getting a time that is almost 1234567891.001, you instead get 1234567890.001. You have time traveled backward a millisecond. By itself you might not care, but you WILL care if you're trying to time a task that takes 100us, because occasionally you will get -900us, which not only breaks your stats substantially, your code might not handle negative times properly. – Jason Jul 21 '22 at 22:18
  • @Jason The rollback is possible theorically. But as you are under the microsecond to get time + process.hrtime, it seems to be quite accurate on this side, sure its not 100%, but enough to get sth you can work with, I did so, no negative stuffs or what, it was ok and I wrote "I'm not so proud" of this solution but it is an interesting one. Meantime, no one knows exactly what happens behind the scene, a cpp node addon could fix this point, if you dig into it, give us a feedback. – pirs Aug 02 '22 at 11:45
  • It's not theoretical. I've fixed this exact bug in three different code bases. All it takes is for you to start a task around the 'top' of the second/minute/millisecond and for rollover to happen. It's particularly prone to happening when you're taking measurements that are closer to the time resolution of a small unit of work, like measuring nanoseconds on an app that can take a microsecond to do object allocation. And as I said, it's not academic when your application crashes or gets stuck in a loop because before > after due to a timer bug. – Jason Aug 05 '22 at 22:12
  • And I will add, every time I had to fix it because the perpetrator dismissed it claiming "that could never happen" after it had already happened - twice. When we do billions of calculations per second "almost never" has to be over a quintillion calculations away. Check your math. – Jason Aug 05 '22 at 22:14
  • @Jason if you want a more precise value, do a simple cpp nodejs addon to bring back time directly from V8 ... And voila. (Note: I wont do it for you sry) – pirs Aug 11 '22 at 01:50
  • It would be simpler if you used both pieces of data from the hrtime api instead of trying to split a timestamp across two incompatible and non-atomic calls. hrtime has different guarantees around NTP than hrtime. You can't compare or merge values from the two on an app that has been running for longer than 30 seconds. – Jason Aug 15 '22 at 23:20
1

The only way nowdays is call some 3rd party.

  1. A lib with compiled function written on C (does't matter language, the point is OS syscall). Write your own or use for example https://www.npmjs.com/package/microtime (src https://github.com/wadey/node-microtime/blob/master/src/microtime.cc)
  2. Spawn a process with date +%s%N, works on Linux out of box. Possible by using require('child_process').exec. I have no idea how accurate time would be because of performance of this solution

Note: process.hrtime is not about current time,

These times are relative to an arbitrary time in the past, and not related to the time of day. [https://www.geeksforgeeks.org/node-js-process-hrtime-method/]

0

A rewrite to help quick understanding:

const hrtime = process.hrtime();     // [0] is seconds, [1] is nanoseconds

let nanoSeconds = (hrtime[0] * 1e9) + hrtime[1];    // 1 second is 1e9 nano seconds
console.log('nanoSeconds:  ' + nanoSeconds);
//nanoSeconds:  97760957504895

let microSeconds = parseInt(((hrtime[0] * 1e6) + (hrtime[1]) * 1e-3));
console.log('microSeconds: ' + microSeconds);
//microSeconds: 97760957504

let milliSeconds = parseInt(((hrtime[0] * 1e3) + (hrtime[1]) * 1e-6));
console.log('milliSeconds: ' + milliSeconds);
//milliSeconds: 97760957

Source: https://nodejs.org/api/process.html#process_process_hrtime_time

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
0

Get hrtime as single number in one line:

const begin = process.hrtime();
// ... Do the thing you want to measure
const nanoSeconds = process.hrtime(begin).reduce((sec, nano) => sec * 1e9 + nano)

Array.reduce, when given a single argument, will use the array's first element as the initial accumulator value. One could use 0 as the initial value and this would work as well, but why do the extra * 0.

Cameron Tacklind
  • 5,764
  • 1
  • 36
  • 45
-1

there are npm packages that bind to the system gettimeofday() function, which returns a microsecond precision timestamp on Linux. Search for npm gettimeofday. Calling C is faster than process.hrtime()

Andras
  • 2,995
  • 11
  • 17
-1

process.hrtime() not give current ts.

This should work.

 const loadNs       = process.hrtime(),
        loadMs       = new Date().getTime(),
        diffNs       = process.hrtime(loadNs),
        microSeconds = (loadMs * 1e6) + (diffNs[0] * 1e9) + diffNs[1]

  console.log(microSeconds / 1e3)
-10

better?

Number(process.hrtime().join(''))
infinito84
  • 1,971
  • 17
  • 8
  • 3
    This does not work at all. DO NOT USE. Since these values are integers, the second element of the array will never have a fixed width. Leading zeros are not there for this to be joined as a string. – user.friendly Oct 19 '18 at 19:51
  • Number(process.hrtime().map((n,i) => i ? ('000000000'+n).slice(-9) : n).join('')) – Mike Jan 17 '20 at 23:51