- Syncing —
sync,isSynchronized - Getting the time —
now,timestamp,offset - Auto-sync —
startAutoSync,stopAutoSync - Smooth correction —
setSmoothCorrection,forceCorrection - WebSocket server —
startWebSocketServer,stopWebSocketServer - Utilities —
format,diff,log,stats - Events —
sync,error,coherenceWarning,driftWarning,correctionComplete - Full configuration
Contacts NTP servers, measures round-trip latency, and calculates the precise clock offset. Must be called at least once before using now().
// Minimal — uses default servers and config
await timeSync.sync();
// With options
await timeSync.sync({
servers: ['time.cloudflare.com', 'time.google.com'],
timeout: 5000, // ms — drop a server if it doesn't respond
coherenceValidation: true // compare servers, use median, warn on outliers
});Throws if all servers fail to respond.
Returns true if at least one successful sync has completed. Does not throw.
if (timeSync.isSynchronized()) {
console.log(timeSync.now());
}Returns the current precise time as a Date object, adjusted by the NTP offset.
const now = timeSync.now(); // Date — e.g. 2026-04-25T15:30:45.123ZReturns the current precise time as an ISO 8601 string.
timeSync.timestamp(); // "2026-04-25T15:30:45.123Z"Returns the difference between your system clock and NTP time, in ms. Positive means your system is ahead, negative means it's behind.
timeSync.offset(); // e.g. -1250 — system is 1.25s behindRe-syncs on a repeating interval. Prevents drift from accumulating over long-running processes.
| Parameter | Type | Default | Description |
|---|---|---|---|
interval |
number | 300000 |
ms between syncs |
timeSync.startAutoSync(300000); // ms — every 5 minutes
timeSync.startAutoSync(60000); // ms — every minute, for high-precision appsComputer clocks drift roughly 1–2 seconds per day. For anything running longer than a few minutes, auto-sync is worth enabling.
Stops the auto-sync timer.
timeSync.stopAutoSync();Controls how the library applies a new offset after re-syncing. Without it, a large offset is applied instantly — which can break timers and create gaps in logs.
| Option | Type | Default | Description |
|---|---|---|---|
maxCorrectionJump |
number (ms) | 1000 |
Apply instantly if the diff is under this |
correctionRate |
number (0–1) | 0.1 |
Fraction of remaining diff to apply each cycle |
maxOffsetThreshold |
number (ms) | 5000 |
Always apply instantly if diff exceeds this |
timeSync.setSmoothCorrection(true, {
maxCorrectionJump: 1000, // ms — small diffs are applied instantly
correctionRate: 0.1, // fraction per sync — fix 10% of the remainder each time
maxOffsetThreshold: 5000 // ms — very large diffs are also applied instantly
});Decision logic on re-sync:
- diff <
maxCorrectionJump→ instant correction (it's small enough) - diff >
maxOffsetThreshold→ instant correction (it's too large to wait) - Otherwise → gradual correction at
correctionRateper sync cycle
→ See smooth-correction.md for a detailed walkthrough.
Skips the gradual process and applies the full pending offset immediately.
timeSync.forceCorrection();Useful during shutdown, testing, or when you explicitly want to jump to accurate time right now.
Starts a WebSocket server that pushes the current NTP time to connected clients. Useful for syncing browser clocks.
timeSync.startWebSocketServer(8080);
// clients connect at ws://localhost:8080Client-side (browser):
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = (e) => {
const { data } = JSON.parse(e.data);
console.log(new Date(data.timestamp));
};Stops the WebSocket server and closes all connections.
timeSync.stopWebSocketServer();Formats a date into a readable string. Pass null as the first argument to format the current NTP time.
| Format value | Output example |
|---|---|
'iso' |
"2026-04-25T15:30:45.123Z" |
'locale' |
"25/04/2026, 17:30:45" (system locale) |
'utc' |
"Sat, 25 Apr 2026 15:30:45 GMT" |
'date' |
"25/04/2026" |
'time' |
"17:30:45" |
'timestamp' |
"1745598645123" (Unix ms as string) |
// Current NTP time
timeSync.format(null, 'iso')
timeSync.format(null, 'locale')
timeSync.format(null, 'locale', 'en-US') // override locale
// A specific date
timeSync.format('2026-01-01', 'iso')
timeSync.format(new Date(), 'utc')locale defaults to the system locale, or the locale set in the constructor.
Returns the absolute difference between two dates in ms. If date2 is omitted, it compares against the current NTP time.
timeSync.diff('2026-01-01', '2026-04-25') // ms between two dates
timeSync.diff('2026-01-01') // ms between that date and nowLogs a message to the console with the current NTP timestamp prepended.
timeSync.log('order dispatched');
// → [2026-04-25T15:30:45.123Z] order dispatchedReturns a snapshot of the current sync state. Useful for health checks and monitoring dashboards.
const s = timeSync.stats();| Field | Type | Description |
|---|---|---|
synchronized |
boolean | Whether sync has completed at least once |
offset |
number (ms) | Raw system clock error from NTP |
rtt |
number (ms) | Last measured network round-trip time |
correctedOffset |
number (ms) | Offset currently being applied (smooth correction) |
targetOffset |
number (ms) | Final target offset for smooth correction |
correctionInProgress |
boolean | Whether gradual correction is still running |
lastSync |
Date | When the last sync completed |
uptime |
number (ms) | Time elapsed since last sync |
config |
object | Active configuration values |
Fires after each successful sync.
timeSync.on('sync', (data) => {
// data.server — hostname that was used
// data.offset — ms — raw clock error
// data.rtt — ms — network round-trip time
console.log(`synced with ${data.server} — offset: ${data.offset}ms, rtt: ${data.rtt}ms`);
});Fires when a sync attempt fails (all servers unreachable, timeout, etc.).
timeSync.on('error', (err) => {
// err.message — what went wrong
// err.server — which server failed
console.error(`sync failed on ${err.server}: ${err.message}`);
});Fires when coherenceValidation is enabled and servers disagree by more than 100ms. The library uses the median offset and continues, but you may want to alert on this.
timeSync.on('coherenceWarning', (data) => {
// data.variance — ms — spread between server offsets
// data.servers — array of server results
console.warn(`server variance: ${data.variance}ms`);
});Fires when now() is called more than 1 hour after the last sync. Your offset may be stale.
timeSync.on('driftWarning', (data) => {
// data.elapsed — ms since last sync
const hours = (data.elapsed / 3600000).toFixed(1);
console.warn(`${hours}h since last sync — consider re-syncing`);
});Fires when smooth correction finishes (converged, timed out, or forced).
timeSync.on('correctionComplete', (data) => {
// data.finalOffset — ms — where correction landed
// data.converged — boolean — true if within 0.5ms of target
// data.forced — boolean — true if forceCorrection() was called
// data.timeout — boolean — true if correction timed out (30s max)
console.log(`correction done — final offset: ${data.finalOffset}ms`);
});All options can be passed to sync() or set in the TimeSync constructor.
const { TimeSync } = require('precise-time-ntp');
const t = new TimeSync({
// NTP servers — up to 3 are queried
servers: ['time.cloudflare.com', 'time.google.com', 'pool.ntp.org'],
timeout: 5000, // ms — per-server timeout
coherenceValidation: true, // cross-validate servers, use median
autoSync: true,
autoSyncInterval: 300000, // ms — how often to re-sync
smoothCorrection: true,
maxCorrectionJump: 1000, // ms
correctionRate: 0.1, // fraction per sync (0.1 = 10%)
maxOffsetThreshold: 5000, // ms
locale: 'fr-FR', // used by format() — defaults to system locale
});