@eryx/date Module

JSON

Lightweight datetime module backed by C++20 std::chrono.

Two core types are exposed: DateTime: a specific instant in time, paired with a display timezone. Duration: a signed span of time at nanosecond precision.

Timezone semantics

A DateTime always stores the true UTC instant internally. The zone field only controls how that instant is displayed (local date/time fields, ISO string, etc.).

Instants produced by fromIso() or parse() carry a fixed UTC offset from the string (e.g. +05:30). Fixed-offset instants are unaware of DST. Call WithZone() to attach a named IANA zone so that DST-aware arithmetic and display work correctly.

Format strings

Format(), FormatUtc(), and parse() accept C++20 std::chrono format tokens:

Token Meaning
%Y Four-digit year
%m Month (01-12)
%d Day (01-31)
%F %Y-%m-%d
%H Hour (00-23)
%M Minute (00-59)
%S Second (00-59) (+ sub-seconds)
%I Hour (01-12)
%p AM / PM
%T %H:%M:%S
%R %H:%M
%A Full weekday name
%B Full month name
%j Day of year
%a Abbreviated weekday
%b Abbreviated month
%Z Timezone name / offset
%z UTC offset +HHMM
%Ez UTC offset +HH:MM

Literal { or } in a format string must be escaped as {{ or }}.

Summary

Classes

days: number
hours: number
minutes: number
seconds: number
milliseconds: number
microseconds: number
nanoseconds: number
subSeconds: number
totalDays: number
totalHours: number
totalMinutes: number
totalSeconds: number
totalMilliseconds: number
totalMicroseconds: number
totalNanoseconds: number
year: number
month: number
day: number
hour: number
minute: number
second: number
nanosecond: number
zone: string
offset: number
weekday: number
dayOfYear: number
isLeap: boolean
isDst: boolean
DateTime:toUnix()number
DateTime:toUnixMs()number
DateTime:withZone(zone: string)DateTime
DateTime:format(fmt: string)string
DateTime:formatUtc(fmt: string)string
DateTime:relative(other: DateTime?)string

Functions

date.now(zone: string?)DateTime
date.fromIso(s: string)DateTime
date.fromTimestamp(ts: number, zone: string?)DateTime
date.fromFields(fields: { year: number, month: number, day: number, hour: number?, minute: number?, second: number?, nanosecond: number? }, zone: string?)DateTime
date.parse(s: string, fmt: string, zone: string?)DateTime
date.timezone()string
date.timezones(){ string }
date.isLeap(year: number)boolean
date.daysInMonth(year: number, month: number)number
date.nanoseconds(n: number)Duration
date.seconds(n: number)Duration
date.minutes(n: number)Duration
date.hours(n: number)Duration
date.days(n: number)Duration

API Reference

Classes

Duration

A signed span of time stored at nanosecond precision.

Component fields give the remainder at each unit after larger units are subtracted (e.g. for a 90-second duration, minutes = 1 and seconds = 30).

Total fields give the entire duration expressed as a floating-point count of the named unit (e.g. for 90 seconds, totalMinutes ≈ 1.5).

Supported operators: +, -, * (scale by number), / (scale by number; dividing two Durations yields a number ratio), unary -, ==, <, <=.

Properties

days: number

Days component

hours: number

Hours component

minutes: number

Minutes component

seconds: number

Seconds component

milliseconds: number

Milliseconds component

microseconds: number

Microseconds component

nanoseconds: number

Nanoseconds component

subSeconds: number

Sub-second remainder as a floating-point fraction of a second.

totalDays: number

Total days

totalHours: number

Total hours

totalMinutes: number

Total minutes

totalSeconds: number

Total seconds

totalMilliseconds: number

Total milliseconds

totalMicroseconds: number

Total microseconds

totalNanoseconds: number

Total nanoseconds

Duration:abs

Returns a new Duration with the same magnitude but always non-negative.

Duration:abs()Duration

DateTime

A specific instant in time paired with a display timezone.

All calendar fields (year, month, ...) reflect local time in the associated zone. The underlying UTC instant is unchanged by WithZone().

Supported operators: + / - with a Duration (shifts the instant), ==, <, <= (compare UTC instants regardless of zone). Subtracting two DateTimes is not supported via -; use Diff() instead.

Properties

year: number

Gregorian year (e.g. 2024)

month: number

Month of year, 1 = January, 12 = December

day: number

Day of month, 1–31

hour: number

Hour of day, 0–23

minute: number

Minute of hour, 0–59

second: number

Second of minute, 0–59

nanosecond: number

Nanosecond of second, 0–999999999

zone: string

IANA timezone name (e.g. "America/New_York") for named-zone instants, or a fixed UTC offset string (e.g. "+05:30") for fixed-offset instants.

offset: number

UTC offset in seconds for the instant (accounts for DST when using a named zone).

weekday: number

ISO 8601 weekday: 1 = Monday, 7 = Sunday.

dayOfYear: number

Day of the year: 1 = January 1, 365/366 = December 31.

isLeap: boolean

true when the year of this instant is a leap year.

isDst: boolean

true when this instant falls within a DST period. Always false for fixed-offset instants (they have no DST concept).

DateTime:toIsoString

Returns an ISO 8601 string such as "2024-03-15T10:30:00+05:30". Sub-seconds are included only when non-zero.

DateTime:toIsoString()string

DateTime:toUnix

Returns the UTC Unix timestamp as a whole number of seconds.

DateTime:toUnix()number

DateTime:toUnixMs

Returns the UTC Unix timestamp as a whole number of milliseconds.

DateTime:toUnixMs()number

DateTime:withZone

Returns a new DateTime representing the same UTC instant displayed in zone. Converts a fixed-offset instant into a DST-aware named-zone one. Throws if zone is not a valid IANA timezone name.

DateTime:withZone(zone: string)DateTime

DateTime:diff

Returns a Duration equal to self − other (positive when self is later).

DateTime:diff(other: DateTime)Duration

DateTime:format

Formats local time using a chrono format string (see module docs for tokens). For fixed-offset instants, %z/%Ez/%Z expand to the literal offset. Example: dt:Format("%Y-%m-%d %H:%M") -> "2024-03-15 10:30"

DateTime:format(fmt: string)string

DateTime:formatUtc

Formats the underlying UTC time using a chrono format string. %z will always output +0000.

DateTime:formatUtc(fmt: string)string

DateTime:startOfDay

Returns a new DateTime at midnight (00:00:00.000000000) of the same local calendar day, preserving the zone/offset.

DateTime:startOfDay()DateTime

DateTime:addMonths

Returns a new DateTime shifted by n calendar months (may be negative). The day is clamped to the last valid day of the target month (e.g. Jan 31 + 1 month -> Feb 28/29).

DateTime:addMonths(n: number)DateTime

DateTime:addYears

Returns a new DateTime shifted by n calendar years (may be negative). Equivalent to AddMonths(n * 12).

DateTime:addYears(n: number)DateTime

DateTime:relative

Returns a human-readable relative time string such as "2 hours ago" or "in 3 days". When other is omitted, the current instant is used.

DateTime:relative(other: DateTime?)string

Functions

date.now

Returns the current instant.

date.now(zone: string?)DateTime

Parameters

zone: string?

Optional IANA timezone name. Defaults to the system local zone.

date.fromIso

Parses an ISO 8601 timestamp string (e.g. "2024-03-15T10:30:00+05:30"). The UTC offset embedded in the string is stored as a fixed offset; call WithZone() on the result if you need DST-aware behaviour.

date.fromIso(s: string)DateTime

date.fromTimestamp

Creates a DateTime from a Unix timestamp (seconds since 1970-01-01T00:00:00Z). Fractional seconds are supported (nanosecond precision).

date.fromTimestamp(ts: number, zone: string?)DateTime

Parameters

ts: number

Seconds since the Unix epoch (may be fractional).

zone: string?

Optional IANA timezone name. Defaults to the system local zone.

date.fromFields

Creates a DateTime from individual calendar fields in the given timezone. Missing optional fields default to 0. The day is not clamped – passing an invalid date (e.g. February 30) raises an error.

date.fromFields(fields: { year: number, month: number, day: number, hour: number?, minute: number?, second: number?, nanosecond: number? }, zone: string?)DateTime

Parameters

fields: { year: number, month: number, day: number, hour: number?, minute: number?, second: number?, nanosecond: number? }

Table with required keys year, month, day and optional keys hour, minute, second, nanosecond.

zone: string?

IANA timezone name. Defaults to the system local zone.

date.parse

Parses a datetime string using a chrono format string (see module docs for tokens).

date.parse(s: string, fmt: string, zone: string?)DateTime

Parameters

s: string

The input string to parse.

fmt: string

A chrono format string, e.g. "%Y-%m-%d %H:%M:%S".

zone: string?

Optional IANA timezone name. If omitted, the UTC offset parsed from the string is stored as a fixed offset; if no offset was parsed, the system local zone is assumed.

date.timezone

Returns the IANA name of the system's local timezone (e.g. "America/New_York").

date.timezone()string

date.timezones

Returns a list of all recognised IANA timezone names in the embedded TZ database.

date.timezones(){ string }

date.isLeap

Returns true when year is a leap year.

date.isLeap(year: number)boolean

date.daysInMonth

Returns the number of days in month of year (accounts for leap years). month is 1-based (1 = January).

date.daysInMonth(year: number, month: number)number

date.nanoseconds

Returns a Duration of exactly n nanoseconds.

date.nanoseconds(n: number)Duration

date.milliseconds

Returns a Duration of exactly n milliseconds.

date.milliseconds(n: number)Duration

date.seconds

Returns a Duration of exactly n seconds.

date.seconds(n: number)Duration

date.minutes

Returns a Duration of exactly n minutes.

date.minutes(n: number)Duration

date.hours

Returns a Duration of exactly n hours.

date.hours(n: number)Duration

date.days

Returns a Duration of exactly n days (always 24 × 3600 seconds; not calendar-aware – use adddays on DateTime for wall-clock days).

date.days(n: number)Duration