nc.time
Dates and durations: formatting, relative time, calendar math, time zones and scheduling, in any language Intl knows. The default language is English so results are the same on every machine; change it with setLocale() or per call with { locale }. Time zones work the same way with setTimezone() or { timeZone }.
const { time } = require("@ix-xs/node-comfort");
import { setLocale } from "@ix-xs/node-comfort/time";time.setLocale("fr").setTimezone("Europe/Paris");
time.relative(Date.now() - 3600e3); // "il y a 1 heure"
time.format(new Date(), "dddd D MMMM YYYY"); // "lundi 15 janvier 2024"
time.cron("0 9 * * 1-5", sendReport); // weekdays at 9:00nc.time.Functions
nc.time.setLocale()
setLocale(locale: string): typeof nc.timeSets the default language for relative, calendar, formatDuration and format.
Parameters
| Name | Type | Description |
|---|---|---|
locale | string | Like "fr", "en-GB", "pt-BR" or "ja". |
Returns typeof import("./Time"): The module, so calls chain.
Example
time.setLocale("fr");
time.relative(Date.now() - 60e3); // "il y a 1 minute"nc.time.setTimezone()
setTimezone(timeZone: string | undefined): typeof nc.timeSets the default time zone for format, calendar, isSameDay, cron... Pass undefined to go back to the system zone.
Parameters
| Name | Type | Description |
|---|---|---|
timeZone | string | undefined | Like "America/New_York". |
Returns typeof import("./Time"): The module, so calls chain.
Throws RangeError If the zone doesn't exist.
Example
time.setTimezone("Europe/Paris");nc.time.getConfig()
getConfig(): { locale: string; timeZone: string | undefined; }The current defaults.
Returns { locale: string, timeZone: string | undefined }
Example
time.getConfig(); // { locale: "en", timeZone: undefined }nc.time.timezones()
timezones(): string[]Every time zone Node knows, sorted.
Returns string[]
Example
time.timezones().includes("Europe/Paris"); // truenc.time.offset()
offset(timeZone?: string, date?: DateInput): numberA zone's UTC offset at a given date, in minutes. Daylight saving included.
Parameters
| Name | Type | Description |
|---|---|---|
timeZoneoptional | string | Defaults to the global zone, then the system's. |
dateoptional | DateInput | Defaults to now. |
Returns number
Example
time.offset("Europe/Paris", "2024-07-01"); // 120
time.offset("Europe/Paris", "2024-01-01"); // 60nc.time.parseDuration()
parseDuration(input: string | number): number | nullTurns a duration into milliseconds. Understands "1h30m", "2 days", "500ms", clock times like "01:30:00", ISO durations like "PT1H30M", and plain numbers. Months and years are refused because their length varies; use add() for those.
Parameters
| Name | Type |
|---|---|
input | string | number |
Returns number | null: null when it isn't a duration.
Example
time.parseDuration("1h30m"); // 5400000
time.parseDuration("01:30:00"); // 5400000
time.parseDuration("banana"); // nullnc.time.formatDuration()
formatDuration(ms: number, options?: FormatDurationOptions): stringWrites a duration for humans.
Parameters
| Name | Type |
|---|---|
ms | number |
optionsoptional | FormatDurationOptions |
Returns string
Example
time.formatDuration(5_400_000); // "1h 30m"
time.formatDuration(90_000, { long: true }); // "1 minute 30 seconds"
time.formatDuration(90_000, { long: true, locale: "fr" }); // "1 minute 30 secondes"
time.formatDuration(93_784_000, { units: 2 }); // "1d 2h"
time.formatDuration(5_405_000, { clock: true }); // "01:30:05"nc.time.relative()
relative(date: DateInput, from?: DateInput, options?: RelativeOptions): stringDescribes a date relative to now: "3 hours ago", "in 2 days", in any language.
Parameters
| Name | Type | Description |
|---|---|---|
date | DateInput | |
fromoptional | DateInput | Compare with this date instead of now. |
optionsoptional | RelativeOptions |
Returns string
Example
time.relative(Date.now() - 3_600_000); // "1 hour ago"
time.relative(Date.now() - 86_400_000, undefined, { numeric: "auto" }); // "yesterday"
time.relative(Date.now() - 3_600_000, undefined, { locale: "fr" }); // "il y a 1 heure"nc.time.calendar()
calendar(date: DateInput, options?: CalendarOptions): stringDescribes a date like a chat app does: "Today at 2:30 PM", "Yesterday at 9:05 AM", a weekday for the coming days, and the full date beyond that.
Parameters
| Name | Type |
|---|---|
date | DateInput |
optionsoptional | CalendarOptions |
Returns string
Example
time.calendar(new Date()); // "Today at 2:30 PM"
time.calendar(yesterday, { locale: "fr" }); // "Hier à 09:05"nc.time.format()
format(date: DateInput, pattern?: string, options?: FormatDateOptions): stringFormats a date with tokens, in any language and time zone.
| Token | Output | Token | Output | |
|---|---|---|---|---|
YYYY / YY | 2024 / 24 | HH / H | 09 / 9 (24h) | |
Q | quarter, 1-4 | hh / h | 09 / 9 (12h) | |
MMMM / MMM | January / Jan | mm / m | 05 / 5 | |
MM / M | 01 / 1 | ss / s | 07 / 7 | |
DD / D | 05 / 5 | SSS | 042 (ms) | |
dddd / ddd | Monday / Mon | A / a | PM / pm | |
d | weekday, 0 is Sunday | Z / ZZ | +02:00 / +0200 | |
W / WW | ISO week | X / x | Unix seconds / ms |
Text in brackets stays as is: "[Today is] dddd".
Parameters
| Name | Type | Description |
|---|---|---|
date | DateInput | |
patternoptional | string | Default: "YYYY-MM-DD HH:mm:ss" |
optionsoptional | FormatDateOptions |
Returns string: Or "Invalid Date".
Example
time.format(new Date(), "YYYY-MM-DD HH:mm:ss"); // "2024-01-15 14:30:05"
time.format(Date.now(), "dddd D MMMM YYYY", { locale: "fr" }); // "lundi 15 janvier 2024"
time.format(Date.now(), "HH:mm Z", { timeZone: "Asia/Tokyo" }); // "22:30 +09:00"nc.time.toISODate()
toISODate(date?: DateInput, options?: TimeZoneOptions): stringThe date as YYYY-MM-DD, the format <input type="date"> and most APIs expect.
Parameters
| Name | Type | Description |
|---|---|---|
dateoptional | DateInput | Defaults to now. |
optionsoptional | TimeZoneOptions |
Returns string
Example
time.toISODate(new Date(2024, 0, 5)); // "2024-01-05"nc.time.add()
add(date: DateInput, amount: string | number, unit?: CalendarUnit): DateAdds time to a date and returns a new Date. Months and years follow the calendar: January 31 plus one month is the end of February.
Parameters
| Name | Type | Description |
|---|---|---|
date | DateInput | |
amount | number | string | A number with unit, or a duration like "1h30m". |
unitoptional | CalendarUnit | Default: "ms" |
Returns Date
Example
time.add(new Date(), "2h30m");
time.add(new Date(), 3, "days");
time.add(new Date(2024, 0, 31), 1, "month"); // 2024-02-29nc.time.subtract()
subtract(date: DateInput, amount: string | number, unit?: CalendarUnit): DateSubtracts time from a date and returns a new Date.
Parameters
| Name | Type | Description |
|---|---|---|
date | DateInput | |
amount | number | string | |
unitoptional | CalendarUnit | Default: "ms" |
Returns Date
Example
time.subtract(new Date(), 7, "days");
time.subtract(new Date(), "90m");nc.time.diff()
diff(a: DateInput, b: DateInput, unit?: CalendarUnit): numbera - b in a unit. Fixed units can give fractions; months and years are whole calendar months and years.
Parameters
| Name | Type | Description |
|---|---|---|
a | DateInput | |
b | DateInput | |
unitoptional | CalendarUnit | Default: "ms" |
Returns number
Example
time.diff("2024-01-03", "2024-01-01", "days"); // 2
time.diff("2024-03-15", "2024-01-20", "months"); // 1nc.time.startOf()
startOf(date: DateInput, unit: StartOfUnit, options?: WeekOptions): DateA new Date at the start of the day, week, month... in local time.
Parameters
| Name | Type |
|---|---|
date | DateInput |
unit | StartOfUnit |
optionsoptional | WeekOptions |
Returns Date
Example
time.startOf(new Date(), "day"); // today at 00:00
time.startOf(new Date(), "week"); // Monday at 00:00
time.startOf(new Date(), "week", { weekStartsOn: 0 }); // Sunday at 00:00nc.time.endOf()
endOf(date: DateInput, unit: StartOfUnit, options?: WeekOptions): DateA new Date at the last millisecond of the day, week, month...
Parameters
| Name | Type |
|---|---|
date | DateInput |
unit | StartOfUnit |
optionsoptional | WeekOptions |
Returns Date
Example
time.endOf(new Date(), "month"); // last day of the month, 23:59:59.999nc.time.isBefore()
Is a before b?
Returns boolean
nc.time.isAfter()
Is a after b?
Returns boolean
Example
if (time.isAfter(expiresAt, Date.now())) grantAccess();nc.time.isBetween()
Is the date between start and end, both included?
Returns boolean
nc.time.isSameDay()
isSameDay(a: DateInput, b: DateInput, options?: TimeZoneOptions): booleanAre both dates on the same calendar day?
Parameters
| Name | Type |
|---|---|
a | DateInput |
b | DateInput |
optionsoptional | TimeZoneOptions |
Returns boolean
Example
time.isSameDay(a, b); // local time
time.isSameDay(a, b, { timeZone: "Asia/Tokyo" }); // as seen in Tokyonc.time.isToday()
isToday(date: DateInput, options?: TimeZoneOptions): booleanIs the date today?
Parameters
| Name | Type |
|---|---|
date | DateInput |
optionsoptional | TimeZoneOptions |
Returns boolean
nc.time.isYesterday()
isYesterday(date: DateInput, options?: TimeZoneOptions): booleanWas the date yesterday?
Parameters
| Name | Type |
|---|---|
date | DateInput |
optionsoptional | TimeZoneOptions |
Returns boolean
nc.time.isTomorrow()
isTomorrow(date: DateInput, options?: TimeZoneOptions): booleanIs the date tomorrow?
Parameters
| Name | Type |
|---|---|
date | DateInput |
optionsoptional | TimeZoneOptions |
Returns boolean
nc.time.isWeekend()
isWeekend(date: DateInput, options?: TimeZoneOptions): booleanIs it a Saturday or a Sunday?
Parameters
| Name | Type |
|---|---|
date | DateInput |
optionsoptional | TimeZoneOptions |
Returns boolean
nc.time.isLeapYear()
isLeapYear(yearOrDate: DateInput): booleanIs it a leap year?
Parameters
| Name | Type | Description |
|---|---|---|
yearOrDate | number | DateInput | A year (1000 to 9999) or a date. |
Returns boolean
Example
time.isLeapYear(2024); // true
time.isLeapYear(1900); // falsenc.time.isValid()
isValid(value: unknown): booleanIs it a real date, or something that parses to one?
Parameters
| Name | Type |
|---|---|
value | unknown |
Returns boolean
Example
time.isValid("2024-02-29"); // true
time.isValid("2024-02-30"); // falsenc.time.daysInMonth()
daysInMonth(dateOrYear: DateInput, month?: number): numberNumber of days in a month.
Parameters
| Name | Type | Description |
|---|---|---|
dateOrYear | DateInput | number | A date, or a year when you pass month. |
monthoptional | number | 1 to 12. |
Returns number
Example
time.daysInMonth(new Date(2024, 1)); // 29
time.daysInMonth(2023, 2); // 28nc.time.dayOfYear()
dayOfYear(date?: DateInput): numberDay of the year, from 1 to 366.
Parameters
| Name | Type | Description |
|---|---|---|
dateoptional | DateInput | Defaults to now. |
Returns number
nc.time.weekOfYear()
weekOfYear(date?: DateInput, options?: { utc?: boolean; } | undefined): numberISO week number, from 1 to 53. Weeks start on Monday, and week 1 holds the year's first Thursday.
Parameters
| Name | Type | Description |
|---|---|---|
dateoptional | DateInput | Defaults to now. |
optionsoptional | { utc?: boolean } | Read the date in UTC. |
Returns number
Example
time.weekOfYear(new Date(2021, 0, 3)); // 53, the last week of 2020nc.time.min()
min(dates: Iterable<DateInput>): Date | undefinedThe earliest date.
Parameters
| Name | Type |
|---|---|
dates | Iterable<DateInput> |
Returns Date | undefined
nc.time.max()
max(dates: Iterable<DateInput>): Date | undefinedThe latest date.
Parameters
| Name | Type |
|---|---|
dates | Iterable<DateInput> |
Returns Date | undefined
nc.time.unix()
unix(): numberThe current Unix timestamp, in seconds.
Returns number
nc.time.stopwatch()
stopwatch(): StopwatchStarts a precise stopwatch.
Returns Stopwatch
Example
const sw = time.stopwatch();
await loadConfig(); sw.lap("config");
await connectDb(); sw.lap("db");
console.log(sw.stop(true)); // "182.4ms"nc.time.measure()
measure<T>(fn: () => T): Promise<{ result: Awaited<T>; duration: number; }>Runs a function, sync or async, and tells you how long it took.
Parameters
| Name | Type |
|---|---|
fn | () => T |
Returns Promise<{ result: Awaited<T>, duration: number }>: duration is in milliseconds.
Example
const { result, duration } = await time.measure(() => db.query(sql));
nc.info(`Query took ${duration.toFixed(1)}ms`);nc.time.every()
every(interval: string | number, task: () => unknown, options?: EveryOptions): ScheduledTaskRuns a task at a regular interval. Unlike setInterval, a slow run delays the next one instead of piling up, timing doesn't drift, and errors are caught.
Parameters
| Name | Type | Description |
|---|---|---|
interval | number | string | In ms, or a duration like "30s". |
task | () => unknown | Can be async. |
optionsoptional | EveryOptions |
Returns ScheduledTask
Throws RangeError If the interval isn't a positive duration.
Example
const job = time.every("5m", syncInventory, { immediate: true, onError: nc.error });
job.next(); // when it runs next
job.stop();nc.time.nextRun()
nextRun(expression: string, options?: CronOptions): Date | undefinedThe next date matching a cron expression, without scheduling anything.
Expressions have 5 fields (minute hour day month weekday), or 6 with seconds first. You can use *, lists (1,15), ranges (1-5), steps (*\/15), names (jan, mon-fri) and @daily, @hourly, @weekly, @monthly, @yearly. As in classic cron, when both the day and the weekday are set, either one matching is enough.
Parameters
| Name | Type |
|---|---|
expression | string |
optionsoptional | CronOptions |
Returns Date | undefined: undefined if nothing matches within 8 years.
Throws SyntaxError If the expression is invalid.
Example
time.nextRun("0 9 * * mon-fri"); // next weekday at 09:00
time.nextRun("0 0 1 * *", { timeZone: "America/New_York" }); // next 1st of the monthnc.time.cron()
cron(expression: string, task: () => unknown, options?: CronOptions): ScheduledTaskRuns a task on a cron schedule, in any time zone. Daylight-saving changes are handled: a skipped time is skipped, a repeated one runs once. See nextRun() for the syntax.
Parameters
| Name | Type | Description |
|---|---|---|
expression | string | |
task | () => unknown | Can be async. |
optionsoptional | CronOptions |
Returns ScheduledTask
Throws SyntaxError If the expression is invalid.
Example
const job = time.cron("0 9 * * 1-5", sendDailyReport, { timeZone: "Europe/Paris" });
time.cron("*\/15 * * * *", refreshCache, { onError: nc.error });
job.stop();Types
Import any of them in TypeScript with import type { CalendarOptions } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").CalendarOptions.
CalendarOptions
Options for calendar().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Defaults to the global locale. |
timeZoneoptional | string | Defaults to the global zone, then the system's. |
nowoptional | DateInput | What "now" is. Defaults to the current time. |
CalendarUnit
A fixed unit, or months and years, whose length varies.
type CalendarUnit = DurationUnit | "M" | "month" | "months" | "y" | "year" | "years"CronOptions
Options for cron() and nextRun().
| Property | Type | Description |
|---|---|---|
timeZoneoptional | string | Zone in which the expression is read, like "Europe/Paris". Defaults to the global zone, then the system's. |
fromoptional | DateInput | nextRun() only: search after this date. Defaults to now. |
unrefoptional | boolean | Let the process exit even if the schedule is active. |
overlapoptional | boolean | Start a run even if the previous one hasn't finished. By default it's skipped. |
onErroroptional | ((error: unknown) => void) | Called when the task fails. |
CronSpec
Parsed cron fields.
| Property | Type | Description |
|---|---|---|
seconds | Set<number> | |
minutes | Set<number> | |
hours | Set<number> | |
days | Set<number> | |
months | Set<number> | |
weekdays | Set<number> | |
anyDay | boolean | |
anyWeekday | boolean |
DateInput
A date: a Date, a timestamp in ms, or a string new Date() understands (ISO 8601 is safest).
type DateInput = Date | number | stringDurationUnit
A unit with a fixed length.
type DurationUnit = "ms" | "millisecond" | "milliseconds" | "s" | "sec" | "second" | "seconds" | "m" | "min" | "minute" | "minutes" | "h" | "hour" | "hours" | "d" | "day" | "days" | "w" | "week" | "weeks"EveryOptions
Options for every().
| Property | Type | Description |
|---|---|---|
immediateoptional | boolean | Also run once right away. |
unrefoptional | boolean | Let the process exit even if the schedule is active. |
onErroroptional | ((error: unknown) => void) | Called when the task fails. Without it, errors surface as unhandled errors. |
FormatDateOptions
Options for format().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Language of month and day names. Defaults to the global locale. |
timeZoneoptional | string | Show the date in this zone, like "Asia/Tokyo". Defaults to the global zone, then the system's. |
FormatDurationOptions
Options for formatDuration().
| Property | Type | Description |
|---|---|---|
longoptional | boolean | Full, translated words: "1 hour 30 minutes" instead of "1h 30m". |
unitsoptional | number | Show at most this many units, largest first: units: 2 turns "1d 3h 5m" into "1d 3h". |
clockoptional | boolean | Clock style, like "01:30:05". |
millisecondsoptional | boolean | Show milliseconds. Defaults to true. |
localeoptional | string | Language for long. Defaults to the global locale. |
RelativeOptions
Options for relative().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Defaults to the global locale. |
numericoptional | "always" | "auto" | "auto" says "yesterday" instead of "1 day ago". Defaults to "always". |
styleoptional | "long" | "short" | "narrow" | "short" gives "in 3 mo.". Defaults to "long". |
ScheduledTask
A schedule returned by every() and cron().
| Property | Type | Description |
|---|---|---|
stop | () => void | Stops the schedule. A run in progress finishes. |
next | () => Date | When the next run is planned. |
isRunning | () => boolean | Whether a run is in progress. |
runs | () => number | How many runs have started. |
StartOfUnit
A unit for startOf() and endOf().
type StartOfUnit = "year" | "quarter" | "month" | "week" | "isoWeek" | "day" | "hour" | "minute" | "second"Stopwatch
Returned by stopwatch().
| Property | Type | Description |
|---|---|---|
elapsed | () => number | Milliseconds since the start. |
stop | (format?: boolean) => string | number | The elapsed time; stop(true) formats it, like "1.5s". |
lap | (label?: string) => number | Records a lap and returns the ms since the previous one. |
laps | () => { label: string; ms: number; total: number; }[] | Every lap so far. |
reset | () => void | Starts over. |
TimeZoneOptions
Time zone setting.
| Property | Type | Description |
|---|---|---|
timeZoneoptional | string | Zone used to decide which day it is. Defaults to the global zone, then the system's. |
WeekOptions
Week settings.
| Property | Type | Description |
|---|---|---|
weekStartsOnoptional | 0 | 4 | 6 | 2 | 1 | 3 | 5 | First day of the week: 0 for Sunday, 1 for Monday. Defaults to 1. |