clock.performance.now returns incorrect value within clock.setInterval callback
See original GitHub issue- FakeTimers version : 7.1.2
- Environment : NodeJS
- Example URL : N/A; see test below
- Other libraries you are using: Jest
When passing fractional milliseconds to clock.setInterval
and clock.tick
, the return value of clock.performance.now
is sometimes incorrect when called within the callback passed to clock.setInterval
.
Here is an example test running within Jest:
import { Clock, install } from '@sinonjs/fake-timers';
let clock: Clock;
beforeAll(() => {
clock = install();
});
afterAll(() => {
clock.uninstall();
});
test('fake timers bug', () => {
const timestamps: number[] = [];
clock.setInterval(() => {
timestamps.push(clock.performance.now());
}, 16.6);
clock.tick(16.6);
clock.tick(16.6);
expect(clock.performance.now()).toBe(33.2); // Passes
expect(timestamps).toStrictEqual([16.6, 33.2]); // Fails
});
What did you expect to happen?
Each timestamp should be a multiple of 16.6.
What actually happens
The timestamp generated on the second iteration of the callback is off by 1 millisecond. The value 32.2
is returned rather than 33.2
.

Interestingly, when calling clock.performance.now
outside of the clock.setInterval
callback, the correct timestamp is returned.
How to reproduce
See test sample above.
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (4 by maintainers)
Top Results From Across the Web
How to create an accurate timer in javascript? - Stack Overflow
now (), the values returned by performance.now() always increase at a constant rate, independent of the system clock (which might be adjusted manually...
Read more >setInterval callback function unexpected halt · Issue #22149
When the project has been running for a month or so, there is no error, the project does not stop, but the callback...
Read more >setInterval() - Web APIs - MDN Web Docs
This method returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval() .
Read more >Scheduling: setTimeout and setInterval
To cancel the execution, we should call clearTimeout/clearInterval with the value returned by setTimeout/setInterval .
Read more >A tale of two clocks - web.dev
The bad side of the JavaScript clock is that it is not very precise. For starters, Date.now() returns a value in milliseconds -...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@fatso83 Thank you for the thoughtful reply! You raise a good point about writing code that does not conform to the spec. I will re-think the code I am writing, which will hopefully make the functionality easier to test. I really appreciate your time on this matter, and I’m happy to close this issue as a non-bug!
Not totally sure what to say here. Code that uses a non-integer duration is essentially “wrong” (not spec-conforming), so this is a more general question of how would you test something that is not supported😃
I think your approach of testing the timers schedule updates at an approximately correct frequency should be fine, and it’s basically what you did above. In any case, most JS runtimes do not make hard realtime guarantees, so whether your timer in practice gets called 51 times per minute or 62 times per minute is totally browser/node/runtime specific. So you are only really testing that fake-timers schedules a call every
parseInt(16.6)
millisecond. Not sure if we can do better than that.