datetime +linux +x86_64

The datetime module implements the common international "Gregorian" chronology, based on the astronomically numbered proleptic Gregorian calendar, as per ISO 8601, and the common 24 hour clock. It provides datetime, a representation of civil date/time and an extension of the time::chrono::moment type, optimized for dealing with the Gregorian chronology.

Datetimes are created with new, now, or with one of the various "from_" functions. Alternatively, use a builder to construct a datetime piece-by-piece, by field assignements or by parsing strings with parse. datetime

instances are designed to be always valid and internally consistent. They should be treated as immutable, and their fields as private. All functions herein return valid datetimes (or appropriate errors), and never modify a datetime's value, even if passed as a pointer, which is used only for internal caching. datetime

fields are accessed, evaluated, and cached via the various "field" functions (year, month, day, etc). Accessing or modifying a datetime's fields directly is discouraged. To mutate a datetime in code, the use of the builder interface is recommended. datetime

s may be localized to different time::chrono::timezones via the in function. The "field" functions will evaluate the correct values accordingly. You'll find a standard selection of world timezones in the time::chrono module.

To convert datetimes to and from strings, use parse and format.

For arithmetics, use diff, add and hop. Note that calendrical arithmetic is highly irregular with many edge cases, so think carefully about what you want.



type builder;
type calculus;
type period;
type strategy;
type unit;

// Undocumented types:
type datetime;


type insufficient;
type invalid;


const EMAIL: str;
const EMAILZ: str;
const EPOCHAL_JULIAN: i64;
const POSIX: str;
const RFC3339: str;
const STAMP: str;
const STAMP_NANO: str;
const STAMP_NOZL: str;


fn add(datetime, calculus, period...) datetime;
fn after(datetime, datetime) bool;
fn asformat(str, *datetime) (str | invalid | io::error);
fn before(datetime, datetime) bool;
fn bsformat([]u8, str, *datetime) (str | invalid | io::error);
fn day(*datetime) int;
fn diff(datetime, datetime) period;
fn epochal(*datetime) chrono::epochal;
fn eq(datetime, datetime) bool;
fn era(*datetime) int;
fn finish(*builder, strategy...) (datetime | insufficient | invalid);
fn format(io::handle, str, *datetime) (size | invalid | io::error);
fn from_instant(time::instant, chrono::locality) datetime;
fn from_moment(chrono::moment) datetime;
fn from_str(str, str) (datetime | insufficient | invalid);
fn hop(datetime, period...) datetime;
fn hour(*datetime) int;
fn in(chrono::locality, datetime) datetime;
fn is_leap_year(int) bool;
fn isoweek(*datetime) int;
fn isoweekyear(*datetime) int;
fn lookupzone(*datetime) chrono::zone;
fn min(*datetime) int;
fn month(*datetime) int;
fn new(chrono::locality, (time::duration | void), int...) (datetime | invalid);
fn newbuilder() builder;
fn now() datetime;
fn nsec(*datetime) int;
fn parse(*builder, str, str) (void | invalid);
fn period_eq(period, period) bool;
fn sec(*datetime) int;
fn sub(datetime, calculus, period...) datetime;
fn to_instant(datetime) time::instant;
fn to_moment(datetime) chrono::moment;
fn truncate(datetime, unit) datetime;
fn unitdiff(datetime, datetime, unit) i64;
fn week(*datetime) int;
fn weekday(*datetime) int;
fn year(*datetime) int;
fn yearday(*datetime) int;

// Undocumented functions:
fn transform(datetime, time::duration) datetime;


type builder[link]

type builder = datetime;

Constructs a new datetime. Start with newbuilder, then collect enough datetime information incrementally by direct field assignments and/or one or more calls to parse. Finish with finish.

let builder = datetime::newbuilder();
datetime::parse(&builder, "Year: %Y", "Year: 2038");
datetime::parse(&builder, "Month: %m", "Month: 01"); = 19;
let dt = datetime::finish(&builder, datetime::strategy::YMD);

type calculus[link]

type calculus = enum {
	// Units are added in the order of largest (years) to smallest
// (nanoseconds). If the resulting date does not exist, the first extant
// date previous to the initial result is returned.

Specifies the behaviour of calendar arithmetic.

type period[link]

type period = struct {
	eras: int,
	years: int,
	// Can be 28, 29, 30, or 31 days long
months: int, // Weeks start on Monday
weeks: int, days: int, hours: int, minutes: int, seconds: int, nanoseconds: i64, };

Represents a span of time in the proleptic Gregorian calendar, using relative units of time. Used for calendar arithmetic.

type strategy[link]

type strategy = enum uint {
	YMD = 1 << 0, // year, month, day
YD = 1 << 1, // year, yearday
YWD = 1 << 2, // year, week, weekday
ISOYWD = 1 << 4, // isoyear, isoweek, weekday
ALL = YMD | YD | YWD | ISOYWD, // all strategies, in order as presented here

Specifies which builder fields (and what strategy) to use to calculate the epochal, and thus a valid datetime.

type unit[link]

type unit = enum {


The various datetime units that can be used for arithmetic.

type datetime[link]

Show undocumented member
type datetime = struct {
	era: (void | int),
	year: (void | int),
	month: (void | int),
	day: (void | int),
	yearday: (void | int),
	isoweekyear: (void | int),
	isoweek: (void | int),
	week: (void | int),
	weekday: (void | int),
	hour: (void | int),
	min: (void | int),
	sec: (void | int),
	nsec: (void | int),


type insufficient[link]

type insufficient = !void;

A builder has insufficient information and cannot create a valid datetime.

type invalid[link]

type invalid = !chrono::invalid;

The given combination of date, time, and locality is invalid.


def EMAIL[link]

def EMAIL: str;

datetime::format string for the email date format.

def EMAILZ[link]

def EMAILZ: str;

datetime::format string for the email date format, with zone offset and zone abbreviation.



The Hare epoch of the Gregorian Common Era



The Hare epoch of the Julian Day Number

def POSIX[link]

def POSIX: str;

datetime::format string used by default for POSIX date(1).

def RFC3339[link]

def RFC3339: str;

datetime::format string compatible with RFC 3339.

def STAMP[link]

def STAMP: str;

datetime::format string for a simple timestamp.

def STAMP_NANO[link]

def STAMP_NANO: str;

datetime::format string for a simple timestamp with nanoseconds.

def STAMP_NOZL[link]

def STAMP_NOZL: str;

datetime::format string for a simple timestamp with nanoseconds, zone offset, zone abbreviation, and locality.


fn add[link]

fn add(dt: datetime, flag: calculus, pp: period...) datetime;

Adds a period of time to a datetime, most significant units first. Conserves relative distance from cyclical points on the calendar when possible. This can be used, for example, to find the date one year from now.

let dt = ... // 1999-05-13 12:30:45
datetime::add(dt, datetime::calculus::DEFAULT, datetime::period {
	years  = 22, // 2021-05-13 12:30:45
	months = -1, // 2021-04-13 12:30:45
	days   = -4, // 2020-04-09 12:30:45

fn after[link]

fn after(a: datetime, b: datetime) bool;

Returns true if the first date is after the second date.

fn asformat[link]

fn asformat(layout: str, dt: *datetime) (str | invalid | io::error);

Formats a datetime and writes it into a heap-allocated string. The caller must free the return value.

fn before[link]

fn before(a: datetime, b: datetime) bool;

Returns true if the first date is before the second date.

fn bsformat[link]

fn bsformat(buf: []u8, layout: str, dt: *datetime) (str | invalid | io::error);

Formats a datetime and writes it into a caller supplied buffer. The returned string is borrowed from this buffer.

fn day[link]

fn day(dt: *datetime) int;

Returns a datetime's day of the month

fn diff[link]

fn diff(a: datetime, b: datetime) period;

Calculates the difference between two datetimes.

fn epochal[link]

fn epochal(dt: *datetime) chrono::epochal;

Returns a datetime's number of days since the calendar epoch 0000-01-01

fn eq[link]

fn eq(a: datetime, b: datetime) bool;

Returns true if two dates are numerically equal.

fn era[link]

fn era(dt: *datetime) int;

Returns a datetime's era

fn finish[link]

fn finish(f: *builder, m: strategy...) (datetime | insufficient | invalid);

Returns a datetime from a builder. The provided strategys will be tried in order until a valid datetime is produced, or fail otherwise. The default strategy is strategy::ALL.

fn format[link]

fn format(h: io::handle, layout: str, dt: *datetime) (size | invalid | io::error);

Formats a datetime according to a layout and writes to an io::handle.

The layout may contain any of the following format specifiers listed below. Implemented are a subset of the POSIX strftime(3) format specifiers, as well as some others. Use of unimplemented specifiers or an otherwise invalid layout will cause an abort.

%% -- A literal '%' character.
%a -- The abbreviated name of the day of the week.
%A -- The full name of the day of the week.
%b -- The abbreviated name of the month.
%B -- The full name of the month.
%d -- The day of the month (decimal, range 01 to 31).
%H -- The hour of the day as from a 24-hour clock (range 00 to 23).
%I -- The hour of the day as from a 12-hour clock (range 01 to 12).
%j -- The ordinal day of the year (range 001 to 366).
%L -- The locality's name (the timezone's identifier).
%m -- The month (decimal, range 01 to 12).
%M -- The minute (decimal, range 00 to 59).
%N -- The nanosecond of the second (range 000000000 to 999999999).
%p -- Either "AM" or "PM" according to the current time.
      "AM" includes midnight, and "PM" includes noon.
%S -- The second of the minute (range 00 to 60).
%u -- The day of the week (decimal, range 1 to 7). 1 represents Monday.
%U -- The week number of the current year (range 00 to 53),
      starting with the first Sunday as the first day of week 01.
%w -- The day of the week (decimal, range 0 to 6). 0 represents Sunday.
%W -- The week number of the current year (range 00 to 53),
      starting with the first Monday as the first day of week 01.
%y -- The year without the century digits (range 00 to 99).
%Y -- The year.
%z -- The observed zone offset.
%Z -- The observed zone abbreviation.

fn from_instant[link]

fn from_instant(i: time::instant, loc: chrono::locality) datetime;

Creates a datetime from a time::instant.

fn from_moment[link]

fn from_moment(m: chrono::moment) datetime;

Creates a datetime from a time::chrono::moment.

fn from_str[link]

fn from_str(layout: str, s: str) (datetime | insufficient | invalid);

Creates a datetime from a string, parsed according to a layout, using strategy::ALL, or fails otherwise.

fn hop[link]

fn hop(dt: datetime, pp: period...) datetime;

Given a datetime and a period, "hops" to the minimum value of each field (years, months, days, etc) plus or minus an offset, and returns a new datetime. This can be used, for example, to find the start of last year.

Consults each period's fields from most to least significant (from years to nanoseconds).

If a field's value N is zero, nothing happens. Otherwise, hop will reckon to the Nth inter-period point from where last reckoned. This repeats until all the given period's fields are exhausted.

let dt = ... // 1999-05-13 12:30:45
datetime::hop(dt, datetime::period {
	years  = 22, // produces 2021-01-01 00:00:00
	months = -1, // produces 2020-11-01 00:00:00
	days   = -4, // produces 2020-10-27 00:00:00

fn hour[link]

fn hour(dt: *datetime) int;

Returns a datetime's hour of the day

fn in[link]

fn in(loc: chrono::locality, dt: datetime) datetime;

Transforms and creates a new datetime in a different time::chrono::locality.

fn is_leap_year[link]

fn is_leap_year(y: int) bool;

Calculates whether a given year is a leap year.

fn isoweek[link]

fn isoweek(dt: *datetime) int;

Returns a datetime's ISO week

fn isoweekyear[link]

fn isoweekyear(dt: *datetime) int;

Returns a datetime's ISO week-numbering year

fn lookupzone[link]

fn lookupzone(dt: *datetime) chrono::zone;

Finds and returns a datetime's currently observed zone.

fn min[link]

fn min(dt: *datetime) int;

Returns a datetime's minute of the hour

fn month[link]

fn month(dt: *datetime) int;

Returns a datetime's month of the year

fn new[link]

fn new(
	loc: chrono::locality,
	offs: (time::duration | void),
	fields: int...
) (datetime | invalid);

Creates a new datetime. When loc=void, defaults to chrono::local.

// 0000 Jan  1st 00:00:00.000000000 +0000 UTC
datetime::new(time::chrono::UTC, 0);

// 2038 Jan 19th 03:14:07.000000618 +0000 UTC
datetime::new(time::chrono::UTC, 0, 2038, 01, 19, 03, 14, 07, 618);

// 2038 Jan 19th 02:00:00.000000000 +0100 Europe/Amsterdam
datetime::new(&time::chrono::tz("Europe/Amsterdam"), 1 * time::HOUR,
	2038, 01, 19, 02);

'offs' is the zone offset from the normal timezone (in most cases, UTC). For example, the "Asia/Tokyo" timezone has a single zoffset of +9 hours, but the "Australia/Sydney" timezone has zoffsets +10 hours and +11 hours, as they observe Daylight Saving Time.

If specified (non-void), 'offs' must match one of the timezone's observed zoffsets, or will fail. See time::chrono::fixedzone for custom timezones.

You may omit the zoffset. If the givem timezone has a single zone, new will use that zone's zoffset. Otherwise new will try to infer the zoffset from the multiple zones. This will fail during certain timezone transitions, where certain datetimes are ambiguous or nonexistent. For example:

- In the Europe/Amsterdam timezone, at 1995 March 26th, the local time 02:30 was never observed, as the clock jumped forward 1 hour from 02:00 CET to 03:00 CEST.

- In the Europe/Amsterdam timezone, at 1995 September 24th, the local time 02:30 was observed twice (00:30 UTC & 01:30 UTC), as the clock jumped back 1 hour from 03:00 CEST to 02:00 CET.

fn newbuilder[link]

fn newbuilder() builder;

Creates a new builder

fn now[link]

fn now() datetime;

Returns a datetime for the immediate system time.

fn nsec[link]

fn nsec(dt: *datetime) int;

Returns a datetime's nanosecond of the second

fn parse[link]

fn parse(build: *builder, layout: str, s: str) (void | invalid);

Parses a datetime string into a builder, using a "layout" format string with a set of specifiers as documented under format. Partial, incremental parsing is possible.

datetime::parse(&builder, "%Y-%m-%d", "2038-01-19");
datetime::parse(&builder, "%H:%M:%S", "03:14:07");

fn period_eq[link]

fn period_eq(a: period, b: period) bool;

Returns true if two periods are numerically equal.

fn sec[link]

fn sec(dt: *datetime) int;

Returns a datetime's second of the minute

fn sub[link]

fn sub(dt: datetime, flag: calculus, pp: period...) datetime;

Subtracts a calendrical period of time to a datetime, most significant units first. Conserves relative distance from cyclical points on the calendar when possible.

let dt = ... // 1999-05-13 12:30:45
datetime::subtract(dt, datetime::calculus::DEFAULT, datetime::period {
	years  = 22, // 1977-05-13 12:30:45
	months = -1, // 1977-06-13 12:30:45
	days   = -4, // 1977-06-17 12:30:45

fn to_instant[link]

fn to_instant(dt: datetime) time::instant;

Creates a time::instant from a datetime.

fn to_moment[link]

fn to_moment(dt: datetime) chrono::moment;

Creates a time::chrono::moment from a datetime

fn truncate[link]

fn truncate(dt: datetime, u: unit) datetime;

Truncates the given datetime at the provided unit. For example, truncating to the nearest unit::YEAR will set the month, day, hour, minute, seconds, and nanoseconds fields to their minimum values.

fn unitdiff[link]

fn unitdiff(a: datetime, b: datetime, u: unit) i64;

Calculates the difference between two datetimes using the given unit, truncating towards zero.

fn week[link]

fn week(dt: *datetime) int;

Returns a datetime's Gregorian week

fn weekday[link]

fn weekday(dt: *datetime) int;

Returns a datetime's day of the week

fn year[link]

fn year(dt: *datetime) int;

Returns a datetime's year

fn yearday[link]

fn yearday(dt: *datetime) int;

Returns a datetime's ordinal day of the year

fn transform[link]

Show undocumented member
fn transform(dt: datetime, zo: time::duration) datetime;