radlang — Dates & Time (Date)

This document covers the built-in Date type: creating dates, reading their components, formatting, and parsing.

For language fundamentals see the Overview.


Overview

Date is a built-in value type — no import needed. Internally it holds a single millisecond timestamp (epoch, UTC), but you work with it through constructors and methods. All component getters (getHours, getDate, …) report values in local time.

fn main() {
    Date now = Date()                      // current date/time
    sys.output(now.toString())             // e.g. Wed Jul 08 2026 14:32:01
    sys.output(now.getFullYear())          // 2026
}

Creating a date

Date()                 : Date     // current date/time
Date.new()             : Date     // current date/time (alias of Date())
Date(ms: long)         : Date     // from an epoch-millisecond timestamp
Date(text: string)     : Date     // parse a date string
Date.now()             : long     // current time as raw epoch ms (NOT a Date)
Date.now.micro()       : long     // current time as raw epoch microseconds
Date.now.nano()        : long     // current time as raw epoch nanoseconds
  • Date() / Date.new() build a Date for the current moment.
  • Date(ms) builds a Date from a millisecond timestamp — round-trips with getTime().
  • Date(text) parses a string (see Parsing).
  • Date.now() returns the current time as a bare long (epoch ms), handy for timing/deltas without allocating a Date.
  • Date.now.micro() / Date.now.nano() return the current time as a bare long in microseconds / nanoseconds.
fn main() {
    Date a = Date()                        // now
    Date b = Date(0)                       // the epoch: 1970-01-01T00:00:00 UTC
    Date c = Date("2026-05-17")            // parsed
    long  t = Date.now()                   // e.g. 1783705921000
    long  us = Date.now.micro()            // e.g. 1783705921000234
    long  ns = Date.now.nano()             // e.g. 1783705921000234000

    sys.output(b.getTime())                // 0
    sys.output(c.getFullYear())            // 2026
}

Note. Date(ms) stores a UTC instant, but the component getters below report local time. So Date(0).getFullYear() is 1970 only in UTC/ahead timezones — west of UTC it reads 1969 (epoch 0 is 1969-12-31 locally). Use getTime() when you need the absolute, timezone-independent value.


Reading components

Each getter returns an int (except getTime, a long), in local time.

MethodReturnsRange / notes
getTime()longEpoch milliseconds
getFullYear()intFour-digit year, e.g. 2026
getMonth()int0–11 (0 = January)
getDate()intDay of month, 1–31
getDay()intDay of week, 0–6 (0 = Sunday)
getHours()int0–23
getMinutes()int0–59
getSeconds()int0–59
fn main() {
    Date d = Date("2026-05-17 09:30:00")
    sys.output(d.getFullYear())   // 2026
    sys.output(d.getMonth())      // 4   (May — zero-based!)
    sys.output(d.getDate())       // 17
    sys.output(d.getHours())      // 9
    sys.output(d.getMinutes())    // 30
}

Note. getMonth() is zero-based (January = 0, December = 11) and getDay() is the weekday starting at Sunday = 0 — matching JavaScript’s Date. Add 1 to getMonth() for a human month number.


Formatting

Default string form

date.toString()             : string
date.toLocaleDateString()   : string

Both render the date with the built-in format Www Mmm DD YYYY HH:MM:SS (e.g. Sun May 17 2026 09:30:00). This form round-trips: Date(d.toString()) parses back to the same instant.

fn main() {
    Date d = Date()
    sys.output(d.toString())    // Wed Jul 08 2026 14:32:01
}

Custom format

date.format(template: string) : string

Substitutes these tokens in template (everything else is copied verbatim):

TokenMeaningExample
YYYY4-digit year2026
MM2-digit month (1-based)05
dd2-digit day of month17
HH2-digit hour (24h)09
mm2-digit minute30
ss2-digit second00
zzz3-digit milliseconds042
fn main() {
    Date d = Date("2026-05-17 09:30:00")
    sys.output(d.format("YYYY-MM-dd"))            // 2026-05-17
    sys.output(d.format("dd/MM/YYYY HH:mm:ss"))   // 17/05/2026 09:30:00
    sys.output(d.format("YYYY-MM-ddTHH:mm:ss.zzz")) // 2026-05-17T09:30:00.000
}

Note. In format templates, MM is the 1-based month (unlike the zero-based getMonth()), and case matters: MM = month, mm = minute, HH = hour, ss = second, dd = day.


Parsing

Date(text) accepts these formats, tried in order:

  • Www Mmm DD YYYY HH:MM:SS — the toString() output (so it round-trips)
  • YYYY-MM-DDTHH:MM:SS — ISO 8601 datetime
  • YYYY-MM-DD HH:MM:SS — space-separated datetime
  • YYYY-MM-DD — bare ISO date (time defaults to local midnight)

An unrecognized string parses to epoch 0 (1970-01-01).

fn main() {
    Date d1 = Date("2026-05-17T09:30:00")
    Date d2 = Date("2026-05-17")            // 09:30 dropped → local midnight
    sys.output(d1.getHours())               // 9
    sys.output(d2.getHours())               // 0
}

Timing example

fn main() {
    long start = Date.now()
    sys.sleep(50)
    long elapsed = Date.now() - start
    sys.output("waited ~" + elapsed.toString() + " ms")
}

Quick reference

CallReturnsPurpose
Date() / Date.new()DateCurrent date/time
Date(ms)DateFrom epoch milliseconds
Date(text)DateParse a date string
Date.now()longCurrent time as epoch ms
Date.now.micro()longCurrent time as epoch microseconds
Date.now.nano()longCurrent time as epoch nanoseconds
date.getTime()longEpoch milliseconds
date.getFullYear()intYear
date.getMonth()intMonth, 0–11
date.getDate()intDay of month
date.getDay()intWeekday, 0–6 (Sun=0)
date.getHours/getMinutes/getSeconds()intTime components
date.toString() / toLocaleDateString()stringDefault formatted string
date.format(tmpl)stringCustom-formatted string

Picking the right tool

  • A wall-clock value you’ll read fields from → Date().
  • Just measuring elapsed time → Date.now() (raw long, no allocation).
  • Storing/transmitting a timestamp → getTime() (a long you can rebuild with Date(ms)).
  • Human-readable output → toString(), or format(...) for a specific layout.