time::date
The time::date module implements the common international Gregorian chronology, based on the astronomically numbered proleptic Gregorian calendar and the ISO week-numbering calendar, as per the ISO 8601 standard, and the common 24 hour clock. It provides date, a representation of civil date/time and a optimized extension of the time::chrono::moment type.
The time::chrono:: module has many useful functions which interoperate with dates. Any time::chrono:: function which accepts *moment also accepts *date.
Dates are created using new, now, localnow, or a "from_" function. Alternatively, the virtual+realize interface can handle indeterminate date/time information, and construct new dates incrementally and safely.
The observer functions (year, hour, etc.) evaluate a date's observed chronological values, adjusted for its associated locality. Use in to localize a date to another locality. Consult your system's timezone database using tzdb.
For working with date/time strings, see parse and format.
Date arithmetic is categorized into two:
Chronologies are irregular due to field overflows and timezone discontinuities. These effects are mitigated with zflag and rflag, which deserve careful consideration.
Index
Types
type date = struct {
chrono::moment,
loc: locality,
zonephase: nullable *zonephase,
daydate: (void | i64),
daytime: (void | i64),
era: (void | int),
year: (void | int),
month: (void | int),
day: (void | int),
yearday: (void | int),
isoweekyear: (void | int),
isoweek: (void | int),
week: (void | int),
sundayweek: (void | int),
weekday: (void | int),
hour: (void | int),
minute: (void | int),
second: (void | int),
nanosecond: (void | int),
};
type locality = *timezone;
type petz = struct {
std_abbr: str,
std_offset: time::duration,
dst_abbr: str,
dst_offset: time::duration,
dst_startdate: petz_ruledate,
dst_starttime: time::duration,
dst_enddate: petz_ruledate,
dst_endtime: time::duration,
};
type rflag = enum uint {
DEFAULT = 0, REVSIG = 1 << 0, FLOOR = 1 << 1,
CEIL = 1 << 2,
HOP = 1 << 3,
FOLD = 1 << 4,
};
type span = struct {
years: i64,
months: i64,
weeks: i64,
days: i64,
hours: i64,
minutes: i64,
seconds: i64,
nanoseconds: i64,
};
type step = enum {
NANOSECOND = 1,
SECOND = 2,
MINUTE = 4,
HOUR = 8,
DAY = 16,
WEEK = 32,
MONTH = 64,
YEAR = 128,
ERA = 256,
};
type timezone = struct {
tsc: *chrono::timescale,
name: str,
daylength: time::duration,
phases: []zonephase,
transitions: []zonetransition,
lookupzone: nullable *zonelookuper,
petz: petz,
};
type virtual = struct {
date,
vsec: (void | i64),
vnsec: (void | i64),
vloc: (void | locality),
locname: (void | str),
zoff: (void | time::duration | zflag),
zabbr: (void | str),
century: (void | int),
year100: (void | int),
hour12: (void | int),
ampm: (void | bool),
};
type zflag = enum u8 {
CONTIG = 0,
LAP_EARLY = 1,
LAP_LATE = 2,
GAP_START = 4,
GAP_END = 8,
};
type zonelookuper = fn(locality, *date) *zonephase;
type zonephase = struct {
zoff: time::duration,
name: str,
abbr: str,
dst: bool,
};
type zonetransition = struct {
when: time::instant,
zoneindex: size,
};
type petz_ruledate = (petz_ruledate_julian | petz_ruledate_ordinal | petz_ruledate_weekdate);
type petz_ruledate_julian = i16;
type petz_ruledate_ordinal = i16;
type petz_ruledate_weekdate = (u8, u8, u8);
type zferror = enum {
GAP,
LAP,
};
Errors
type error = !(invalid | insufficient | zfunresolved | parsefail | invalidtzif | tzdberror | chrono::tscmismatch);
type insufficient = !void;
type invalid = !void;
type invalidpetzstr = !void;
type invalidtzif = !void;
type parsefail = !(size, rune);
type tzdberror = !(invalidtzif | fs::error | io::error);
type zfunresolved = !zferror;
Constants
def APRIL: int = 4;
def AUGUST: int = 8;
def DECEMBER: int = 12;
def EARTH_DAY: time::duration = 86400 * time::SECOND;
def EMAIL: str = "%a, %d %b %Y %H:%M:%S %z";
def EMAILZONE: str = "%a, %d %b %Y %H:%M:%S %z %Z";
def EPOCHDAY_GREGORIAN: i64 = -719164;
def EPOCHDAY_JULIAN: i64 = -2440588;
def FEBRUARY: int = 2;
def FRIDAY: int = 4;
def ISOWKSTAMP: str = "%G-W%V-%u %H:%M:%S";
def JANUARY: int = 1;
def JOURNAL: str = "%Y %b %d, %a %H:%M:%S %z %Z %L";
def JULY: int = 7;
def JUNE: int = 6;
def LOCALTIME_PATH: str = "/etc/localtime";
def MARCH: int = 3;
def MARS_SOL_MARTIAN: time::duration = 86400 * time::SECOND;
def MARS_SOL_TERRESTRIAL: time::duration = 88775244147000 * time::NANOSECOND;
def MAY: int = 5;
def MONDAY: int = 0;
def NOVEMBER: int = 11;
def OCTOBER: int = 10;
def POSIX: str = "%a %b %e %H:%M:%S %Y";
def QUARTZ: str = "%s.%N";
def QUARTZLOC: str = "%s.%N:%L";
def QUARTZZOFF: str = "%s.%N%z";
def RFC3339: str = "%Y-%m-%dT%H:%M:%S%z";
def SATURDAY: int = 5;
def SEPTEMBER: int = 9;
def STAMP: str = "%Y-%m-%d %H:%M:%S";
def STAMPLOC: str = "%Y-%m-%d %H:%M:%S.%N %z %Z %L";
def STAMPNANO: str = "%Y-%m-%d %H:%M:%S.%N";
def STAMPZOFF: str = "%Y-%m-%d %H:%M:%S.%N %z";
def STAMPZONE: str = "%Y-%m-%d %H:%M:%S.%N %z %Z";
def SUNDAY: int = 6;
def THURSDAY: int = 3;
def TUESDAY: int = 1;
def TZDB_PATH: str = "/usr/share/zoneinfo";
def WEDNESDAY: int = 2;
def WRIST: str = "%b-%d %a %H:%M %Z";
Globals
const GPS: locality;
const LOCAL: locality;
const MTC: locality;
const TAI: locality;
const TT: locality;
const UTC: locality;
Functions
fn abs(x: span) span;
fn add(d: date, x: time::duration) date;
fn asformat(layout: str, d: *date) (str | io::error);
fn bsformat(buf: []u8, layout: str, d: *date) (str | io::error);
fn coincident(a: *date, b: *date) bool;
fn day(d: *date) int;
fn daydate(d: *date) i64;
fn daytime(d: *date) i64;
fn equalspan(x: span, y: span) bool;
fn era(d: *date) int;
fn fixedzone(tsc: *chrono::timescale, name: str, daylen: time::duration, z: zonephase) *timezone;
fn format(h: io::handle, layout: str, d: *date) (size | io::error);
fn formatspan(s: span, sep: rune = ' ') str;
fn from_datetime(loc: locality, zo: time::duration, dd: i64, dt: i64) date;
fn from_instant(loc: locality, t: time::instant) date;
fn from_moment(loc: locality, m: chrono::moment) (date | chrono::tscmismatch);
fn from_str(layout: str, s: str, locs: locality...) (date | parsefail | insufficient | invalid);
fn hop(a: date, b: date, u: step) i64;
fn hour(d: *date) int;
fn in(loc: locality, d: date) (date | chrono::tscmismatch);
fn isleapyear(y: int) bool;
fn isoweek(d: *date) int;
fn isoweekyear(d: *date) int;
fn load_tzif(h: io::handle, tz: *timezone) (void | invalidtzif | io::error);
fn localnow() date;
fn minute(d: *date) int;
fn month(d: *date) int;
fn nanosecond(d: *date) int;
fn neg(x: span) span;
fn new(loc: locality, zoff: (time::duration | zflag), fields: int...) (date | invalid | zfunresolved);
fn newvirtual() virtual;
fn now() date;
fn parse(v: *virtual, layout: str, info: str) (void | parsefail);
fn realize(v: virtual, locs: locality...) (date | insufficient | invalid | zfunresolved);
fn reckon(d: date, zoff: (time::duration | zflag), rf: rflag, spans: span...) (date | invalid | zfunresolved);
fn second(d: *date) int;
fn strerror(err: error) const str;
fn sum(spans: span...) span;
fn sundayweek(d: *date) int;
fn timezone_free(tz: *timezone) void;
fn to_instant(d: date) time::instant;
fn to_moment(d: date) chrono::moment;
fn traverse(a: date, b: date) span;
fn truncate(d: date, zf: zflag, u: step) (date | invalid | zfunresolved);
fn tzdb(tzid: str) (locality | tzdberror);
fn week(d: *date) int;
fn weekday(d: *date) int;
fn year(d: *date) int;
fn yearday(d: *date) int;
fn zone(d: *date) zonephase;
fn zone_finish(z: *zonephase) void;
Types
type date
type date = struct {
chrono::moment,
loc: locality,
zonephase: nullable *zonephase,
daydate: (void | i64),
daytime: (void | i64),
era: (void | int),
year: (void | int),
month: (void | int),
day: (void | int),
yearday: (void | int),
isoweekyear: (void | int),
isoweek: (void | int),
week: (void | int),
sundayweek: (void | int),
weekday: (void | int),
hour: (void | int),
minute: (void | int),
second: (void | int),
nanosecond: (void | int),
};
A "datetime" object, optimized for the Gregorian chronology. All instantiated dates are valid, pertain to a locality, and directly convertible to a time::chrono::moment or time::instant.
A date observes various chronological values, which are cached in its "observer" fields. To evaluate and obtain these values, use the various observer functions, documented inline.
Unless interfaced via a virtual, dates should be treated as immutable. Mutating or interrogating fields directly results in undefined behaviour.
type locality
type locality = *timezone;
The locality of a date. Contains information about how to calculate a moment's observed chronological values.
type petz
type petz = struct {
std_abbr: str,
std_offset: time::duration,
dst_abbr: str,
dst_offset: time::duration,
dst_startdate: petz_ruledate,
dst_starttime: time::duration,
dst_enddate: petz_ruledate,
dst_endtime: time::duration,
};
A POSIX "extending timezone" of the "TZ" environment variable format. Used for extending calculations beyond the last known transition.
Example PETZ in string form: "CET-1CEST,M3.5.0,M10.5.0/3".
type rflag
type rflag = enum uint {
DEFAULT = 0, REVSIG = 1 << 0, FLOOR = 1 << 1,
CEIL = 1 << 2,
HOP = 1 << 3,
FOLD = 1 << 4,
};
Specifies the behaviour of reckon when doing chronological arithmetic.
The FLOOR, CEIL, HOP, and FOLD specifies how to resolve sub-significant overflows -- when a field's change in value causes any sub-significant field's range to shrink below its current value and become invalid. For example, adding 1 month to January 31st results in February 31st, a date with an unresolved day field, since February permits only 28 or 29 days.
type span
type span = struct {
years: i64,
months: i64,
weeks: i64,
days: i64,
hours: i64,
minutes: i64,
seconds: i64,
nanoseconds: i64,
};
Represents a span of time in the Gregorian chronology; a set of nominal periods of time. Used for chronological arithmetic.
type step
type step = enum {
NANOSECOND = 1,
SECOND = 2,
MINUTE = 4,
HOUR = 8,
DAY = 16,
WEEK = 32,
MONTH = 64,
YEAR = 128,
ERA = 256,
};
Nominal unitary periods of the Gregorian chronology. Used for chronological arithmetic.
type timezone
type timezone = struct {
tsc: *chrono::timescale,
name: str,
daylength: time::duration,
phases: []zonephase,
transitions: []zonetransition,
lookupzone: nullable *zonelookuper,
petz: petz,
};
A timezone; a political or otherwise theoretical region with a ruleset regarding offsets for calculating localized date/time.
type virtual
type virtual = struct {
date,
vsec: (void | i64),
vnsec: (void | i64),
vloc: (void | locality),
locname: (void | str),
zoff: (void | time::duration | zflag),
zabbr: (void | str),
century: (void | int),
year100: (void | int),
hour12: (void | int),
ampm: (void | bool),
};
A virtual date of undetermined validity; a date wrapper interface. It is meant as an intermediary container for date information to be resolved with the realize function.
A virtual date's "observer" fields (including that of the embedded date) should be treated as writable. The realize function takes into account all these fields, except for the embedded time::chrono::moment and locality fields (.sec .nsec .tsc .loc).
This can be used to safely construct a new date piece-by-piece. Start with newvirtual, then collect enough date/time information incrementally by direct field assignments and/or with parse. Finish with realize.
let v = date::newvirtual();
v.vloc = chrono::tz("Europe/Amsterdam")!;
v.zoff = date::zflag::LAP_EARLY | date::zflag::GAP_END;
date::parse(&v, "Date: %Y-%m-%d", "Date: 2000-01-02")!;
v.hour = 15;
v.minute = 4;
v.second = 5;
v.nanosecond = 600000000;
let d = date::realize(v)!;
Virtual date behaviour with the observer functions is undefined.
type zflag
type zflag = enum u8 {
CONTIG = 0,
LAP_EARLY = 1,
LAP_LATE = 2,
GAP_START = 4,
GAP_END = 8,
};
Flags for resolving undetermined zone-offsets. Handles timezone transitions.
The realize function, as well as other date creation functions (e.g. new, truncate, reckon) accept zflags in place of a numerical zone-offset. If zflags are provided, these functions first calculate an intermediate date with a reasonable numerical zone-offset, usually some preexisting one or a best guess using some locality.
This intermediate date can be invalid if it falls within the observed gap or overlap of a timezone transition, where such dates are ambiguous or nonexistent. In this case, the provided zflags are consulted, and a final adjustment takes place before the final resultant date with a new zone-offset (or zfunresolved) is returned.
Timezone transitions create gaps and overlaps, the two causes of invalid intermediate dates. Passing one "GAP_" and one "LAP_" flag covers both cases.
let zf = date::zflag::LAP_EARLY | date::zflag::GAP_END;
date::new(loc, zf, fields...)!; // will never return [[zfunresolved]]
Note, "GAP_" flags will cause the resultant date to be different to the intermediate date if it falls within a gap.
Flags with greater value take precedent.
The following figures exist to help understand the effect of these flags.
Fig A 2000 October 29th
-1 hour
f=02:30+0200
g=02:30+0100
lp | lq
+0200 | | | +0100
Observed time: 00 01 02 | 03 04 05
Amsterdam: |-----|-----|==*==|-----|-----|
. . .\ :: |. .
. . . \: :| . .
. . . : : . .
. . . :\ |: . .
. . . : \| : . .
UTC: |-----|-----|--*--|--*--|-----|
Contiguous time: 22 23 00 | 01 | 02 03
| | |
a tx b
Fig A -- A backjump timezone transition in the Europe/Amsterdam locality. The transition is marked by "tx". There is an overlap in the chronology, marked by "lp" and "lq". The specified local time 02:30 falls within the observed overlap, and so has two valid zone-offsets and can be observed twice, as dates "f" and "g". When localized to UTC, these two observations correspond to UTC dates "a" and "b" respectively.
Fig B 2000 March 26th
+1 hour
f~02:30+!!!!
gp | gq
+0100 | | | +0200
Observed time: 00 01 02 | 03 04 05
Amsterdam: |-----|-----| * |-----|-----|
. . | / . .
. . | / . .
. . | / . .
. . | / . .
. . |/ . .
UTC: |-----|-----|-----|-----|-----|
Contiguous time: 23 00 01 02 03 04
|
tx
Fig B -- A forejump timezone transition in the Europe/Amsterdam locality. The transition is marked by "tx". There is a gap in the chronology, marked by "gp" and "gq". The specified local time 02:30 falls within the observed gap, and so cannot be observed and is invalid.
type zonelookuper
type zonelookuper = fn(locality, *date) *zonephase;
Determines the correct zonephase to observe for a given date.
type zonephase
type zonephase = struct {
zoff: time::duration,
name: str,
abbr: str,
dst: bool,
};
A timezone state, with an offset for calculating localized date/time.
type zonetransition
type zonetransition = struct {
when: time::instant,
zoneindex: size,
};
A timezone transition between two zonephases.
type petz_ruledate
Show undocumented member
type petz_ruledate = (petz_ruledate_julian | petz_ruledate_ordinal | petz_ruledate_weekdate);
type petz_ruledate_julian
Show undocumented member
type petz_ruledate_julian = i16;
type petz_ruledate_ordinal
Show undocumented member
type petz_ruledate_ordinal = i16;
type petz_ruledate_weekdate
Show undocumented member
type petz_ruledate_weekdate = (u8, u8, u8);
type zferror
Show undocumented member
type zferror = enum {
GAP,
LAP,
};
Errors
type error
type error = !(invalid | insufficient | zfunresolved | parsefail | invalidtzif | tzdberror | chrono::tscmismatch);
All possible errors returned from this module.
type insufficient
type insufficient = !void;
A virtual date does not have enough information from which to create a valid date.
type invalid
type invalid = !void;
Invalid date.
type invalidpetzstr
type invalidpetzstr = !void;
Invalid POSIX extending TZ string.
type invalidtzif
type invalidtzif = !void;
Invalid TZif data.
type parsefail
type parsefail = !(size, rune);
A parsing error occurred. This shall contain a byteindex of and rune from the layout at the position where the parsing error occured.
type tzdberror
type tzdberror = !(invalidtzif | fs::error | io::error);
Error concerning the Timezone database.
type zfunresolved
type zfunresolved = !zferror;
Failed to resolve an absent zone-offset. The provided zflags failed to account for some timezone effect and could not produce a valid zone-offset.
Constants
def APRIL
def APRIL: int = 4;
Ordinal for the month of April.
def AUGUST
def AUGUST: int = 8;
Ordinal for the month of August.
def DECEMBER
def DECEMBER: int = 12;
Ordinal for the month of December.
def EARTH_DAY
def EARTH_DAY: time::duration = 86400 * time::SECOND;
The duration of a day on Earth, in terrestrial (SI) seconds.
def EMAIL
def EMAIL: str = "%a, %d %b %Y %H:%M:%S %z";
format layout for the email date format.
def EMAILZONE
def EMAILZONE: str = "%a, %d %b %Y %H:%M:%S %z %Z";
format layout for the email date format, with zone offset and zone abbreviation.
def EPOCHDAY_GREGORIAN
def EPOCHDAY_GREGORIAN: i64 = -719164;
The Hare epochal day of the Gregorian Common Era.
def EPOCHDAY_JULIAN
def EPOCHDAY_JULIAN: i64 = -2440588;
The Hare epochal day of the Julian Day Number.
def FEBRUARY
def FEBRUARY: int = 2;
Ordinal for the month of February.
def FRIDAY
def FRIDAY: int = 4;
Ordinal for the weekday Friday.
def ISOWKSTAMP
def ISOWKSTAMP: str = "%G-W%V-%u %H:%M:%S";
format layout for an ISO week-numbering timestamp.
def JANUARY
def JANUARY: int = 1;
Ordinal for the month of January.
def JOURNAL
def JOURNAL: str = "%Y %b %d, %a %H:%M:%S %z %Z %L";
format layout for a friendly, comprehensive datetime.
def JULY
def JULY: int = 7;
Ordinal for the month of July.
def JUNE
def JUNE: int = 6;
Ordinal for the month of June.
def LOCALTIME_PATH
def LOCALTIME_PATH: str = "/etc/localtime";
The filepath of the system's "localtime" file, typically a symlink to a TZif file under TZDB_PATH.
def MARCH
def MARCH: int = 3;
Ordinal for the month of March.
def MARS_SOL_MARTIAN
def MARS_SOL_MARTIAN: time::duration = 86400 * time::SECOND;
The duration of a solar day on Mars, in Martian seconds.
def MARS_SOL_TERRESTRIAL
def MARS_SOL_TERRESTRIAL: time::duration = 88775244147000 * time::NANOSECOND;
The duration of a solar day on Mars, in terrestrial (SI) seconds.
def MAY
def MAY: int = 5;
Ordinal for the month of May.
def MONDAY
def MONDAY: int = 0;
Ordinal for the weekday Monday.
def NOVEMBER
def NOVEMBER: int = 11;
Ordinal for the month of November.
def OCTOBER
def OCTOBER: int = 10;
Ordinal for the month of October.
def POSIX
def POSIX: str = "%a %b %e %H:%M:%S %Y";
format layout for the POSIX locale's default date & time representation.
def QUARTZ
def QUARTZ: str = "%s.%N";
format layout for a precise timescalar second and nanosecond.
def QUARTZLOC
def QUARTZLOC: str = "%s.%N:%L";
format layout for a precise timescalar second, nanosecond, and locality.
def QUARTZZOFF
def QUARTZZOFF: str = "%s.%N%z";
format layout for a precise timescalar second, nanosecond, and zone offset.
def RFC3339
def RFC3339: str = "%Y-%m-%dT%H:%M:%S%z";
format layout compatible with RFC 3339.
def SATURDAY
def SATURDAY: int = 5;
Ordinal for the weekday Saturday.
def SEPTEMBER
def SEPTEMBER: int = 9;
Ordinal for the month of September.
def STAMP
def STAMP: str = "%Y-%m-%d %H:%M:%S";
format layout for a standard, collatable timestamp.
def STAMPLOC
def STAMPLOC: str = "%Y-%m-%d %H:%M:%S.%N %z %Z %L";
format layout for a standard, collatable timestamp with nanoseconds, zone offset, zone abbreviation, and locality.
def STAMPNANO
def STAMPNANO: str = "%Y-%m-%d %H:%M:%S.%N";
format layout for a standard, collatable timestamp with nanoseconds.
def STAMPZOFF
def STAMPZOFF: str = "%Y-%m-%d %H:%M:%S.%N %z";
format layout for a standard, collatable timestamp with nanoseconds and zone offset.
def STAMPZONE
def STAMPZONE: str = "%Y-%m-%d %H:%M:%S.%N %z %Z";
format layout for a standard, collatable timestamp with nanoseconds, zone offset, and zone abbreviation.
def SUNDAY
def SUNDAY: int = 6;
Ordinal for the weekday Sunday.
def THURSDAY
def THURSDAY: int = 3;
Ordinal for the weekday Thursday.
def TUESDAY
def TUESDAY: int = 1;
Ordinal for the weekday Tuesday.
def TZDB_PATH
def TZDB_PATH: str = "/usr/share/zoneinfo";
The filepath of the system's TZDB (Timezone Database) directory, a filetree of TZif (Time Zone Information Format) files and other related files.
def WEDNESDAY
def WEDNESDAY: int = 2;
Ordinal for the weekday Wednesday.
def WRIST
def WRIST: str = "%b-%d %a %H:%M %Z";
format layout for a friendly, terse datetime.
Globals
let LOCAL
const LOCAL: locality;
The local locality; the system or environment configured timezone.
This is set during the program's initialization. In order of preference, the TZ environment variable is used, if set; the file at LOCALTIME_PATH, if present; or, as a last resort, UTC is used as a default.
Functions
fn abs
fn abs(x: span) span;
Returns a span with its fields made absolute and positive.
fn asformat(layout: str, d: *date) (str | io::error);
Formats a date and writes it into a heap-allocated string. The caller must free the return value.
fn bsformat(buf: []u8, layout: str, d: *date) (str | io::error);
Formats a date and writes it into a caller supplied buffer. The returned string is borrowed from this buffer.
fn coincident
fn coincident(a: *date, b: *date) bool;
Returns true if two dates represent the same time in the same locality, which is to say that their locality and time::instant are both equal. Their observed chronological values should be the same in all cases.
See time::chrono::compare.
fn day
fn day(d: *date) int;
Observes a date's day of the month. Range 1 to 31.
fn daydate
fn daydate(d: *date) i64;
Observes a date's observed daydate (day number since epoch).
For dates with a locality based on the UTC, TAI, GPS, and similar time::chrono::timescales, their epoch date should be interpreted as the Unix epoch (1970 Janurary 1st). Other timescales may suggest their own interpretations applicable to other chronologies.
fn daytime
fn daytime(d: *date) i64;
Observes a date's observed time-of-day (amount of daytime progressed in a day) as nanoseconds.
fn equalspan
fn equalspan(x: span, y: span) bool;
Returns true if two spans are numerically equal, false otherwise.
fn era
fn era(d: *date) int;
Observes a date's era.
fn fixedzone
fn fixedzone(tsc: *chrono::timescale, name: str, daylen: time::duration, z: zonephase) *timezone;
Creates a timezone with a single zonephase. Useful for fixed offsets. The caller must free the return value with timezone_free. An example, replicate the civil time Hawaii timezone on Earth:
let hawaii = chrono::fixedzone(
&chrono::utc,
"Custom/Hawaiian_Reef",
chrono::EARTH_DAY,
chrono::zonephase {
zoff = -10 * time::HOUR,
abbr = "HARE",
dst = false,
...
},
);
fn format(h: io::handle, layout: str, d: *date) (size | io::error);
Formats a date according to a layout and writes to an io::handle.
The layout may contain any of the following format specifiers listed below. These specifiers emit 2 digit zero-padded decimals unless stated otherwise. Use of unimplemented specifiers or an invalid layout will cause an abort.
- %% : A single literal '%' character.
- %a : The day of the week, abbreviated name. ("Sun").
- %A : The day of the week, full name. ("Sunday").
- %b : The month, abbreviated name. ("Jan").
- %B : The month, full name. ("January").
- %C : The century (the year without the last 2 digits). ("20").
- %d : The day of the month. Range 01 to 31. ("02").
- %e : The day of the month. Range 1 to 31, right-aligned, space-padded. (" 2").
- %F : The full Gregorian calendar date. Alias for "%Y-%m-%d". ("2000-01-02").
- %G : The ISO week-numbering year. At least 4 digits. ISO-years before the Common Era have a minus sign prefix. ("1999").
- %H : The hour of the day of a 24-hour clock. Range 00 to 23. ("15").
- %I : The hour of the day of a 12-hour clock. Range 01 to 12. ("03").
- %j : The ordinal day of the year. 3 digits, range 001 to 366. ("002").
- %L : The locality's name (the timezone identifier). ("Europe/Amsterdam").
- %m : The month of the year. Range 01 to 12. ("01").
- %M : The minute of the hour. Range 00 to 59. ("04").
- %N : The nanosecond of the second. 9 digits, range 000000000 to 999999999. ("600000000").
- %p : The meridian indicator, either "AM" or "PM". "AM" includes midnight, and "PM" includes noon.
- %s : The number of seconds since the locality's epoch. ("946821845").
- %S : The second of the minute. Range 00 to 59. ("05").
- %T : The wall-time of a 24-hour clock without nanoseconds. Alias for "%H:%M:%S". ("15:04:05").
- %u : The day of the week. 1 digit, range 1 to 7, Monday to Sunday. ("7").
- %U : The sunday-week of the year. Range 00 to 53. The year's first Sunday is the first day of week 01. ("01").
- %V : The week of the ISO week-numbering year. Range 01 to 53. ("52").
- %w : The day of the sunday-week. 1 digit, range 0 to 6, Sunday to Saturday. ("0").
- %W : The week of the year. Range 00 to 53. The year's first Monday is the first day of week 01. ("00").
- %y : The year's last 2 digits, no century digits. Range 00 to 99. ("00").
- %Y : The year. At least 4 digits. Years before the Common Era have a minus sign prefix. ("2000").
- %z : The observed zone offset. ("+0100").
- %Z : The observed zone abbreviation. ("CET").
fn formatspan(s: span, sep: rune = ' ') str;
Formats a span and writes it into an internal static buffer. The returned string is borrowed from this buffer. The following layout is used:
"?Y ?M ?W ?D ?h ?m ?s ?n"
where each '?' is replaced with the appopriate span field values in order of decreasing significance, and the inbetween spaces are replaced with the given sep argument.
fn from_datetime
fn from_datetime(loc: locality, zo: time::duration, dd: i64, dt: i64) date;
Creates a date from a given locality, zone-offset, daydate, and time-of-day.
fn from_str
fn from_str(layout: str, s: str, locs: locality...) (date | parsefail | insufficient | invalid);
Creates a date from a string, parsed according to a layout format. See parse and format. Example:
let new = date::from_str(
date::STAMPLOC,
"2000-01-02 15:04:05.600000000 +0100 CET Europe/Amsterdam",
chrono::tz("Europe/Amsterdam")!
)!;
At least a complete calendar date has to be provided. If the hour, minute, second, or nanosecond values are not provided, they default to 0. If the zone-offset or zone-abbreviation are not provided, the zflags LAP_EARLY and GAP_END are used.
The date's locality will be selected from the provided locality arguments. The 'name' field of these localities will be matched against the parsed result of the %L specifier. If %L is not specified, or if no locality is provided, UTC is used.
fn hop
fn hop(a: date, b: date, u: step) i64;
Calculates the nominal step difference between two dates.
Be aware, using date of different localitys may return unexpected results.
fn hour
fn hour(d: *date) int;
Observes a date's hour of the day.
fn isleapyear
fn isleapyear(y: int) bool;
Calculates whether a year is a leap year.
fn isoweek
fn isoweek(d: *date) int;
Observes a date's ISO week-numbering week. Range 0 to 53.
fn isoweekyear
fn isoweekyear(d: *date) int;
Observes a date's ISO week-numbering year.
fn load_tzif
fn load_tzif(h: io::handle, tz: *timezone) (void | invalidtzif | io::error);
Loads TZif (Time Zone Information Format) data onto a given timezone, initializing the fields ".phases", ".transitions", and ".petz".
Refer to "RFC 8536" for the TZif format.
fn minute
fn minute(d: *date) int;
Observes a date's minute of the hour.
fn month
fn month(d: *date) int;
Observes a date's month of the year. Range January=1 to December=12.
fn nanosecond
fn nanosecond(d: *date) int;
Observes a date's nanosecond of the second.
fn neg
fn neg(x: span) span;
Returns a span with its fields negated.
fn new
fn new(loc: locality, zoff: (time::duration | zflag), fields: int...) (date | invalid | zfunresolved);
Creates a new date. Accepts a locality, a zone-offset, and up to seven chronological fields applied in the following order:
- year
- month
- day
- hour
- minute
- second
- nanosecond
8 or more fields causes an abort. If omitted, the month and day default to 1, and the rest default to 0.
If the desired zone-offset is known, it can be given as a time::duration. Otherwise, use a zflag. See zflag on its effects to the result.
An invalid combination of provided date/time/zoff values returns invalid.
Examples:
// 0000-01-01 00:00:00.000000000 +0000 UTC UTC
date::new(date::UTC, date::zflag::CONTIG);
// 2000-01-02 15:04:05.600000000 +0000 UTC UTC
date::new(date::UTC, 0,
2000, 1, 2, 15, 4, 5, 600000000);
// 2000-01-02 15:00:00.000000000 +0100 CET Europe/Amsterdam
date::new(date::tzdb("Europe/Amsterdam")!,
1 * time::HOUR, // standard time in January
2000, 1, 2, 15);
// Could return [[zfunresolved]] by encountering a timezone transition.
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::CONTIG,
fields...);
// Will never return [[zfunresolved]].
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::LAP_EARLY | date::zflag::GAP_END,
fields...);
// On this day in Amsterdam, the clock jumped +1 hour at 02:00.
// 02:30 is never observed. Note the difference in zone-offset.
//
// 2000-03-26 01:59:59.999999999 +0100 CET Europe/Amsterdam
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::GAP_START,
2000, 3, 26, 2, 30);
//
// 2000-03-26 03:00:00.000000000 +0200 CET Europe/Amsterdam
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::GAP_END,
2000, 3, 26, 2, 30);
// On this day in Amsterdam, the clock jumped -1 hour at 03:00.
// 02:30 is observed twice. Note the difference in zone-offset.
//
// 2000-10-29 02:30:00.000000000 +0200 CET Europe/Amsterdam
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::LAP_EARLY,
2000, 10, 29, 2, 30);
//
// 2000-10-29 02:30:00.000000000 +0100 CET Europe/Amsterdam
date::new(date::tzdb("Europe/Amsterdam")!,
date::zflag::LAP_LATE,
2000, 10, 29, 2, 30);
fn newvirtual
fn newvirtual() virtual;
Creates a new virtual date. All its fields are voided or nulled.
fn parse
fn parse(v: *virtual, layout: str, info: str) (void | parsefail);
Parses date information from a string into a virtual date, according to a layout with specifiers as documented under format. Partial, sequential, aggregative parsing is possible.
date::parse(&v, "%Y-%m-%d", "2019-12-27");
date::parse(&v, "%H:%M:%S.%N", "22:07:08.000000000");
date::parse(&v, "%z %Z %L", "+0100 CET Europe/Amsterdam");
Parse will return parsefail if an invalid layout format specifier is encountered or if given info string does not match the layout.
fn realize
fn realize(v: virtual, locs: locality...) (date | insufficient | invalid | zfunresolved);
Realizes a valid date from a virtual date, or fails appropriately.
The virtual date must hold enough valid date information to calculate a resulting date. A valid combination of "inputs" (filled in, non-void fields) must be provided. For example:
let v = date::newvirtual();
v.locname = "Europe/Amsterdam";
v.zoff = date::zflag::LAP_EARLY | date::zflag::GAP_END;
date::parse(&v, // fills-in .year .month .day
"Date: %Y-%m-%d", "Date: 2038-01-19")!;
v.hour = 4;
v.minute = 14;
v.second = 7;
v.nanosecond = 0;
let d = date::realize(v, date::tzdb("Europe/Amsterdam")!)!;
A fixed algorithm is used to ascertain the given input combination. Combinations are attempted in a particular order listed below. Inputs marked with '*' can be substituted with further combinations. The algorithm is as follows:
The resultant date is made from a locality and time::instant.
The locality is derived from one of:
- .vloc
- .locname : This is compared to the .name field of each locality provided via the locs parameter, or "UTC" if none are provided. The first matching locality is used.
The instant is derived from one of:
- .vsec, .vnsec
- .daydate*, .daytime*, .zoff : See zflag for its effects here.
A void .daydate may be substituted with one of:
- .year*, .month, .day
- .year*, .yearday
- .year*, .week, .weekday
- .isoweekyear, .isoweek, .weekday
A void .daytime may be substituted with:
- .hour*, .minute, .second, .nanosecond
A void .year may be substituted with:
A void .hour may be substituted with:
If an insufficient combination was provided, insufficient is returned. If invalid values were provided, invalid is returned. Any zflags assigned to the .zoff field affect the final result.
fn reckon
fn reckon(d: date, zoff: (time::duration | zflag), rf: rflag, spans: span...) (date | invalid | zfunresolved);
Reckons from a given date to a new one, via a given set of spans. This is a chronological arithmetic operation. Each span is reckoned independently in succession, applying (adding) their units from most to least significant.
The rflag parameter handles field overflows and other behaviours. The zflag parameter affects the final result. Example:
// 2000-02-29 00:00:00.000000000 -1100 -11 Pacific/Apia
let a = date::new(chrono::tz("Pacific/Apia")!, -11 * time::HOUR,
2000, 2, 29)!;
let b = date::reckon(a, // starts as: 2000-Feb-29 00:00 -1100
date::zflag::GAP_END,
date::rflag::DEFAULT,
date::span {
years = 11, // becomes: 2011-Feb-28 00:00 -1100
months = 10, // becomes: 2011-Dec-28 00:00 -1100
days = 1, // becomes: 2011-Dec-29 00:00 -1100
hours = 36, // becomes: 2011-Dec-30 12:00 -1100
},
// In Samoa, Apia, the day 2011-Dec-30 was skipped entirely.
// Thus, after applying date::zflag::GAP_END for adjustment,
// we arrive at the final date, time, and zone-offset:
// 2011-12-31 00:00:00.000000000 +1400 +14 Pacific/Apia
);
See add.
fn second
fn second(d: *date) int;
Observes a date's second of the minute.
fn strerror
fn strerror(err: error) const str;
Converts an error into a human-friendly string. The result may be statically allocated.
fn sum
fn sum(spans: span...) span;
Returns the sum span of a set of spans.
fn sundayweek
fn sundayweek(d: *date) int;
Observes a date's Gregorian week starting Sunday. Range 0 to 53. All days in a year before the year's first Sunday belong to week 0.
fn timezone_free
fn timezone_free(tz: *timezone) void;
Frees a timezone. A locality argument can be passed.
fn to_instant
fn to_instant(d: date) time::instant;
Extracts the time::instant of the given date.
fn traverse
fn traverse(a: date, b: date) span;
Calculates the span between two dates, from A to B.
The returned span, provided to reckon with rflag::DEFAULT and date A, will produce B. The span's fields will all be the same sign.
Be aware, using date of different localitys may return unexpected results.
fn truncate
fn truncate(d: date, zf: zflag, u: step) (date | invalid | zfunresolved);
Truncates the given date at the provided nominal step. The zflag parameter affects the final result. Example:
// On this day in Sao Paulo, a +1 hour jump occurs at 00:00.
// The time range 00:00..00:59 is never observed.
//
// 2000-10-08 12:00:00.000000000 -0200 -02 America/Sao_Paulo
let a = date::new(chrono::tz("America/Sao_Paulo")!, -2 * time::HOUR,
2000, 10, 8, 12)!
//
// 2000-10-08 01:00:00.000000000 -0200 -02 America/Sao_Paulo
let b = date::truncate(a, date::zflag::GAP_END, date::step::DAY)!;
fn tzdb
fn tzdb(tzid: str) (locality | tzdberror);
Loads a timezone from the system's TZDB (Timezone Database) as a locality. Each call returns a new instance. The caller must free the return value. See timezone_free.
The given "TZID" shall be a TZDB identifier and acts as the relative filepath to a TZif (Time Zone Information Format) file under TZDB_PATH. For example, "Europe/Amsterdam" for "/usr/share/zoneinfo/Europe/Amsterdam".
The loaded timezones are assigned the TZID as its name, the time::chrono::utc timescale, and the EARTH_DAY day-length
fn week
fn week(d: *date) int;
Observes a date's Gregorian week starting Monday. Range 0 to 53. All days in a year before the year's first Monday belong to week 0.
fn weekday
fn weekday(d: *date) int;
Observes a date's day of the week. Range Monday=0 to Sunday=6.
fn year
fn year(d: *date) int;
Observes a date's year.
fn yearday
fn yearday(d: *date) int;
Observes a date's ordinal day of the year. Range 1 to 366.
fn zone
fn zone(d: *date) zonephase;
Observes a date's zonephase.
fn zone_finish
fn zone_finish(z: *zonephase) void;
Frees resources associated with a zonephase.