#[repr(transparent)]pub struct DateTime(_);
Expand description
A CAP timestamp.
DateTime
corresponds exactly to a chrono::DateTime<FixedOffset>
, except that CAP timestamps
are limited to 1-second resolution.
Example
// Get a chrono DateTime
let chrono_now = chrono::Local::now();
// Convert a chrono DateTime to a CAP DateTime
let cap_now = oasiscap::DateTime::from(chrono_now);
assert_eq!(chrono_now, cap_now);
assert_eq!(cap_now, chrono_now);
// Convert back
// The fractional seconds are gone, but the timestamp is otherwise equal
let chrono_roundtrip = chrono::DateTime::from(cap_now);
assert_eq!(chrono_roundtrip.nanosecond(), 0);
assert_eq!(chrono_now.with_nanosecond(0).unwrap(), chrono_roundtrip);
// Format the CAP DateTime as a CAP string
let cap_string = cap_now.to_string();
assert_eq!(cap_string.len(), 25);
// Parse a CAP DateTime back from a CAP string
let parsed: oasiscap::DateTime = cap_string.parse().unwrap();
assert_eq!(parsed, cap_now);
assert_eq!(parsed, chrono_now);
Textual encoding history
CAP v1.0 specifies timestamps to be “in ISO 8601 format”, which sounds reasonable but
unfortunately permits a very wide range of possible formats. The XML schema simply states that
timestamps are xs:dateTime
.
xs:dateTime
is “closely related to” and “inspired by” ISO 8601, but is a different model,
so CAP v1.0 is a bit self-contradictory. A larger concern is that xs:dateTime
specifies that
the canonical encoding for UTC is “Z”:
The mapping so defined is one-to-one, except that ‘+00:00’, ‘-00:00’, and ‘Z’ all represent the same zero-length duration timezone, UTC; ‘Z’ is its canonical representation.
This caused problems for some implementations which expected numeric offsets.
CAP v1.1 addressed this point, specified that timestamps are “in dateTime format, and
specifically links to xs:dateTime
’s definition. It also requires a numeric offset:
Alphabetic timezone designators such as “Z” MUST NOT be used. The timezone for UTC MUST be represented as “-00:00”.
However, xs:dateTime
permits both “untimezoned times” and fractional seconds:
“Local” or untimezoned times are presumed to be the time in the timezone of some unspecified locality as prescribed by the appropriate legal authority
Untimezoned times are not desirable for automatic processing of public safety information, and fractional seconds offer needless flexibility.
CAP v1.2 finally settled the matter, with the XML schema specifying that timezone offsets must always be numeric, and that fractional seconds are not permitted:
<simpleType>
<restriction base = "xs:dateTime">
<pattern value = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[-,+]\d\d:\d\d"/>
</restriction>
</simpleType>
Other implementers subsequently back-ported this formatting requirement to CAP v1.1 and v1.0, e.g. Google’s Public Alert extended CAP v1.0 schema.
Textual encoding decisions
DateTime
accepts values with fractional seconds because they are legal xs:dateTime
values,
but it discards the fraction, because fractional seconds seem to have been permitted by
accident.
assert_eq!(
"2002-05-24T16:49:00.123-01:00".parse::<DateTime>().unwrap(),
"2002-05-24T16:49:00-01:00".parse::<DateTime>().unwrap(),
);
assert_eq!(
"2002-05-24T16:49:00.123-01:00".parse::<DateTime>().unwrap().to_string(),
"2002-05-24T16:49:00-01:00",
);
DateTime
rejects untimezoned values, even though they are legal xs:dateTime
values and
therefore are permitted by some versions of the CAP standards, because the lack of reference
frame makes them unsuited for automatic processing.
assert!("2002-05-24T16:49:00".parse::<DateTime>().is_err());
DateTime
accepts +00:00
, -00:00
, and Z
as synonyms for UTC, since all three are legal
xs:dateTime
values, and all three clearly indicate UTC. This is more permissive than CAP v1.2,
but these timezone offsets are unambiguous, and it is useful for interoperability. DateTime
always formats UTC as -00:00
, which strictly complies with CAP v1.2 and is also accepted by
CAP v1.1 and v1.0 systems.
assert_eq!(
"2002-05-24T16:49:00-00:00".parse::<DateTime>().unwrap().to_string(),
"2002-05-24T16:49:00-00:00",
);
assert_eq!(
"2002-05-24T16:49:00+00:00".parse::<DateTime>().unwrap().to_string(),
"2002-05-24T16:49:00-00:00",
);
assert_eq!(
"2002-05-24T16:49:00Z".parse::<DateTime>().unwrap().to_string(),
"2002-05-24T16:49:00-00:00",
);
Trait Implementations
sourceimpl<'de> Deserialize<'de> for DateTime
impl<'de> Deserialize<'de> for DateTime
sourcefn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
sourceimpl From<DateTime> for DateTime<FixedOffset>
impl From<DateTime> for DateTime<FixedOffset>
sourceimpl Ord for DateTime
impl Ord for DateTime
sourceimpl PartialOrd<DateTime> for DateTime
impl PartialOrd<DateTime> for DateTime
sourcefn partial_cmp(&self, other: &DateTime) -> Option<Ordering>
fn partial_cmp(&self, other: &DateTime) -> Option<Ordering>
This method returns an ordering between self
and other
values if one exists. Read more
1.0.0 · sourcefn lt(&self, other: &Rhs) -> bool
fn lt(&self, other: &Rhs) -> bool
This method tests less than (for self
and other
) and is used by the <
operator. Read more
1.0.0 · sourcefn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
impl Copy for DateTime
impl Eq for DateTime
impl StructuralEq for DateTime
impl StructuralPartialEq for DateTime
Auto Trait Implementations
impl RefUnwindSafe for DateTime
impl Send for DateTime
impl Sync for DateTime
impl Unpin for DateTime
impl UnwindSafe for DateTime
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> ToOwned for T where
T: Clone,
impl<T> ToOwned for T where
T: Clone,
type Owned = T
type Owned = T
The resulting type after obtaining ownership.
sourcefn clone_into(&self, target: &mut T)
fn clone_into(&self, target: &mut T)
toowned_clone_into
)Uses borrowed data to replace owned data, usually by cloning. Read more