New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

temporal-fun

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

temporal-fun

Modern temporal date utility library, built for Temporal API

latest
npmnpm
Version
0.1.1
Version published
Weekly downloads
368
-21.37%
Maintainers
1
Weekly downloads
 
Created
Source

temporal-fun

A modern date utility library for working with the Temporal API.

Features

  • 🌟 Temporal Native: Built specifically for the modern Temporal API
  • 🔒 Pure Functions: All functions are immutable and side-effect free
  • 📝 TypeScript First: Fully typed with excellent LSP support
  • Concise API: Short names for the most common functionality (e.g. date("2025-08-28"))
  • 💪 Zero Dependencies: Only requires temporal-polyfill as a peer dependency

Installation

npm install --save temporal-fun temporal-polyfill

Quick Start

import { date, dateTime, zoned, dateLike, isDateTime, fmtRelativeToNow, fmtShort, now, startOfWeek, today } from 'temporal-fun';

// Parse & convert
date('2025-03-20')  // PlainDate
dateTime('2025-03-20T15:30:00')  // PlainDateTime
zoned('2024-01-15T18:30[America/New_York]')  // Zoned
zoned('2024-01-15', 'America/New_York')  // Zoned (midnight New York)

date('2025-03-20T15:30:00') // PlainDate (strips time component)
dateTime('2024-01-15')      // PlainDateTime (midnight)

// Current date/time
now()   // Instant
today() // PlainDate

// Parse into union of Temporal types with date component
const parsed = dateLike('2024-01-15T10:30');
if (isDateTime(parsed)) {
  // Type narrowed from DateLike to PlainDateTime
}

// Format dates
fmtShort(plainDate, 'en-US')    // "1/15/24"
fmtRelativeToNow(zonedDateTime, { locales: 'en-US'}) // "2 days ago"

// Date math
const weekStart = startOfWeek(zonedDateTime, 1); // Monday start

Core Concepts

Naming

Throughout this library:

  • date refers to Temporal.PlainDate
  • time refers to Temporal.PlainTime
  • dateTime refers to Temporal.PlainDateTime
  • zoned refers to Temporal.ZonedDateTime
  • instant refers to Temporal.Instant
  • legacy refers to the JS built-in Date

However, to avoid colliding with the built-in Date type/constructor, temporal-fun keeps the "Plain" prefixes only in the type definitions and constructor names.

// Constructor & type aliases
const PlainDate = Temporal.PlainDate;
const PlainDateTime = Temporal.PlainDateTime;
const Zoned = Temporal.ZonedDateTime;
const PlainTime = Temporal.PlainTime;
const Instant = Temporal.Instant;

// Union types
type DateLike = PlainDate | PlainDateTime | Zoned | Instant;  // Types with date component
type TimeLike = PlainTime | PlainDateTime | Zoned | Instant;  // Types with time component

API Categories

👷 Constructing

import { now, today, nowZoned, PlainDate, PlainDateTime, Instant, Time, Zoned } from 'temporal-fun';

// Current time functions
today();                         // → PlainDate (today)
today('America/New_York');       // → PlainDate (current date in New York)
now();                           // → Instant (current)
nowZoned('America/New_York');    // → ZonedDateTime (now in New York)

// Temporal constructors
PlainDate(year, month, day)
PlainDateTime(year, month, day, hour?, minute?, second?)
Instant(epochNanoseconds)
Zoned(epochNanoseconds, timezone)
PlainTime(hour?, minute?, second?)

📝 Parsing & Conversion

Construct Temporal types via parsing and/or conversions with intuitive behaviors.

The date, time, dateTime, zoned, and instant functions have 2 steps:

  • Parse strings into the best-fitting Temporal type (if called with strings)
  • Convert to the target Temporal type (if not already in target type)

See PARSING.md for a more thorough explanation and comparison of Temporal vs temporal-fun parsing methods:

import { dateLike, timeLike, date, dateTime, time, zoned, parseZoned, instant, now, nowZoned, legacy } from 'temporal-fun';

// Parsing
date('2024-01-15');               // → PlainDate
dateTime('2024-01-15T10:30:00');  // → PlainDateTime
time('14:30:00');                 // → PlainTime
instant('2024-01-15T10:30Z');     // → Instant
zoned('2024-01-15T10:30:00[America/New_York]'); // → Zoned

// Parse with automatic conversion
date('2024-01-15T10:30:00');      // → PlainDate (strips time)
dateTime('2024-01-15');           // → PlainDateTime (midnight)
time('2024-01-1514:30:00');       // → PlainTime (stripe date)
instant('2024-01-15');            // → Instant (midnight)
zoned('2024-01-15T10:30Z');       // → Zoned (UTC timezone)

// Converting
date(nowZoned('America/New_York'))  // → PlainDate: same as `today('America/New_York')`
instant(new Date())                 // → Instant: Same as `now()`
instant(date('2024-01-15'))         // → Instant: Same as `instant('2024-01-15')`
zoned(now())                        // → Zoned: Same as `nowZoned('UTC')`
zoned('2024-01-15', 'America/New_York');  // → Zoned: midnight in New York
zoned(new Date(), 'America/New_York');    // → Zoned: Same as `nowZoned('America/New_York')`

// Parse into a union of Temporal types
dateLike('2024-01-15');           // → PlainDate
dateLike('2024-01-15T10:30');     // → PlainDateTime
dateLike('2024-01-15T10:30Z');    // → Instant

// Convert back to legacy Date
legacy(instant('2024-01-15T10:30Z')); // → Date: Same as `new Date('2024-01-15T10:30Z')`

🔍 Type Guards

Check what type of Temporal object you're working with.

Each of these guards will narrow a DateLike or TimeLike type.

import { isDate, isDateTime, isZoned, isTime, isInstant, isDateLike, isTimeLike } from 'temporal-fun';

if (isDate(someValue)) {
  // TypeScript knows someValue is PlainDate
  console.log(someValue.toString());
}

if (isZoned(someValue)) {
  // TypeScript knows someValue is ZonedDateTime
  console.log(someValue.timeZoneId);
}

if (isDateLike(someValue)) {
  // Has date component (PlainDate | PlainDateTime | Zoned | Instant)
}

if (isTimeLike(someValue)) {
  // Has time component (PlainTime | PlainDateTime | Zoned | Instant)
}

🌎 Locales

Several formatting, comparison, math, and timezone functions accept locale(s) and/or weekStartsOn arguments which can be specified locally or globally.

import { setLocales } from 'temporal-fun';

const d = date("2025-03-20");

setLocales('en-US');  // Sets the default locale
startOfWeek(d)        // Uses Sunday as start-of-week (based on default locale)
fmtShort(d)           // Uses en-US locale (based on default locale)
fmtShort(d, 'en-GB')  // Overrides the default locale

📊 Comparison

Compare dates and check relationships.

import { compare, isBefore, isAfter, isEqualOrBefore, isEqualOrAfter, isSameDay, isSameWeek, min, max, minMax, rangesOverlap } from 'temporal-fun';

// Basic comparisons
compare(date1, date2);    // -1, 0, or 1
isBefore(date1, date2);           // boolean
isAfter(date1, date2);            // boolean
isEqualOrBefore(date1, date2);    // boolean
isEqualOrAfter(date1, date2);     // boolean

// Min/max
min([date1, date2, date3]);       // returns earliest date
max([date1, date2]);              // returns latest date
minMax([date1, date2, date3]);    // returns [earliest, latest]

// Day/week comparison
isSameDay(date1, date2);          // boolean
isSameWeek(date1, date2, 1);      // boolean (weekStartsOn: 1 = Monday)

// Range overlap
rangesOverlap([start1, end1], [start2, end2]); // boolean

🧮 Math & Manipulation

Start/end of periods, intervals, and date sequences.

import { startOfDay, endOfDay, startOfWeek, endOfWeek, startOfMonth, endOfMonth, startOfYear, endOfYear, stepInterval, eachDayOfInterval, eachWeekOfInterval, eachMonthOfInterval, eachYearOfInterval } from 'temporal-fun';

// Start/end of periods
startOfDay(dateTime);                    // Set time to 00:00:00
endOfDay(date);                          // Set time to 23:59:59.999
startOfWeek(date, 1);                    // Monday = 1, Sunday = 0 or 7
endOfWeek(date, 1);                      // End of week
startOfMonth(date);                      // First day of month
endOfMonth(date);                        // Last day of month
startOfYear(date);                       // January 1st
endOfYear(date);                         // December 31st
floor(dateTime, "minute")                // Round down to the minute
ceil(dateTime, "hour")                   // Round up to the hour
round(date, "hour")                      // Round to the nearest hour

// Interval sequences
eachDayOfInterval({ start, end });        // Array of PlainDate
eachWeekOfInterval({ start, end });       // Array of week starts
eachMonthOfInterval({ start, end });      // Array of month starts
eachYearOfInterval({ start, end });       // Array of year starts

stepInterval({ start, end }, { days: 2 }); // array of datelikes from start to end, in 2-day intervals
eachWeekOfInterval({ start, end }, { weekStartsOn: 7 }) // returns the Sunday of each week intersecting [start, end]

🎨 Formatting

Display dates in human-readable locale-aware formats.

Temporal already provides RFC 9557 (and related) formats via .toString(), and very comprehensive locale-specific formatting via .toLocaleString().

This package provides a few concise, simple formatting functions to cover to most common locale-specific variants.

These generally follow CLDR locale-specific formatting guidance with some timezone-related adjustments for specific types:

  • PlainDateTime: never render a timezone
  • Zoned: always render a timezone
  • Instant: always render in UTC
import { fmtRelativeToNow, fmtShort, fmtMedium, fmtLong } from 'temporal-fun';

// Relative formatting
fmtRelativeToNow(date, { locales: 'en-US' }); // "2 days ago"

// Short/medium/long formatting helpers
fmtShort(date, 'en-US');        // "3/24/25"
fmtMedium(date, 'en-US');       // "Mar 24, 2025"
fmtLong(dateTime, 'en-US');     // "March 24, 2025 at 8:30 AM"
fmtFull(dateTime, 'en-US');      // "Monday, March 24, 2025 at 8:30:05 AM"

Note: The installed ICU/locales can affect this formatting, especially for loosely specified format details like separators and spacing. Examples renderings for select locales (generated by bin/locale-formats.ts <locales>):

Formaten-USen-GBes-ESzh-CN
PlainDate short3/24/2524/03/202524/3/252025/3/24
PlainDate mediumMar 24, 202524 Mar 202524 mar 20252025年3月24日
PlainDate longMarch 24, 202524 March 202524 de marzo de 20252025年3月24日
PlainDate fullMonday, March 24, 2025Monday, 24 March 2025lunes, 24 de marzo de 20252025年3月24日 星期一
PlainTime short8:30 AM08:308:3008:30
PlainTime medium8:30:05 AM08:30:058:30:0508:30:05
PlainTime long8:30:05 AM08:30:058:30:0508:30:05
PlainTime full8:30:05 AM08:30:058:30:0508:30:05
PlainDateTime short3/24/25, 8:30 AM24/03/2025, 08:3024/3/25, 8:302025/3/24 08:30
PlainDateTime mediumMar 24, 2025 at 8:30 AM24 Mar 2025 at 08:3024 mar 2025, 8:302025年3月24日 08:30
PlainDateTime longMarch 24, 2025 at 8:30 AM24 March 2025 at 08:3024 de marzo de 2025, 8:302025年3月24日 08:30
PlainDateTime fullMonday, March 24, 2025 at 8:30:05 AMMonday, 24 March 2025 at 08:30:05lunes, 24 de marzo de 2025, 8:30:052025年3月24日 星期一 08:30:05
Zoned short3/24/25, 8:30 AM EDT24/03/2025, 08:30 GMT-424/3/25, 8:30 GMT-42025/3/24 08:30GMT-4
Zoned mediumMar 24, 2025 at 8:30 AM EDT24 Mar 2025 at 08:30 GMT-424 mar 2025, 8:30 GMT-42025年3月24日 08:30GMT-4
Zoned longMarch 24, 2025 at 8:30 AM Eastern Daylight Time24 March 2025 at 08:30 Eastern Daylight Time24 de marzo de 2025, 8:30 hora de verano oriental2025年3月24日 08:30北美东部夏令时间
Zoned fullMonday, March 24, 2025 at 8:30:05 AM Eastern Daylight TimeMonday, 24 March 2025 at 08:30:05 Eastern Daylight Timelunes, 24 de marzo de 2025, 8:30:05 (hora de verano oriental)2025年3月24日 星期一 北美东部夏令时间 08:30:05
Instant short3/24/25, 1:30 PM UTC24/03/2025, 13:30 UTC24/3/25, 13:30 UTC2025/3/24 13:30UTC
Instant mediumMar 24, 2025 at 1:30 PM UTC24 Mar 2025 at 13:30 UTC24 mar 2025, 13:30 UTC2025年3月24日 13:30UTC
Instant longMarch 24, 2025 at 1:30 PM UTC24 March 2025 at 13:30 UTC24 de marzo de 2025, 13:30 UTC2025年3月24日 13:30UTC
Instant fullMonday, March 24, 2025 at 1:30:05 PM Coordinated Universal TimeMonday, 24 March 2025 at 13:30:05 Coordinated Universal Timelunes, 24 de marzo de 2025, 13:30:05 (tiempo universal coordinado)2025年3月24日 星期一 协调世界时 13:30:05

🌍 Timezone

Work with timezones and timezone information.

import { getAllTimezones, isValidTimezone, getTimezoneName, getGMTOffset } from 'temporal-fun';

// Get all available timezones
getAllTimezones();                          // Array of IANA timezone strings

// Validate timezone
isValidTimezone('America/New_York');        // true
isValidTimezone('Invalid/Zone');            // false

// Get timezone display name
getTimezoneName(zonedDateTime);             // "EST" or "EDT" (depends on date)
getTimezoneName(zonedDateTime, { style: 'long', locale: 'en-US' }); // "Eastern Standard Time"

// Format GMT offset
getGMTOffset(300);                          // "GMT+5:00" (300 minutes = 5 hours)
getGMTOffset(-330);                         // "GMT-5:30" (India offset)

✅ Validation

Validate if a string can be parsed into a given Temporal type.

import { isValidDateString, isValidTimeString, isValidZonedString } from 'temporal-fun';

// Validation
isValidDateString('2024-01-15'); // true
isValidTimeString('25:30'); // false
isValidDateTimeString('2024-01-15 25:30') // true
isValidInstant('2024-01-15'); // false
isValidZonedString('2024-01-15T10:30:00[America/New_York]') // true

Keywords

temporal

FAQs

Package last updated on 01 Oct 2025

Did you know?

Socket

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.

Install

Related posts