Dates & time
Dates, time zones, formatting, and measuring time.
On this page
valk.time has DateTime for calendar dates, Duration for lengths of time, time zones, clocks and sleeping.
Create a date#
use valk.time
fn main() {
let date = time.DateTime.new(2026, 1, 15, 9, 30) ! {
println("Invalid date")
return
}
println(date) // 2026-01-15T09:30:00Z
println(date.year()) // 2026
println(date.day_of_week()) // 4
let midnight = time.DateTime.new(2026, 1, 1) ! return
let now = time.DateTime.now()
println(now > midnight) // true
}
DateTime is UTC unless it has a zone. Arguments are year, month, day, hour, minute, second and microsecond; the ones left out default to their minimum. An invalid date throws. Dates compare with ==, < and >.
| Read | Returns |
|---|---|
year() month() day() |
Calendar parts |
hour() minute() second() microsecond() |
Time parts |
day_of_week() |
1 (Monday) to 7 (Sunday) |
day_of_year(), is_leap_year() |
Position in the year |
unix_seconds(), unix_us() |
Unix timestamp |
DateTime.from_unix_seconds(ts) and from_unix_us(ts) go the other way.
Change a date#
use valk.time
fn main() {
let date = time.DateTime.new(2026, 1, 31) ! return
let later = date.add_months(1) ! return
println(later.format("Y-m-d")) // 2026-02-28
let first = date.with_day(1) ! return
println(first.format("Y-m-d")) // 2026-01-01
date.modify_add_days(1) ! return
println(date.format("Y-m-d")) // 2026-02-01
}
add_years,add_months,add_days,add_hours,add_minutes,add_seconds,add_microsecondsreturn a new date; amounts may be negative.with_year,with_month,with_day,with_hour, ... return a copy with one part replaced.modify_add_*andmodify_*change the date itself.
Format and parse#
use valk.time
fn main() {
let date = time.DateTime.from_format("Y-m-d H:i", "2026-03-01 14:30") ! {
println("Invalid date text")
return
}
println(date.format("d/m/Y H:i")) // 01/03/2026 14:30
println(date.format("l j F Y, g A")) // Sunday 1 March 2026, 2 PM
println(date.to_iso8601()) // 2026-03-01T14:30:00Z
let parsed = time.DateTime.from_iso8601("2026-03-01T14:30:00+02:00") ! return
println(parsed.in_utc() !? parsed) // 2026-03-01T12:30:00Z
}
from_format reads text with the same tokens format writes, and throws when the text does not match. Put a \ before a letter to write it as is: "Y-m-d\\TH:i".
| Token | Meaning | Token | Meaning |
|---|---|---|---|
Y / y |
Year, 2026 / 26 | H / G |
Hour 00-23 / 0-23 |
m / n |
Month 01 / 1 | h / g |
Hour 01-12 / 1-12 |
M / F |
Jan / January | A / a |
AM / am |
d / j |
Day 05 / 5 | i / s |
Minute / second |
D / l |
Mon / Monday | v / u |
Milliseconds / microseconds |
N |
Weekday 1-7 | O / P |
Offset +0100 / +01:00 |
U |
Unix seconds | T |
Zone abbreviation |
Durations#
use valk.time
fn main() {
let start = time.DateTime.new(2026, 5, 1, 9) ! return
let end = time.DateTime.new(2026, 5, 1, 10, 30) ! return
let took = end - start
println(took.to_string()) // 1h30m
println(took.minutes()) // 90
println(took > time.Duration.of_minutes(45)) // true
let deadline = start.add(time.Duration.of_hours(2)) ! return
println(deadline) // 2026-05-01T11:00:00Z
}
Subtracting two dates gives a Duration. Make one with Duration.of_days, of_hours, of_minutes, of_seconds, of_ms or of_us, and read it back with days(), hours(), ... ms() or seconds_float(). Durations add, subtract and compare with the usual operators.
Time zones#
use valk.time
fn main() {
let amsterdam = time.zone("Europe/Amsterdam") ! {
println("Unknown zone")
return
}
let meeting = time.DateTime.new_in(amsterdam, 2026, 3, 30, 9) ! return
println(meeting) // 2026-03-30T09:00:00+02:00
println(meeting.zone_abbreviation()) // CEST
println(meeting.in_utc() !? meeting) // 2026-03-30T07:00:00Z
let new_york = time.zone("America/New_York") ! return
println(meeting.in_zone(new_york) !? meeting) // 2026-03-30T03:00:00-04:00
}
time.zone takes an IANA zone name. The same instant compares equal in any zone. add_days, add_months and with_* keep the wall-clock time across daylight saving changes; add_hours and smaller units count elapsed time.
DateTime.now_in(zone)andfrom_format_in(zone, pattern, text)work in a zone.time.local_zone()is the zone of the machine (theTZvariable, then the system settings).time.utc()andtime.fixed_zone(3600)give zones without daylight saving.utc_offset()andis_dst()describe a date in its zone.
Sleep#
use valk.time
fn main() {
time.sleep_ms(10)
time.sleep(time.Duration.of_ms(10))
println("done")
}
Sleeping pauses only the current coroutine; other coroutines keep running. sleep_ns takes nanoseconds.
Measure elapsed time#
use valk.time
fn main() {
let start = time.mono_ms()
time.sleep_ms(20)
let elapsed = time.mono_ms() - start
println(elapsed >= 20) // true
}
mono_ms, mono_us and mono_ns read a monotonic clock: it only moves forward, even when the system clock changes, so use it for durations. unix_ms, unix_us and unix_ns return wall-clock time since 1970.

