Date.now()

The cheapest way to ask what time it is. It is also a wall clock, which means it can jump backwards — so it is the wrong tool for measuring how long something took.

Date static methodES5 (2009)
Common call
Date.now()
Returns
milliseconds since the epoch
Replaces
new Date().getTime()
Watch out
not monotonic — use performance.now() for durations
Date.now()
→ number

Examples

1. A timestamp
typeof Date.now()
Returns
'number'
2. No object allocated
Date.now()
Returns
1773576000000, for example
3. The older idiom
new Date().getTime()
Returns
the same value, plus a Date
4. Build a Date from it
new Date(Date.now())
Returns
equivalent to new Date()
5. Elapsed, roughly
const t = Date.now(); work(); Date.now() - t
Returns
milliseconds, subject to clock changes
6. Elapsed, properly
const t = performance.now(); work(); performance.now() - t
Returns
monotonic, sub-millisecond

Pitfalls

1. It is not monotonic
It reads the system wall clock, which NTP adjusts, users change, and daylight saving shifts. A duration measured by subtracting two readings can come out negative, or absurdly large, for reasons that have nothing to do with your code.
Can go backwards
const t = Date.now();
await slow();
Date.now() - t
occasionally negative
Monotonic clock
const t = performance.now();
await slow();
performance.now() - t
always increasing
2. Millisecond resolution, and often less
The value is an integer number of milliseconds, so anything faster than that measures as zero. Browsers also deliberately coarsen the clock to mitigate timing attacks, so consecutive calls can return the same number.
Too coarse
const t = Date.now();
fastThing();
Date.now() - t
0
Finer clock
const t = performance.now();
fastThing();
performance.now() - t
0.043
3. Using it as a unique id
Two calls in the same millisecond return the same number, and on a fast machine that happens constantly. A timestamp is not an identifier — crypto.randomUUID is, and it is built in.
Collides
const id = Date.now();
duplicates within a millisecond
A real id
const id = crypto.randomUUID();
unique
4. It cannot be stubbed by assignment in strict code
Tests that need a fixed clock often reassign Date.now. It works, but it leaks between tests if not restored, and it does not affect new Date(). Fake-timer helpers replace both together, which is what you actually want.
Only half stubbed
Date.now = () => 0;
new Date().getTime()
still the real time
Fake timers
vi.useFakeTimers();
vi.setSystemTime(0);
both stubbed

When to use

Use it
  • Recording when something happened
  • Cache timestamps and expiry checks
  • Cheap age comparisons, where a second either way does not matter
  • Avoiding a Date allocation in a hot path
Reach for something else
  • Measuring elapsed time → performance.now()
  • Generating ids → crypto.randomUUID()
  • Sub-millisecond timing → performance.now()
  • Anything that must survive a clock change → a monotonic source

Notes

Complexity
O(1)
Return
A number; no object is allocated
CPython impl
V8: Builtins-date-now
Memory
No allocation — the reason to prefer it over new Date().getTime()
Thread-safe
Single-threaded

FAQ

Because the value is different every time it is called. A demo would show a number that was already stale by the time you read it, and the differential audit that checks every other demo on this site could never reproduce it. The examples above describe the shape rather than pretending to a fixed answer.

History

ES1
new Date().getTime() was the only way to read the current time.
ES5
Date.now added, avoiding the throwaway allocation.