npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@phyxiusjs/clock

v0.1.1

Published

Deterministic time control for Node.js applications

Readme

Clock

Make time explicit, testable, and observable.

Real systems deal with NTP corrections, leap seconds, DST shifts, VM migrations, system sleep, and clock drift. Your code often assumes time is a straight line. It is not.

Clock does not prevent those jumps. It makes them visible, gives you a linear timeline for measuring durations, and lets you test how your code behaves when the clock moves in surprising ways. Think of it as a seatbelt for time.

Two implementations, one interface:

  • System clock for production use, with wall time and monotonic time.
  • Controlled clock for tests, with instant jumps and simulated anomalies.

Why time can be flaky

External synchronization and adjustments

  • NTP corrections: containers inherit the host’s time, so any host NTP adjustment propagates inside.
  • Daylight Saving Time (DST): changes the local representation and can affect apps that do not stick to UTC.
  • Manual host clock changes: rare in production but possible during maintenance.
  • Cloud provider host adjustments: the underlying VM host can receive a time correction from the provider’s infrastructure.

Virtualization and orchestration factors

  • Host and guest clock desynchronization: especially if NTP is disabled or drift is significant.
  • Paused and resumed containers or nodes: clock jumps when resuming after suspension.
  • Live migration between hosts: in Kubernetes or cloud-managed environments, pods or VMs may be migrated to hosts with slightly different clocks.

System-level quirks and anomalies

  • Leap seconds: occasionally inserted or removed from UTC and can cause a repeated second or a time step if the kernel does not smear or handle it smoothly.
  • Kernel or container runtime bugs: rare, but timekeeping code can misbehave under certain workloads.

The Problem

You know that flaky test you have? The one that passes most of the time but fails “randomly”? This may be why.

// Schedule an auction to end in 60 seconds
const endAt = Date.now() + 60_000;

setTimeout(() => {
  if (Date.now() >= endAt) {
    closeAuction();
  }
}, 60_000);

This works until the clock moves.

  • Forward jump: NTP correction, leap second mishandling, VM migration. Your auction ends early.
  • Backward jump: system sleep, manual clock adjustment. Your auction ends late or never closes.

In tests, the same problem hides in plain sight:

it("should close the auction after 1 minute", async () => {
  const auction = new Auction();
  auction.start();

  await new Promise((resolve) => setTimeout(resolve, 60_000));
  expect(auction.isClosed()).toBe(true);
});

This passes until some unrelated test, slow CI run, or host-level clock adjustment shifts the wall clock in the middle of execution. The test becomes “sometimes red, sometimes green,” and you never trust it again.


Clock helps you with this

Example 1 — Measuring elapsed time without wall clock drift

const start = clock.now();
await clock.sleep(ms(500));
const end = clock.now();

const elapsed = end.monoMs - start.monoMs; // immune to NTP/DST jumps

Example 2 — Simulating an NTP correction in tests

const deadline = { wallMs: clock.now().wallMs + 5_000 };
const wait = clock.deadline(deadline);

clock.jumpWallTime(clock.now().wallMs - 10_000);
clock.advanceBy(ms(5_000));
await wait; // emits time:deadline:err

Example 3 — Deterministic intervals in tests

const ticks: number[] = [];
clock.interval(ms(100), () => ticks.push(clock.now().monoMs));
clock.advanceBy(ms(350));
// ticks: [100, 200, 300]

Example 4 — Observing missed deadlines in production

const clock = createSystemClock({ emit: console.log });
await clock.deadline({ wallMs: Date.now() + 1000 });
// See drift and event logs

Clock does NOT help you with this

Example 1 — Time zone conversions

// Not Clock's job:
new Date().toLocaleString("en-US", { timeZone: "America/New_York" });

Example 2 — Calculating calendar days between two dates

// Not Clock's job — DST-aware day math needs a date library
const days = differenceInDays(dateA, dateB);

Example 3 — Parsing or formatting dates

// Not Clock's job:
format(new Date(), "yyyy-MM-dd");

Example 4 — Retrospective math on arbitrary timestamps

// If you only have two Date objects from the past:
const delta = dateB.getTime() - dateA.getTime(); // wall time only

Why not just use Jest’s fake timers?

Jest’s fake timers replace the native timer functions with a mocked scheduler so you can skip waits. They cannot:

  • Distinguish between wall time and monotonic time.
  • Model real-world anomalies like NTP jumps, leap seconds, or DST shifts.
  • Advance one clock while keeping another steady.
  • Simulate time moving backwards.
  • Emit structured events for observability in production.

If you use only Jest’s timers, you can verify “it fires after X milliseconds” in a perfect, isolated world. The moment you need to know how your code reacts when the system clock changes mid-flight, you are out of luck.

Even if tests are all you care about, ControlledClock helps prevent flakiness by:

  • Simulating wall time jumps without affecting monotonic progression.
  • Preserving deterministic interval cadence under catch-up.
  • Allowing independent control over deadlines and elapsed time.
  • Matching production semantics exactly, so your tests are not lying to you.

What this is not

Clock is not a date manipulation library. It does not parse, format, or do arithmetic on calendar dates. It is not a time zone converter. It does not replace libraries like date-fns, Luxon, or Moment.

Clock is focused on representing “now” in two forms — wall time and monotonic time — and giving you precise control and observability over how that “now” changes in real systems and tests.

If you want to know what time it is in Tokyo next Friday, use a date library. If you want to know exactly when “now” changes and how your code behaves when it does, use Clock.


Installation

npm install @phyxius/clock

What you get

  • Time you can reason about: wall time for scheduling and monotonic time for measuring.
  • Time you can test: jump to any moment instantly, simulate anomalies, and verify behavior.
  • Time that works in production: structured events for clear observability of timer behavior and drift.

Clock does not fix time. It gives you two different references to make the use very explicit, while also enabling truly deterministic testing. Everything else builds on that foundation.