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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts-time-utils

v4.1.0

Published

A comprehensive TypeScript utility library for time, dates, durations, and calendar operations with full tree-shaking support

Readme

ts-time-utils

A comprehensive TypeScript utility library for time, dates, durations, and calendar operations. Zero dependencies, full tree-shaking support, 430+ functions across 32 categories.

npm version License: MIT

Live Playground & Docs | GitHub

Features

  • Lightweight — Import only what you need with tree-shaking support
  • Zero dependencies — Pure TypeScript, no external packages
  • Type-safe — Full TypeScript support with IntelliSense
  • Comprehensive — 430+ functions across 32 utility categories
  • Fluent API — Chain operations with the chain() API
  • Extensible — Plugin system for custom functionality

Installation

npm install ts-time-utils

Quick Start

import { formatDuration, timeAgo, Duration } from 'ts-time-utils';

// Format milliseconds to readable duration
formatDuration(3661000); // "1 hour, 1 minute, 1 second"

// Get "time ago" strings
timeAgo(new Date(Date.now() - 3600000)); // "1 hour ago"

// Duration arithmetic
const meeting = Duration.fromMinutes(45);
const buffer = Duration.fromMinutes(15);
meeting.add(buffer).toString(); // "1h"

Tree-shaking (recommended)

import { formatDuration } from 'ts-time-utils/format';
import { differenceInUnits } from 'ts-time-utils/calculate';
import { isValidDate } from 'ts-time-utils/validate';

Utility Categories

Format

Format durations, time ago strings, and custom date formats.

import { formatDuration, timeAgo, parseDuration } from 'ts-time-utils/format';

formatDuration(65000);                    // "1 minute, 5 seconds"
formatDuration(65000, { short: true });   // "1m 5s"
timeAgo(new Date(Date.now() - 60000));    // "1 minute ago"
parseDuration('1h 30m');                  // 5400000 (ms)

Calculate

Date arithmetic, differences, and business day calculations.

import { differenceInUnits, addTime, startOf, endOf } from 'ts-time-utils/calculate';

differenceInUnits(date1, date2, 'days');  // 10
addTime(new Date(), 5, 'hours');          // 5 hours from now
startOf(new Date(), 'day');               // 00:00:00 today
endOf(new Date(), 'month');               // Last moment of month

Validate

Date validation, checks, and comparisons.

import { isValidDate, isLeapYear, isWeekend, isSameDay } from 'ts-time-utils/validate';

isValidDate(new Date('2025-13-01'));      // false
isLeapYear(2024);                         // true
isWeekend(new Date('2025-09-13'));        // true (Saturday)
isSameDay(date1, date2);                  // boolean

Duration

Immutable Duration class with arithmetic operations.

import { Duration } from 'ts-time-utils/duration';

const d1 = Duration.fromHours(2.5);
const d2 = Duration.fromString('1h 30m 45s');
const d3 = Duration.between(startDate, endDate);

d1.add(d2).toString();        // "4h 0m 45s"
d1.greaterThan(d2);           // true
d1.multiply(2).hours;         // 5

Chain API

Fluent chainable API for date operations.

import { chain } from 'ts-time-utils/chain';

chain(new Date())
  .startOf('day')
  .add(9, 'hours')
  .add(30, 'minutes')
  .toDate();  // Today at 9:30am

chain(new Date())
  .add(1, 'week')
  .startOf('week')
  .format('YYYY-MM-DD');  // Next week Monday

Timezone

Timezone conversions, DST handling, and zone comparisons.

import { formatInTimeZone, isDST, convertTimezone } from 'ts-time-utils/timezone';

formatInTimeZone(date, 'America/New_York');
isDST(new Date('2025-07-14'), 'America/New_York');  // true
convertTimezone(date, 'UTC', 'Asia/Tokyo');

Calendar

ISO weeks, quarters, holidays, and calendar grids.

import { getWeekNumber, getQuarter, getEaster, getUSHolidays } from 'ts-time-utils/calendar';

getWeekNumber(new Date('2025-09-14'));    // 37
getQuarter(new Date('2025-07-15'));       // 3
getEaster(2025);                          // Easter Sunday 2025
getUSHolidays(2025);                      // Array of US federal holidays

Date Range

Date range operations: overlap, gaps, merge, split.

import { mergeDateRanges, findGaps, dateRangeOverlap } from 'ts-time-utils/dateRange';

const ranges = [
  { start: new Date('2024-01-01'), end: new Date('2024-01-10') },
  { start: new Date('2024-01-05'), end: new Date('2024-01-15') },
];

mergeDateRanges(ranges);  // Merged into single range
findGaps(busyTimes, workday);  // Available time slots
dateRangeOverlap(range1, range2);  // true/false

Recurrence

RRULE-inspired recurring event patterns.

import { createRecurrence, recurrenceToString } from 'ts-time-utils/recurrence';

const weekly = createRecurrence({
  frequency: 'weekly',
  interval: 1,
  startDate: new Date('2025-01-01'),
  byWeekday: [1, 3, 5],  // Mon, Wed, Fri
});

weekly.getNextOccurrence(new Date());
weekly.getAllOccurrences();
recurrenceToString(weekly.rule);  // "Every week on Monday, Wednesday, Friday"

Cron

Parse and match cron expressions.

import { matchesCron, getNextCronDate, describeCron, CRON_PRESETS } from 'ts-time-utils/cron';

matchesCron('0 9 * * 1-5', date);         // true if weekday 9am
getNextCronDate('0 9 * * *');             // Next 9am
describeCron('0 9 * * 1-5');              // "At 09:00 on Monday through Friday"
CRON_PRESETS.DAILY;                       // "0 0 * * *"

Fiscal Year

Fiscal year utilities with configurable start month.

import { getFiscalYear, getFiscalQuarter, FISCAL_PRESETS } from 'ts-time-utils/fiscal';

getFiscalYear(date, FISCAL_PRESETS.UK_INDIA);     // April start
getFiscalYear(date, FISCAL_PRESETS.AUSTRALIA);   // July start
getFiscalYear(date, FISCAL_PRESETS.US_FEDERAL);  // October start
getFiscalQuarter(date, { startMonth: 4 });       // Q2 for UK fiscal

Compare & Sort

Sort, group, and analyze date arrays.

import { sortDates, closestDate, groupDatesByMonth, snapDate } from 'ts-time-utils/compare';

sortDates(dates, 'desc');
closestDate(target, candidates);
groupDatesByMonth(dates);  // Map by YYYY-MM
snapDate(date, 15, 'minutes');  // Snap to 15-min grid

Iterate

Iterate through date sequences and count dates.

import { eachDay, eachWeekday, countWeekdays, filterDays } from 'ts-time-utils/iterate';

eachDay(start, end);       // Array of each day
eachWeekday(start, end);   // Weekdays only (Mon-Fri)
countWeekdays(start, end); // Number of weekdays
filterDays(start, end, d => d.getDate() === 15);  // 15th of each month

Natural Language

Parse human-friendly date strings.

import { parseNaturalDate, extractDatesFromText } from 'ts-time-utils/naturalLanguage';

parseNaturalDate('tomorrow');
parseNaturalDate('next Friday');
parseNaturalDate('in 2 weeks');
parseNaturalDate('end of month');

extractDatesFromText('Meeting tomorrow at 3pm');
// [{ date: Date, text: 'tomorrow at 3pm', confidence: 0.9 }]

International Holidays

Public holidays for 20 countries.

import { getHolidays, isHoliday, getNextHoliday } from 'ts-time-utils/holidays';

getHolidays(2025, 'UK');      // UK bank holidays
getHolidays(2025, 'DE');      // German holidays
isHoliday(date, 'CA');        // Is Canadian holiday?
getNextHoliday(date, 'AU');   // Next Australian holiday

// Supported: UK, NL, DE, CA, AU, IT, ES, CN, IN, US,
//            JP, FR, BR, MX, KR, SG, PL, SE, BE, CH

Locale

Multi-language formatting with 40+ locales.

import { formatRelativeTime, formatDateLocale, detectLocale } from 'ts-time-utils/locale';

formatRelativeTime(pastDate, { locale: 'es' });  // "hace 2 horas"
formatRelativeTime(pastDate, { locale: 'de' });  // "vor 2 Stunden"
formatDateLocale(date, 'fr', 'long');            // "15 janvier 2024"
detectLocale();                                   // Auto-detect system locale

Working Hours

Business hours calculations with break support.

import { isWorkingTime, addWorkingDays, workingDaysBetween } from 'ts-time-utils/workingHours';

isWorkingTime(date, config);
addWorkingDays(date, 5, config);
workingDaysBetween(start, end, config);

Serialization

Safe JSON date serialization and deserialization.

import { serializeDate, parseJSONWithDates, stringifyWithDates } from 'ts-time-utils/serialize';

serializeDate(date, { format: 'iso' });    // "2025-09-14T12:30:45.123Z"
serializeDate(date, { format: 'epoch' });  // 1757853045123

const json = stringifyWithDates(data, ['createdAt']);
const parsed = parseJSONWithDates(json, ['createdAt']);

Performance

Async utilities, benchmarking, and timing.

import { sleep, benchmark, Stopwatch, debounce } from 'ts-time-utils/performance';

await sleep(1000);
await benchmark(() => heavyOperation(), 10);

const stopwatch = new Stopwatch();
stopwatch.start();
// ... operations
stopwatch.getElapsed();

const debouncedFn = debounce(fn, 300);

Age

Age calculations and birthday utilities.

import { calculateAge, getLifeStage, getNextBirthday } from 'ts-time-utils/age';

calculateAge(new Date('1990-05-15'));  // { years: 34, months: 4, days: 2 }
getLifeStage(25);                      // "adult"
getNextBirthday(birthDate);            // Next birthday date

Countdown

Timer and countdown utilities.

import { createCountdown, getRemainingTime, formatCountdown } from 'ts-time-utils/countdown';

const countdown = createCountdown(targetDate, {
  onTick: (remaining) => console.log(remaining.days, 'd'),
  onComplete: () => console.log('Done!'),
});
countdown.start();

getRemainingTime(targetDate);  // { days, hours, minutes, seconds }
formatCountdown(targetDate, { units: ['days', 'hours'] });  // "45d 12h"

Interval

Time interval operations.

import { createInterval, intervalsOverlap, mergeIntervals } from 'ts-time-utils/interval';

const a = createInterval('2025-01-01', '2025-01-05');
const b = createInterval('2025-01-04', '2025-01-10');
intervalsOverlap(a, b);  // true
mergeIntervals([a, b]);  // Single merged interval

Range Presets

Common date range presets.

import { today, lastNDays, thisWeek, thisMonth } from 'ts-time-utils/rangePresets';

today();        // { start, end } for today
lastNDays(7);   // Last 7 days
thisWeek();     // Current week
thisMonth();    // Current month

Non-Gregorian Calendars

Convert dates between calendar systems using Intl.DateTimeFormat.

import { toHebrewDate, toIslamicDate, toJapaneseDate, getChineseZodiac } from 'ts-time-utils/calendars';

toHebrewDate(new Date());        // { year: 5785, month: 4, day: 23, calendar: 'hebrew' }
toIslamicDate(new Date());       // { year: 1446, month: 7, day: 1, calendar: 'islamic-umalqura' }
toJapaneseDate(new Date());      // { year: 6, era: 'Reiwa', calendar: 'japanese' }
getChineseZodiac(2024);          // 'Dragon'

// Supported: Hebrew, Islamic, Buddhist, Japanese, Persian, Chinese

Temporal API Compatibility

Future-proof with Temporal-like objects that work with native Date.

import { toPlainDate, toPlainDateTime, toZonedDateTime, toInstant } from 'ts-time-utils/temporal';

const date = toPlainDate(2024, 3, 25);
date.add({ days: 7 });           // PlainDate
date.until(otherDate);           // Duration
date.dayOfWeek;                  // 1 (Monday, ISO)

const zdt = toZonedDateTime(new Date(), 'America/New_York');
zdt.hour;                        // Hour in that timezone
zdt.toInstant();                 // Epoch-based Instant

const instant = toInstant(Date.now());
instant.toZonedDateTime('UTC');  // Convert to any timezone

High-Precision Utilities

Nanosecond timestamps, BigInt support, DST handling, and leap seconds.

import {
  createNanosecondTimestamp, nowNanoseconds,
  toBigIntMs, ValidDate, isInDSTGap, leapSecondsBetween
} from 'ts-time-utils/precision';

// Nanosecond precision
const ts = createNanosecondTimestamp(Date.now(), 500000);
ts.totalNanoseconds;             // BigInt

// BigInt timestamps for large date ranges
toBigIntMs(new Date());          // BigInt milliseconds

// DST transition detection
isInDSTGap(new Date('2024-03-10T02:30:00'));

// Validated dates (never invalid)
const valid = ValidDate.from(date);  // Throws if invalid
const maybe = ValidDate.tryFrom(date);  // Returns null if invalid

// Leap second awareness
leapSecondsBetween(date1, date2);  // Number of leap seconds

Parse

Date parsing from various formats.

import { parseDate, parseTime, autoDetectFormat } from 'ts-time-utils/parse';

parseDate('Dec 25, 2025');
parseDate('25/12/2025', 'DD/MM/YYYY');
parseTime('2:30 PM');  // { hour: 14, minute: 30 }
autoDetectFormat('2025-09-14');  // 'YYYY-MM-DD'

Scheduling

Appointment slots, availability, and booking conflict detection.

import {
  generateSlots, getAvailableSlots, findNextAvailable,
  hasConflict, findConflicts, mergeBookings
} from 'ts-time-utils/scheduling';

// Generate 30-min slots for a day
const slots = generateSlots(new Date(), {
  slotDuration: 30,
  workingHours: { startTime: { hour: 9, minute: 0 }, endTime: { hour: 17, minute: 0 } }
});

// Find available slots (excluding existing bookings)
const available = getAvailableSlots(new Date(), existingBookings, config);

// Find next available slot of specific duration
findNextAvailable(new Date(), bookings, 60, config);  // 60-min slot

// Check for conflicts
hasConflict(bookings, proposedSlot);  // true/false
findConflicts(bookings, proposedSlot);  // Array of conflicting bookings

// Merge adjacent bookings
mergeBookings(bookings);

Finance

Market hours, trading days, and settlement date calculations.

import {
  isMarketOpen, isTradingDay, getMarketHours,
  getNextMarketOpen, addTradingDays, getSettlementDate,
  eachTradingDay, getOptionsExpiration
} from 'ts-time-utils/finance';

// Check market status
isMarketOpen(new Date(), 'NYSE');      // Is NYSE open right now?
isTradingDay(new Date(), 'NASDAQ');    // Is today a trading day?
getMarketHours('NYSE');                // { open: {hour:9,minute:30}, close: {hour:16,minute:0} }

// Market timing
getNextMarketOpen(new Date());         // Next market open time
addTradingDays(new Date(), 5);         // 5 trading days from now

// Settlement (T+2, etc.)
getSettlementDate(tradeDate, 2);       // T+2 settlement date

// Iterate trading days
eachTradingDay(start, end);            // Array of trading days

// Options expiration (3rd Friday)
getOptionsExpiration(2025, 3);         // March 2025 expiration

Healthcare

Medication scheduling, shift patterns, and compliance windows.

import {
  getMedicationTimes, getNextMedicationTime, parseMedicationFrequency,
  generateShiftSchedule, getShiftForTime, isOnShift,
  createOnCallRotation, getOnCallStaff,
  getComplianceDeadline, timeUntilDeadline
} from 'ts-time-utils/healthcare';

// Medication times (BID = twice daily, TID = 3x daily, etc.)
getMedicationTimes(new Date(), 'BID');   // [8am, 8pm] (default wake/sleep times)
getMedicationTimes(new Date(), 'q6h');   // Every 6 hours
getNextMedicationTime(now, 'TID');       // Next scheduled dose
parseMedicationFrequency('twice daily'); // 'BID'

// Shift scheduling
generateShiftSchedule(start, end, { pattern: '12hr', startTime: { hour: 7, minute: 0 } });
getShiftForTime(now, shiftConfig);       // Current shift
isOnShift(now, shiftStart, config);      // Is within shift?

// On-call rotations
const rotation = createOnCallRotation(start, end, ['Dr. Smith', 'Dr. Jones'], 24);
getOnCallStaff(now, rotation);           // Who's on call?

// Compliance windows
getComplianceDeadline(eventDate, 72);    // 72-hour window
timeUntilDeadline(eventDate, deadline);  // Duration remaining

Plugin System

Extend ChainedDate with custom functionality.

import { chain, registerPlugin, createPlugin } from 'ts-time-utils/chain';

const businessPlugin = createPlugin('business', {
  addBusinessDays(days: number) {
    // Implementation
    return this;
  },
  isBusinessDay() {
    const day = this.toDate().getDay();
    return day !== 0 && day !== 6;
  }
});

registerPlugin(businessPlugin);

chain(new Date())
  .addBusinessDays(5)
  .isBusinessDay();  // true/false

API Reference

For complete API documentation, see the Playground & Docs.

All Modules

| Module | Description | |--------|-------------| | format | Duration formatting, time ago, date patterns | | calculate | Date arithmetic, differences, rounding | | validate | Date validation, comparisons, type checks | | duration | Immutable Duration class with arithmetic | | chain | Fluent chainable API | | timezone | Timezone conversions, DST handling | | calendar | ISO weeks, quarters, holidays, grids | | calendars | Non-Gregorian calendars (Hebrew, Islamic, etc.) | | temporal | Temporal API compatibility layer | | precision | Nanoseconds, BigInt, DST, leap seconds | | dateRange | Range operations: overlap, gaps, merge | | recurrence | RRULE-inspired recurring patterns | | cron | Cron expression parsing and matching | | fiscal | Fiscal year utilities | | compare | Date sorting, grouping, statistics | | iterate | Date iteration and counting | | naturalLanguage | Natural language date parsing | | holidays | International holidays (20 countries) | | locale | Multi-language formatting (40+ locales) | | workingHours | Business hours calculations | | serialize | JSON date serialization | | performance | Async utilities, benchmarking | | age | Age calculations, birthdays | | countdown | Timer and countdown utilities | | interval | Time interval operations | | rangePresets | Common date range presets | | parse | Date parsing from various formats | | scheduling | Appointment slots, availability, booking | | finance | Market hours, trading days, settlement | | healthcare | Medication schedules, shifts, on-call | | plugins | Plugin system for extensions | | constants | Time constants and types |


Development

npm install      # Install dependencies
npm run build    # Build both CJS and ESM
npm test         # Run tests
npm run lint     # Lint code

Releasing

Releases are automated via GitHub Actions with npm trusted publishing (OIDC).

To release a new version:

git tag v4.0.1        # Create tag (use semantic versioning)
git push --tags       # Push tag → triggers publish workflow

The workflow automatically:

  1. Sets package.json version from tag
  2. Runs lint, tests, and build
  3. Publishes to npm with provenance

Version format: Tags must match v* pattern (e.g., v4.0.0, v4.1.0-beta.1)

License

MIT