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 uncertain or invalid 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 time::chrono::locality. Use in to localize a date to another locality; consult time::chrono::tz. See parse and format for working with date/time strings.
Date arithmetic operations are categorized into "timescalar" or "chronological". Timescalar uses time::duration; see add, time::chrono::diff. Chronological uses period; see reckon, pdiff, unitdiff, truncate. Note that calendrical arithmetic is highly irregular due to field overflows and timezone discontinuities, so think carefully about what you want.
Index
Types
type date = struct {
chrono::moment,
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 period = struct {
years: i64,
months: i64,
weeks: i64,
days: i64,
hours: i64,
minutes: i64,
seconds: i64,
nanoseconds: i64,
};
type rflag = enum uint {
DEFAULT = 0, REVSIG = 1 << 0, FLOOR = 1 << 1,
CEIL = 1 << 2,
HOP = 1 << 3,
FOLD = 1 << 4,
};
type unit = enum {
ERA,
YEAR,
MONTH,
WEEK,
DAY,
HOUR,
MINUTE,
SECOND,
NANOSECOND,
};
type virtual = struct {
date,
vsec: (void | i64),
vnsec: (void | i64),
vloc: (void | chrono::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 lack = enum u8 {
LOCALITY = 1 << 0, DAYDATE = 1 << 1, DAYTIME = 1 << 2, ZOFF = 1 << 3, };
Errors
type error = !(insufficient | invalid | zfunresolved | parsefail);
type insufficient = !lack;
type invalid = !chrono::invalid;
type parsefail = !(size, rune);
type zfunresolved = !bool;
Constants
def APRIL: int = 4;
def AUGUST: int = 8;
def DECEMBER: int = 12;
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 MARCH: int = 3;
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 WEDNESDAY: int = 2;
def WRIST: str = "%b-%d %a %H:%M %Z";
Functions
fn abs(p: period) period;
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 day(d: *date) int;
fn era(d: *date) int;
fn format(h: io::handle, layout: str, d: *date) (size | io::error);
fn from_instant(loc: chrono::locality, i: time::instant) date;
fn from_moment(m: chrono::moment) date;
fn from_str(layout: str, s: str, locs: chrono::locality...) (date | parsefail | insufficient | invalid);
fn hour(d: *date) int;
fn in(loc: chrono::locality, d: date) (date | chrono::discontinuity);
fn isleapyear(y: int) bool;
fn isoweek(d: *date) int;
fn isoweekyear(d: *date) int;
fn localnow() date;
fn minute(d: *date) int;
fn month(d: *date) int;
fn nanosecond(d: *date) int;
fn neg(p: period) period;
fn new(loc: chrono::locality, zoff: (time::duration | zflag), fields: int...) (date | invalid | zfunresolved);
fn newvirtual() virtual;
fn now() date;
fn parse(v: *virtual, layout: str, s: str) (void | parsefail);
fn pdiff(a: date, b: date) period;
fn peq(pa: period, pb: period) bool;
fn realize(v: virtual, locs: chrono::locality...) (date | insufficient | invalid | zfunresolved);
fn reckon(d: date, zoff: (time::duration | zflag), rf: rflag, ps: period...) (date | invalid | zfunresolved);
fn second(d: *date) int;
fn strerror(err: error) const str;
fn sum(ps: period...) period;
fn sundayweek(d: *date) int;
fn truncate(d: date, zf: zflag, u: unit) (date | invalid | zfunresolved);
fn unitdiff(a: date, b: date, u: unit) i64;
fn week(d: *date) int;
fn weekday(d: *date) int;
fn year(d: *date) int;
fn yearday(d: *date) int;
Types
type date
type date = struct {
chrono::moment,
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 date/time object; a time::chrono::moment wrapper optimized for the Gregorian chronology, and by extension a time::instant wrapper.
This object should be treated as private and immutable. Directly mutating its fields causes undefined behaviour when used with module functions. Likewise, interrogating the fields' type and value (e.g. using match statements) is also improper.
A date observes various chronological values, cached in its fields. To evaluate and obtain these values, use the various observer functions (year, hour, etc.). These values are derived from the embedded moment information, and thus are guaranteed to be valid.
See virtual for an public, mutable, intermediary representation of a date, which waives guarantees of validity.
type period
type period = 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, using nominal units of time. Used for chronological arithmetic.
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 unit
type unit = enum {
ERA,
YEAR,
MONTH,
WEEK,
DAY,
HOUR,
MINUTE,
SECOND,
NANOSECOND,
};
The nominal units of the Gregorian chronology. Used for chronological arithmetic.
type virtual
type virtual = struct {
date,
vsec: (void | i64),
vnsec: (void | i64),
vloc: (void | chrono::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; a date wrapper interface, which represents a date of uncertain validity. Its fields need not be valid observed chronological values. It is meant as an intermediary container for date information to be resolved with the realize function.
Unlike date, a virtual date's fields are meant to be treated as public and mutable. The embedded time::instant and time::chrono::locality fields (.sec .nsec .loc) are considered meaningless. Behaviour with the observer functions is undefined.
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)!;
type zflag
type zflag = enum u8 {
CONTIG = 0,
LAP_EARLY = 1,
LAP_LATE = 2,
GAP_START = 4,
GAP_END = 8,
};
Flags for resolving an absent zone-offset. Handles timezone transitions.
The realize function, as well as other date creation functions (like new, truncate, reckon...) accept zflags. If zflags are provided, these functions normally calculate an intermediate date with a best-guess numerical zone-offset. This intermediate date can be invalid if it falls within the observed overlap or gap of a timezone transition, where such dates are ambiguous or nonexistent. In this case, the provided zflags are consulted, and a final calculation takes place before the final resultant date (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 that usage of "GAP_" flags will cause the resultant date to be different to what is originally specified if the intermediate date 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 lack
Show undocumented member
type lack = enum u8 {
LOCALITY = 1 << 0, DAYDATE = 1 << 1, DAYTIME = 1 << 2, ZOFF = 1 << 3, };
Errors
type error
type error = !(insufficient | invalid | zfunresolved | parsefail);
All possible errors returned from date.
type insufficient
type insufficient = !lack;
A virtual date does not have enough information from which to create a valid date.
type invalid
type invalid = !chrono::invalid;
Invalid date.
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 failure occured.
type zfunresolved
type zfunresolved = !bool;
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. A false value signifies the occurence of a timezone transition gap. A true value signifies the occurence of a timezone transition overlap.
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 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 MARCH
def MARCH: int = 3;
Ordinal for the month of March.
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 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.
Functions
fn abs
fn abs(p: period) period;
Returns a period 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 day
fn day(d: *date) int;
Observes a date's day of the month. Range 1 to 31.
fn era
fn era(d: *date) int;
Observes a date's era.
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 from_str
fn from_str(layout: str, s: str, locs: chrono::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 zflagss LAP_EARLY and GAP_END are used.
The date's time::chrono::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, time::chrono::UTC is used.
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 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(p: period) period;
Returns a period with its fields negated.
fn new
fn new(loc: chrono::locality, zoff: (time::duration | zflag), fields: int...) (date | invalid | zfunresolved);
Creates a new date. Accepts a time::chrono::locality, a zone-offset, and up to seven nominal 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(time::chrono::UTC, date::zflag::CONTIG);
// 2000-01-02 15:04:05.600000000 +0000 UTC UTC
date::new(time::chrono::UTC, 0,
2000, 1, 2, 15, 4, 5, 600000000);
// 2000-01-02 15:00:00.000000000 +0100 CET Europe/Amsterdam
date::new(time::chrono::tz("Europe/Amsterdam")!,
1 * time::HOUR, // standard time in January
2000, 1, 2, 15);
// Could return [[zfunresolved]] by encountering a timezone transition.
date::new(time::chrono::tz("Europe/Amsterdam")!,
date::zflag::CONTIG,
fields...);
// Will never return [[zfunresolved]].
date::new(time::chrono::tz("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(time::chrono::tz("Europe/Amsterdam")!,
date::zflag::GAP_START,
2000, 3, 26, 2, 30);
//
// 2000-03-26 03:00:00.000000000 +0200 CET Europe/Amsterdam
date::new(time::chrono::tz("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(time::chrono::tz("Europe/Amsterdam")!,
date::zflag::LAP_EARLY,
2000, 10, 29, 2, 30);
//
// 2000-10-29 02:30:00.000000000 +0100 CET Europe/Amsterdam
date::new(time::chrono::tz("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, s: str) (void | parsefail);
Parses a datetime string into a virtual date, according to a layout format string 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 format specifier is encountered or if given string 's' does not match the layout.
fn pdiff
fn pdiff(a: date, b: date) period;
Calculates the period between two dates, from A to B. The returned period, provided to reckon along with A, will produce B, regardless of the calculus used. All the period's non-zero fields will have the same sign.
fn peq
fn peq(pa: period, pb: period) bool;
Returns true if two periods are numerically equal, false otherwise.
fn realize
fn realize(v: virtual, locs: chrono::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 be able to calculate values for the resulting date. A valid combination of its fields must be "filled-in" (hold numerical, non-void values). 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, time::chrono::tz("Europe/Amsterdam")!)!;
This function consults the fields of the given virtual date using a predictable procedure, attempting the simplest and most common field combinations first. Fields marked below with an asterisk (*), when empty, depend on other filled-in field-sets to calculate a new value for itself. The order in which these "dependency" field-sets are tried is described below.
The resultant date depends on a locality value and instant value.
The locality (time::chrono::locality) value depends on:
- .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 (time::instant) value depends on:
- .vsec, .vnsec
- .daydate*, .daytime*, .zoff
An empty .daydate depends on:
- .year*, .month, .day
- .year*, .yearday
- .year*, .week, .weekday
- .isoweekyear, .isoweek, .weekday
An empty .daytime depends on:
- .hour*, .minute, .second, .nanosecond
An empty .year depends on:
An empty .hour depends on:
If not enough information was provided, insufficient is returned. If invalid information was 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, ps: period...) (date | invalid | zfunresolved);
Reckons from a given date to a new one, via a given set of periods. This is a chronological arithmetic operation. Each period 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::period {
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(ps: period...) period;
Returns the sum period of a set of periods.
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 truncate
fn truncate(d: date, zf: zflag, u: unit) (date | invalid | zfunresolved);
Truncates the given date at the provided nominal unit. 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::unit::DAY)!;
fn unitdiff
fn unitdiff(a: date, b: date, u: unit) i64;
Calculates the nominal unit difference between two dates.
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.