
Security News
GitHub Actions Checkout Now Blocks Risky pull_request_target Checkouts
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.
@hyperfrontend/time-utils
Advanced tools
Functional time utilities for async operations, intervals, and time normalization.
Functional time utilities for async operations, intervals, and time normalization.
@hyperfrontend/time-utils provides composable, testable utilities for working with time-based operations in JavaScript. The library focuses on enhancing the control and flexibility of standard timing APIs (setTimeout, setInterval) while adding specialized utilities for async workflows and time window calculations.
Unlike the native timing APIs which offer limited lifecycle control, this library wraps them in functional interfaces that support pausing, resuming, resetting, and subscription management. All utilities return immutable objects with frozen APIs, preventing accidental mutation while maintaining predictable behavior.
setTimeout operations with tracked remaining timesleep() utility for sequential code flowsAll timing abstractions maintain internal state privately while exposing frozen API objects, following the revealing module pattern. Timer implementations track elapsed time explicitly to enable pause/resume functionality, while clock implementations manage subscriber arrays with simple filter-based unsubscription. The library avoids classes and prototypes in favor of factory functions that return object literals.
JavaScript's setTimeout and setInterval cannot be paused—once started, they either complete or get cancelled. This creates problems for features like user-initiated pauses in games, animations during background tabs, or request throttling. createTimer() tracks elapsed time internally, enabling pause/resume without restarting from the beginning or losing progress.
Example: A countdown timer in a game needs to pause when the user switches tabs. With setTimeout, you'd need to calculate remaining time manually and create a new timeout. With createTimer, just call timer.pause().
Native setInterval requires creating separate intervals for each callback that needs to run at the same frequency, leading to drift and coordination issues. createClock() lets multiple callbacks subscribe to a single interval loop, ensuring they all fire synchronously at exact intervals. Perfect for real-time dashboards, clocks, or animation frames.
Example: A dashboard with 5 widgets updating every second would require 5 separate setInterval calls, potentially drifting apart. A single clock can notify all widgets simultaneously from one interval.
Writing readable sequential code with delays requires nested callbacks or promise chains with setTimeout. sleep() provides a clean async/await compatible delay utility that works naturally with modern async functions. This is essential for testing, retry logic, rate limiting, and animation sequences.
Example: Retry logic becomes await sleep(1000); retry() instead of setTimeout(() => retry(), 1000), maintaining the sequential flow of async functions.
Real-time data aggregation often requires grouping events into time buckets (5-minute windows, hourly intervals, etc.). normalizeToBaseTimeWindow() rounds timestamps down to the nearest window boundary, simplifying time-series data grouping for metrics, logs, and analytics.
Example: Events at 10:03, 10:07, and 10:12 with a 5-minute window all normalize to 10:00, 10:05, and 10:10 respectively, creating clean bucket keys for aggregation.
Testing code with setTimeout and setInterval typically requires jest timers or sinon fakes, adding complexity. These utilities use standard timing APIs internally but expose functional interfaces that are easier to mock and test. The frozen return objects prevent accidental mutations that could cause subtle timing bugs.
npm install @hyperfrontend/time-utils
Pauseable timer:
import { createTimer } from '@hyperfrontend/time-utils'
const timer = createTimer(() => console.log('Done!'), 5000)
timer.resume() // Start the 5-second countdown
// After 3 seconds, user pauses
timer.pause() // Pauses with 2 seconds remaining
// Later, resume from where we left off
timer.resume() // Continues with remaining 2 seconds
// Or reset with a new duration
timer.reset(10000) // Restart with 10 seconds
Multi-subscriber clock:
import { createClock } from '@hyperfrontend/time-utils'
// Create a clock that ticks every second
const clock = createClock(1000)
// Multiple subscribers can listen
clock.subscribe((time) => console.log('Widget 1:', time))
clock.subscribe((time) => console.log('Widget 2:', time))
clock.start() // Both widgets update every second
// Later, stop all updates
clock.stop()
// Unsubscribe specific callbacks
clock.unsubscribe(callback)
Async delays:
import { sleep } from '@hyperfrontend/time-utils'
async function retryWithDelay(fn, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await fn()
} catch (error) {
if (i < attempts - 1) {
await sleep(1000 * Math.pow(2, i)) // Exponential backoff
}
}
}
throw new Error('All retries failed')
}
Time window normalization:
import { normalizeToBaseTimeWindow } from '@hyperfrontend/time-utils'
// Group metrics into 5-minute windows
const events = [new Date('2024-01-17T10:03:45Z'), new Date('2024-01-17T10:07:22Z'), new Date('2024-01-17T10:12:03Z')]
const buckets = new Map()
events.forEach((timestamp) => {
const bucket = normalizeToBaseTimeWindow(timestamp, 5)
const key = bucket.toISOString()
buckets.set(key, (buckets.get(key) || 0) + 1)
})
// Results:
// "2024-01-17T10:00:00Z" → 2 events
// "2024-01-17T10:10:00Z" → 1 event
Simple interval with cleanup:
import { setIntervalCallback } from '@hyperfrontend/time-utils'
// Returns a cleanup function
const cleanup = setIntervalCallback(() => {
console.log('Polling...')
}, 5000)
// Later, stop polling
cleanup()
Timing Abstractions:
createTimer(callback, delay) - Creates a pauseable, resumable timer (enhanced setTimeout)
timer.pause() - Pauses timer, preserving remaining timetimer.resume() - Resumes timer from remaining timetimer.reset(newDelay?) - Restarts timer with optional new durationcreateClock(interval?) - Creates a multi-subscriber interval loop (default: 1000ms)
clock.start() - Begins interval loopclock.stop() - Stops interval loopclock.subscribe(callback) - Adds callback to subscriber listclock.unsubscribe(callback) - Removes callback from subscribersclock.interval - Read-only interval durationUtility Functions:
sleep(milliseconds) - Returns promise that resolves after delay (async/await compatible)setIntervalCallback(callback, interval) - Simple setInterval wrapper returning cleanup functionnormalizeToBaseTimeWindow(time, baseTimeWindow) - Rounds timestamp down to nearest time window boundary (window in minutes)| Platform | Support |
|---|---|
| Browser | ✅ |
| Node.js | ✅ |
| Web Workers | ✅ |
| Deno, Bun, Cloudflare Workers | ✅ |
| Format | File | Tree-Shakeable |
|---|---|---|
| ESM | index.esm.js | ✅ |
| CJS | index.cjs.js | ❌ |
| IIFE | bundle/index.iife.min.js | ❌ |
| UMD | bundle/index.umd.min.js | ❌ |
<!-- unpkg -->
<script src="https://unpkg.com/@hyperfrontend/time-utils"></script>
<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@hyperfrontend/time-utils"></script>
<script>
const { createResumableInterval, sleep } = HyperfrontendTimeUtils
</script>
Global variable: HyperfrontendTimeUtils
None — zero external dependencies.
This library is part of the hyperfrontend monorepo.
MIT
FAQs
Functional time utilities for async operations, intervals, and time normalization.
The npm package @hyperfrontend/time-utils receives a total of 17 weekly downloads. As such, @hyperfrontend/time-utils popularity was classified as not popular.
We found that @hyperfrontend/time-utils demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.