ts-time-utils
v4.1.0
Published
A comprehensive TypeScript utility library for time, dates, durations, and calendar operations with full tree-shaking support
Maintainers
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.
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-utilsQuick 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 monthValidate
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); // booleanDuration
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; // 5Chain 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 MondayTimezone
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 holidaysDate 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/falseRecurrence
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 fiscalCompare & 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 gridIterate
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 monthNatural 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, CHLocale
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 localeWorking 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 dateCountdown
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 intervalRange 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 monthNon-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, ChineseTemporal 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 timezoneHigh-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 secondsParse
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 expirationHealthcare
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 remainingPlugin 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/falseAPI 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 codeReleasing
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 workflowThe workflow automatically:
- Sets
package.jsonversion from tag - Runs lint, tests, and build
- Publishes to npm with provenance
Version format: Tags must match v* pattern (e.g., v4.0.0, v4.1.0-beta.1)
License
MIT
