Expand description
mf2-fn-datetime — the MessageFormat 2 date/time functions of Rust MF2:
:datetime, :date, :time, and the handler that formats unannotated
date/time values. The semantics — operands, options, errors, time zones
— are here, once; a Backend only turns the result, a Plan, into
text:
| Feature | DefaultBackend (the statics’) |
|---|---|
| none | Neutral, a deterministic locale-independent stub (ISO 8601 pieces) |
datetime-icu | icu::Icu: ICU4X over the catalog’s icu.blob LOCALE entry, on client and server alike (narrower variants: Icu<GregorianOnly, NoZones> …) |
datetime-intl | Intl on wasm32-unknown-unknown: Host::format_date_time (the browser’s Intl.DateTimeFormat through mf2-host-web’s INTL_HOST); elsewhere Icu over ICU4X’s compiled data |
use mf2_fn_datetime::{DateTimeFunction, Neutral};
use mf2_runtime::{Function, Registry};
// `DATETIME`, `DATE`, `TIME`, `DATES` are these over the default backend.
static DATETIME: DateTimeFunction<Neutral> = DateTimeFunction::datetime(Neutral);
static DATES: DateTimeFunction<Neutral> = DateTimeFunction::unannotated(Neutral);
static FUNCTIONS: [(&str, &dyn Function); 1] = [("datetime", &DATETIME)];
static REGISTRY: Registry = Registry::new(&FUNCTIONS).with_dates(&DATES);A message formatted with that registry: the mf2 facade’s front page,
which reaches this crate as mf2::fn_datetime.
§The handlers
| Static | Registry name | What |
|---|---|---|
DATETIME | datetime | date and time; dateFields (year-month-day), dateLength (medium), timePrecision (minute), timeZoneStyle |
DATE | date | the date; fields (year-month-day), length (medium) |
TIME | time | the time; precision (minute), timeZoneStyle |
DATES | — (Registry::with_dates) | an unannotated date/time, as :datetime with its defaults |
All three functions take the override options timeZone and calendar;
:datetime and :time also hour12. Closed world: a registry
names only the handlers its corpus uses, and an unused one is never
linked. A handler over another backend: DateTimeFunction::datetime
and its siblings.
§Semantics, and the choices the spec leaves open
- Operands. A date/time value — an
Arg::DateTime, or what a date/time function resolved, with its options — or an application value’sCustomValue::as_date_time, or a string that is a date/time literal value: a literal, a string argument or an application value’sas_str(parse_literal). A literal must match the spec’s regular expression as a whole and name a day that exists; the spec’s MAY — other ISO 8601 forms — is not taken, so what parses is exactly the regex (-00:00is offset 0). Without a time it is 00:00:00, without an offset floating. Anything else (numbers, booleans, a fallback value, no operand) is Bad Operand and a fallback value. - A
:datevalue as a:timeoperand (and the reverse, which the spec says MAY be a Bad Operand): accepted. A resolved value keeps the whole date/time of its operand, so{$d :time}over$d = {|…T15:04:06| :date}shows 15:04; a date literal’s time is 00:00. - Options. Each function takes exactly the options datetime.md lists
for it; any other option is ignored (so
hour12andtimeZoneStyleon:date). The non-override options must be literals: a variable is Bad Option and the option is ignored. A value that is not one the option takes is Bad Option, ignored. Values compare exactly (case-sensitive). An override option may come from a variable whose value is a string (or an application value withas_str); any other value is Bad Option. - Override options.
timeZone:input,UTC, an RFC 3339time-numoffset(±hh:mm, hour 00–23), or an RFC 9557time-zone-name(mf2_runtime::is_zone_name; any well-formed name — whether a zone of that name exists is the host’s knowledge).hour12:true/false.calendar: a well-formeduvalue,3*8alphanum *("-" 3*8alphanum)in its BCP 47 spelling (UTS 35 also admits_, whichIntl.DateTimeFormatrejects); whether the calendar is known is the backend’s to report. They are inherited from a date/time operand (an argument may carry them too) and the expression’s own take priority; the operand’s other options are not inherited: over.local $d = {|2006-01-02| :date length=long},{$d}formats$das it was resolved (long),{$d :date}is a new:date(medium). A:datevalue keeps anhour12it inherited, for a later:time. - Resolved value. A
Value::DateTimewhoseoptionshold what resolved:datefor:datetimeand:date,timefor:datetimeand:time,time_zone_style,hour12,calendar, andtime_zone— the zone the value is now in (None: the formatting context’s). Not selectable: a selector on it is Bad Selector (the runtime’s). Part kinddatetime, directionLtrfor the neutral backend. - Time zones (
zone’splace). The default oftimeZoneis the formatting context’s zone (FnContext::time_zone).inputis the operand’s own zone; on a floating operand it is Bad Operand and the context’s zone is used (and recorded, so a later expression inheriting it does not report it again). A floating value takes the target zone without conversion; a value with an offset or a zone is converted to a different target: to UTC or an offset by arithmetic, to a named zone throughHost::zone_offset. A floating wall time placed in a named zone gets its instant from a bracketing search overzone_offset(java.time’s / Temporal’scompatiblechoice: in an overlap the earlier instant, in a gap the wall time moves forward by the gap). - No zone data (
Host::zone_offsetanswersNone, the default). Converting a value with an offset to a named zone, or a value in a named zone whose offset is unknown to any other zone, cannot be done: Bad Option and a fallback value, the alternative the specification allows — not a wall time shown in the wrong zone, and not Unsupported Operation, since the conversion itself is what the spec asks for. This includes the formatting context’s default zone, which is thetimeZoneoption’s resolved value when the expression sets none: a context in a named zone needs a host with zone data for instants. Placing a floating value in a named zone needs no conversion, so it is no error: the wall time shows, and the zone’s offset stays unknown (the neutral backend then names the zone fortimeZoneStyle). A converted value pastDate’s year limit is Bad Operand. - Unannotated date/time values (
DATES,Registry::with_dates): formatted as:datetimewith no options (its own override options apply); if that resolution reports an error, the placeholder is a fallback value with that error.
Client-path code: no_std, forbid(unsafe_code), no core::fmt use,
no panicking operation, no allocation —
the semantics, the neutral and the Intl backends. The ICU4X backend
allocates (the blob’s provider) and links ICU4X’s own core::fmt and
panic paths: that is datetime-icu’s cost in client size.
§The user guide
The Rust MF2 book is the user
guide: how the crates fit together, web and native applications, the
command line, and what 2.x promises.
An application reaches this crate through
mf2, as mf2::fn_datetime (feature fn-datetime).
Modules§
- icu
datetime-icu, ordatetime-intland not (target_os=unknownand WebAssembly) - The ICU4X backend (
datetime-icu, and the server side ofdatetime-intl;plans/03-runtime.md§5.1–§5.2): aPlanbecomes an ICU4X semantic skeleton built at runtime (FieldSetBuilder), formatted byicu_datetimewith the plan’s wall time and zone.
Structs§
- Date
Time Function - A date/time handler over the backend
B::datetime,:date,:time, or the unannotated one — the staticscrate::DATETIME,crate::DATE,crate::TIME,crate::DATESover the default backend, or one built with the constructors over another. - Intl
datetime-intl - The host’s date formatter (
Host::format_date_time). A host without one (it answersfalse, the default: an application that namesmf2_host_web::HOSTrather thanINTL_HOST), or one that rejects the request, gets the neutral text. - Neutral
- The neutral backend. Its text is the same in every locale: the pieces the options ask for, in the order date, weekday, time, zone, separated by one space —
- Plan
- What a backend formats: backend-independent, everything MF2 decided.
Statics§
- DATE
:date.- DATES
- Unannotated date/time values, for
Registry::with_dates: as:datetimewith its defaults. - DATETIME
:datetime.- TIME
:time.
Traits§
- Backend
- A date/time backend: turns a
Planinto text. The semantics — operands, options, errors, zones — are done; a backend only formats. Implemented bycrate::Neutral(the stub), and by thedatetime-icuanddatetime-intlbackends behind features (plans/11A6).
Functions§
- operand
- The value of a date/time operand (datetime.md, “Date and Time
Operands”): a date/time — an argument, or a date/time function’s value
with its options —, an application value’s
as_date_time, or a string that is a date/time literal value (a literal, a string argument, an application value’sas_str). Anything else — a number, a fallback value, an application value with neither conversion — is none. - parse_
literal - Parses a date/time literal value: the whole of
smatches the spec’s regular expression
Type Aliases§
- Default
Backend datetime-icu - The backend the statics format with:
icu::Icuwithdatetime-icu(every calendar, zone styles, the catalog’sicu.blob); withdatetime-intlalone,Intlin the browser (wasm32-unknown-unknown) andIcuover compiled data elsewhere;Neutralwith neither.