Struct AmbiguousTimestamp
struct AmbiguousTimestamp { ... }
A possibly ambiguous Timestamp, created by
TimeZone::to_ambiguous_timestamp.
While this is called an ambiguous timestamp, the thing that is
actually ambiguous is the offset. That is, an ambiguous timestamp is
actually a pair of a civil::DateTime and an
AmbiguousOffset.
When the offset is ambiguous, it either represents a gap (civil time is skipped) or a fold (civil time is repeated). In both cases, there are, by construction, two different offsets to choose from: the offset from before the transition and the offset from after the transition.
The purpose of this type is to represent that ambiguity (when it occurs)
and enable callers to make a choice about how to resolve that ambiguity.
In some cases, you might want to reject ambiguity altogether, which is
supported by the AmbiguousTimestamp::unambiguous routine.
This type provides four different out-of-the-box disambiguation strategies:
AmbiguousTimestamp::compatibleimplements theDisambiguation::Compatiblestrategy. In the case of a gap, the offset after the gap is selected. In the case of a fold, the offset before the fold occurs is selected.AmbiguousTimestamp::earlierimplements theDisambiguation::Earlierstrategy. This always selects the "earlier" offset.AmbiguousTimestamp::laterimplements theDisambiguation::Laterstrategy. This always selects the "later" offset.AmbiguousTimestamp::unambiguousimplements theDisambiguation::Rejectstrategy. It acts as an assertion that the offset is unambiguous. If it is ambiguous, then an appropriate error is returned.
The AmbiguousTimestamp::disambiguate method can be used with the
Disambiguation enum when the disambiguation strategy isn't known until
runtime.
Note also that these aren't the only disambiguation strategies. The
AmbiguousOffset type, accessible via AmbiguousTimestamp::offset,
exposes the full details of the ambiguity. So any strategy can be
implemented.
Example
This example shows how the "compatible" disambiguation strategy is implemented. Recall that the "compatible" strategy chooses the offset corresponding to the civil datetime after a gap, and the offset corresponding to the civil datetime before a gap.
use ;
let tz = db.get?;
let dt = date.at;
let offset = match tz.to_ambiguous_timestamp.offset ;
assert_eq!;
# Ok::
Implementations
impl AmbiguousTimestamp
fn datetime(self: &Self) -> DateTimeReturns the civil datetime that was used to create this ambiguous timestamp.
Example
use ; let tz = db.get?; let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; # Ok::fn offset(self: &Self) -> AmbiguousOffsetReturns the possibly ambiguous offset that is the ultimate source of ambiguity.
Most civil datetimes are not ambiguous, and thus, the offset will not be ambiguous either. In this case, the offset returned will be the
AmbiguousOffset::Unambiguousvariant.But, not all civil datetimes are unambiguous. There are exactly two cases where a civil datetime can be ambiguous: when a civil datetime does not exist (a gap) or when a civil datetime is repeated (a fold). In both such cases, the offset is the thing that is ambiguous as there are two possible choices for the offset in both cases: the offset before the transition (whether it's a gap or a fold) or the offset after the transition.
This type captures the fact that computing an offset from a civil datetime in a particular time zone is in one of three possible states:
- It is unambiguous.
- It is ambiguous because there is a gap in time.
- It is ambiguous because there is a fold in time.
Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; # Ok::fn is_ambiguous(self: &Self) -> boolReturns true if and only if this possibly ambiguous timestamp is actually ambiguous.
This occurs precisely in cases when the offset is not
AmbiguousOffset::Unambiguous.Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert!; # Ok::fn compatible(self: Self) -> Result<Timestamp, Error>Disambiguates this timestamp according to the
Disambiguation::Compatiblestrategy.If this timestamp is unambiguous, then this is a no-op.
The "compatible" strategy selects the offset corresponding to the civil time after a gap, and the offset corresponding to the civil time before a fold. This is what is specified in RFC 5545.
Errors
This returns an error when the combination of the civil datetime and offset would lead to a
Timestampoutside of theTimestamp::MINandTimestamp::MAXlimits. This only occurs when the civil datetime is "close" to its ownDateTime::MINandDateTime::MAXlimits.Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; # Ok::fn earlier(self: Self) -> Result<Timestamp, Error>Disambiguates this timestamp according to the
Disambiguation::Earlierstrategy.If this timestamp is unambiguous, then this is a no-op.
The "earlier" strategy selects the offset corresponding to the civil time before a gap, and the offset corresponding to the civil time before a fold.
Errors
This returns an error when the combination of the civil datetime and offset would lead to a
Timestampoutside of theTimestamp::MINandTimestamp::MAXlimits. This only occurs when the civil datetime is "close" to its ownDateTime::MINandDateTime::MAXlimits.Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; # Ok::fn later(self: Self) -> Result<Timestamp, Error>Disambiguates this timestamp according to the
Disambiguation::Laterstrategy.If this timestamp is unambiguous, then this is a no-op.
The "later" strategy selects the offset corresponding to the civil time after a gap, and the offset corresponding to the civil time after a fold.
Errors
This returns an error when the combination of the civil datetime and offset would lead to a
Timestampoutside of theTimestamp::MINandTimestamp::MAXlimits. This only occurs when the civil datetime is "close" to its ownDateTime::MINandDateTime::MAXlimits.Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; # Ok::fn unambiguous(self: Self) -> Result<Timestamp, Error>Disambiguates this timestamp according to the
Disambiguation::Rejectstrategy.If this timestamp is unambiguous, then this is a no-op.
The "reject" strategy always returns an error when the timestamp is ambiguous.
Errors
This returns an error when the combination of the civil datetime and offset would lead to a
Timestampoutside of theTimestamp::MINandTimestamp::MAXlimits. This only occurs when the civil datetime is "close" to its ownDateTime::MINandDateTime::MAXlimits.This also returns an error when the timestamp is ambiguous.
Example
use ; let tz = db.get?; // Not ambiguous. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert_eq!; // Ambiguous because of a gap. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert!; // Ambiguous because of a fold. let dt = date.at; let ts = tz.to_ambiguous_timestamp; assert!; # Ok::fn disambiguate(self: Self, option: Disambiguation) -> Result<Timestamp, Error>Disambiguates this (possibly ambiguous) timestamp into a specific timestamp.
This is the same as calling one of the disambiguation methods, but the method chosen is indicated by the option given. This is useful when the disambiguation option needs to be chosen at runtime.
Errors
This returns an error if this would have returned a timestamp outside of its minimum and maximum values.
This can also return an error when using the
Disambiguation::Rejectstrategy. Namely, when using theRejectstrategy, any ambiguous timestamp always results in an error.Example
This example shows the various disambiguation modes when given a datetime that falls in a "fold" (i.e., a backwards DST transition).
use ; let newyork = db.get?; let dt = date.at; let ambiguous = newyork.to_ambiguous_timestamp; // In compatible mode, backward transitions select the earlier // time. In the EDT->EST transition, that's the -04 (EDT) offset. let ts = ambiguous.clone.disambiguate?; assert_eq!; // The earlier time in the EDT->EST transition is the -04 (EDT) offset. let ts = ambiguous.clone.disambiguate?; assert_eq!; // The later time in the EDT->EST transition is the -05 (EST) offset. let ts = ambiguous.clone.disambiguate?; assert_eq!; // Since our datetime is ambiguous, the 'reject' strategy errors. assert!; # Ok::
impl Clone for AmbiguousTimestamp
fn clone(self: &Self) -> AmbiguousTimestamp
impl Copy for AmbiguousTimestamp
impl Debug for AmbiguousTimestamp
fn fmt(self: &Self, f: &mut $crate::fmt::Formatter<'_>) -> $crate::fmt::Result
impl Eq for AmbiguousTimestamp
impl Freeze for AmbiguousTimestamp
impl PartialEq for AmbiguousTimestamp
fn eq(self: &Self, other: &AmbiguousTimestamp) -> bool
impl RefUnwindSafe for AmbiguousTimestamp
impl Send for AmbiguousTimestamp
impl StructuralPartialEq for AmbiguousTimestamp
impl Sync for AmbiguousTimestamp
impl Unpin for AmbiguousTimestamp
impl UnwindSafe for AmbiguousTimestamp
impl<T> Any for AmbiguousTimestamp
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for AmbiguousTimestamp
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for AmbiguousTimestamp
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for AmbiguousTimestamp
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> From for AmbiguousTimestamp
fn from(t: T) -> TReturns the argument unchanged.
impl<T> ToOwned for AmbiguousTimestamp
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T, U> Into for AmbiguousTimestamp
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for AmbiguousTimestamp
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for AmbiguousTimestamp
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>