Struct ZonedWith
struct ZonedWith { ... }
A builder for setting the fields on a Zoned.
This builder is constructed via Zoned::with.
Example
The builder ensures one can chain together the individual components of a
zoned datetime without it failing at an intermediate step. For example,
if you had a date of 2024-10-31T00:00:00[America/New_York] and wanted
to change both the day and the month, and each setting was validated
independent of the other, you would need to be careful to set the day first
and then the month. In some cases, you would need to set the month first
and then the day!
But with the builder, you can set values in any order:
use date;
let zdt1 = date.at.in_tz?;
let zdt2 = zdt1.with.month.day.build?;
assert_eq!;
let zdt1 = date.at.in_tz?;
let zdt2 = zdt1.with.day.month.build?;
assert_eq!;
# Ok::
Implementations
impl ZonedWith
fn build(self: Self) -> Result<Zoned, Error>Create a new
Zonedfrom the fields set on this configuration.An error occurs when the fields combine to an invalid zoned datetime.
For any fields not set on this configuration, the values are taken from the
Zonedthat originally created this configuration. When no values are set, this routine is guaranteed to succeed and will always return the original zoned datetime without modification.Example
This creates a zoned datetime corresponding to the last day in the year at noon:
use date; let zdt = date.at.in_tz?; assert_eq!; // It also works with leap years for the same input: let zdt = date.at.in_tz?; assert_eq!; # Ok::Example: error for invalid zoned datetime
If the fields combine to form an invalid datetime, then an error is returned:
use date; let zdt = date.at.in_tz?; assert!; let zdt = date.at.in_tz?; assert!; # Ok::fn date(self: Self, date: Date) -> ZonedWithSet the year, month and day fields via the
Dategiven.This overrides any previous year, month or day settings.
Example
This shows how to create a new zoned datetime with a different date:
use date; let zdt1 = date.at.in_tz?; let zdt2 = zdt1.with.date.build?; // The date changes but the time remains the same. assert_eq!; # Ok::fn time(self: Self, time: Time) -> ZonedWithSet the hour, minute, second, millisecond, microsecond and nanosecond fields via the
Timegiven.This overrides any previous hour, minute, second, millisecond, microsecond, nanosecond or subsecond nanosecond settings.
Example
This shows how to create a new zoned datetime with a different time:
use ; let zdt1 = date.at.in_tz?; let zdt2 = zdt1.with.time.build?; // The time changes but the date remains the same. assert_eq!; # Ok::fn year(self: Self, year: i16) -> ZonedWithSet the year field on a
Zoned.One can access this value via
Zoned::year.This overrides any previous year settings.
Errors
This returns an error when
ZonedWith::buildis called if the given year is outside the range-9999..=9999. This can also return an error if the resulting date is otherwise invalid.Example
This shows how to create a new zoned datetime with a different year:
use date; let zdt1 = date.at.in_tz?; assert_eq!; let zdt2 = zdt1.with.year.build?; assert_eq!; # Ok::Example: only changing the year can fail
For example, while
2024-02-29T01:30:00[America/New_York]is valid,2023-02-29T01:30:00[America/New_York]is not:use date; let zdt = date.at.in_tz?; assert!; # Ok::fn era_year(self: Self, year: i16, era: Era) -> ZonedWithSet the year of a zoned datetime via its era and its non-negative numeric component.
One can access this value via
Zoned::era_year.Errors
This returns an error when
ZonedWith::buildis called if the year is outside the range for the era specified. ForEra::BCE, the range is1..=10000. ForEra::CE, the range is1..=9999.Example
This shows that
CEyears are equivalent to the years used by this crate:use ; let zdt1 = date.at.in_tz?; assert_eq!; let zdt2 = zdt1.with.era_year.build?; assert_eq!; // CE years are always positive and can be at most 9999: assert!; assert!; # Ok::But
BCEyears always correspond to years less than or equal to0in this crate:use ; let zdt1 = date.at.in_tz?; assert_eq!; assert_eq!; let zdt2 = zdt1.with.era_year.build?; assert_eq!; assert_eq!; let zdt2 = zdt1.with.era_year.build?; assert_eq!; assert_eq!; // BCE years are always positive and can be at most 10000: assert!; assert!; # Ok::Example: overrides
ZonedWith::yearSetting this option will override any previous
ZonedWith::yearoption:use ; let zdt1 = date.at.in_tz?; let zdt2 = zdt1.with.year.era_year.build?; assert_eq!; # Ok::Similarly,
ZonedWith::yearwill override any previous call toZonedWith::era_year:use ; let zdt1 = date.at.in_tz?; let zdt2 = zdt1.with.era_year.year.build?; assert_eq!; # Ok::fn month(self: Self, month: i8) -> ZonedWithSet the month field on a
Zoned.One can access this value via
Zoned::month.This overrides any previous month settings.
Errors
This returns an error when
ZonedWith::buildis called if the given month is outside the range1..=12. This can also return an error if the resulting date is otherwise invalid.Example
This shows how to create a new zoned datetime with a different month:
use date; let zdt1 = date .at .in_tz?; assert_eq!; let zdt2 = zdt1.with.month.build?; assert_eq!; # Ok::Example: only changing the month can fail
For example, while
2024-10-31T00:00:00[America/New_York]is valid,2024-11-31T00:00:00[America/New_York]is not:use date; let zdt = date.at.in_tz?; assert!; # Ok::fn day(self: Self, day: i8) -> ZonedWithSet the day field on a
Zoned.One can access this value via
Zoned::day.This overrides any previous day settings.
Errors
This returns an error when
ZonedWith::buildis called if the given given day is outside of allowable days for the corresponding year and month fields.Example
This shows some examples of setting the day, including a leap day:
use date; let zdt1 = date.at.in_tz?; assert_eq!; let zdt2 = zdt1.with.day.build?; assert_eq!; let zdt3 = zdt1.with.day.build?; assert_eq!; # Ok::Example: changing only the day can fail
This shows some examples that will fail:
use date; let zdt1 = date .at .in_tz?; // 2023 is not a leap year assert!; // September has 30 days, not 31. let zdt1 = date.in_tz?; assert!; # Ok::fn day_of_year(self: Self, day: i16) -> ZonedWithSet the day field on a
Zonedvia the ordinal number of a day within a year.When used, any settings for month are ignored since the month is determined by the day of the year.
The valid values for
dayare1..=366. Note though that366is only valid for leap years.This overrides any previous day settings.
Errors
This returns an error when
ZonedWith::buildis called if the given day is outside the allowed range of1..=366, or when a value of366is given for a non-leap year.Example
This demonstrates that if a year is a leap year, then
60corresponds to February 29:use date; let zdt = date .at .in_tz?; assert_eq!; # Ok::But for non-leap years, day 60 is March 1:
use date; let zdt = date .at .in_tz?; assert_eq!; # Ok::And using
366for a non-leap year will result in an error, since non-leap years only have 365 days:use date; let zdt = date.at.in_tz?; assert!; // The maximal year is not a leap year, so it returns an error too. let zdt = date.at.in_tz?; assert!; # Ok::fn day_of_year_no_leap(self: Self, day: i16) -> ZonedWithSet the day field on a
Zonedvia the ordinal number of a day within a year, but ignoring leap years.When used, any settings for month are ignored since the month is determined by the day of the year.
The valid values for
dayare1..=365. The value365always corresponds to the last day of the year, even for leap years. It is impossible for this routine to return a zoned datetime corresponding to February 29. (Unless there is a relevant time zone transition that provokes disambiguation that shifts the datetime into February 29.)This overrides any previous day settings.
Errors
This returns an error when
ZonedWith::buildis called if the given day is outside the allowed range of1..=365.Example
This demonstrates that
60corresponds to March 1, regardless of whether the year is a leap year or not:use date; let zdt = date .at .in_tz?; assert_eq!; let zdt = date .at .in_tz?; assert_eq!; # Ok::And using
365for any year will always yield the last day of the year:use date; let zdt = date .at .in_tz?; assert_eq!; let zdt = date .at .in_tz?; assert_eq!; // Careful at the boundaries. The last day of the year isn't // representable with all time zones. For example: let zdt = date .at .in_tz?; assert!; // But with other time zones, it works okay: let zdt = date .at .to_zoned?; assert_eq!; # Ok::A value of
366is out of bounds, even for leap years:use date; let zdt = date.at.in_tz?; assert!; # Ok::fn hour(self: Self, hour: i8) -> ZonedWithSet the hour field on a
Zoned.One can access this value via
Zoned::hour.This overrides any previous hour settings.
Errors
This returns an error when
ZonedWith::buildis called if the given hour is outside the range0..=23.Example
use time; let zdt1 = time.on.in_tz?; assert_eq!; let zdt2 = zdt1.with.hour.build?; assert_eq!; # Ok::fn minute(self: Self, minute: i8) -> ZonedWithSet the minute field on a
Zoned.One can access this value via
Zoned::minute.This overrides any previous minute settings.
Errors
This returns an error when
ZonedWith::buildis called if the given minute is outside the range0..=59.Example
use time; let zdt1 = time.on.in_tz?; assert_eq!; let zdt2 = zdt1.with.minute.build?; assert_eq!; # Ok::fn second(self: Self, second: i8) -> ZonedWithSet the second field on a
Zoned.One can access this value via
Zoned::second.This overrides any previous second settings.
Errors
This returns an error when
ZonedWith::buildis called if the given second is outside the range0..=59.Example
use time; let zdt1 = time.on.in_tz?; assert_eq!; let zdt2 = zdt1.with.second.build?; assert_eq!; # Ok::fn millisecond(self: Self, millisecond: i16) -> ZonedWithSet the millisecond field on a
Zoned.One can access this value via
Zoned::millisecond.This overrides any previous millisecond settings.
Errors
This returns an error when
ZonedWith::buildis called if the given millisecond is outside the range0..=999, or if both this andZonedWith::subsec_nanosecondare set.Example
This shows the relationship between
Zoned::millisecondand [Zoned::subsec_nanosecond]:use time; let zdt1 = time.on.in_tz?; let zdt2 = zdt1.with.millisecond.build?; assert_eq!; # Ok::fn microsecond(self: Self, microsecond: i16) -> ZonedWithSet the microsecond field on a
Zoned.One can access this value via
Zoned::microsecond.This overrides any previous microsecond settings.
Errors
This returns an error when
ZonedWith::buildis called if the given microsecond is outside the range0..=999, or if both this andZonedWith::subsec_nanosecondare set.Example
This shows the relationship between
Zoned::microsecondand [Zoned::subsec_nanosecond]:use time; let zdt1 = time.on.in_tz?; let zdt2 = zdt1.with.microsecond.build?; assert_eq!; # Ok::fn nanosecond(self: Self, nanosecond: i16) -> ZonedWithSet the nanosecond field on a
Zoned.One can access this value via
Zoned::nanosecond.This overrides any previous nanosecond settings.
Errors
This returns an error when
ZonedWith::buildis called if the given nanosecond is outside the range0..=999, or if both this andZonedWith::subsec_nanosecondare set.Example
This shows the relationship between
Zoned::nanosecondand [Zoned::subsec_nanosecond]:use time; let zdt1 = time.on.in_tz?; let zdt2 = zdt1.with.nanosecond.build?; assert_eq!; # Ok::fn subsec_nanosecond(self: Self, subsec_nanosecond: i32) -> ZonedWithSet the subsecond nanosecond field on a
Zoned.If you want to access this value on
Zoned, then useZoned::subsec_nanosecond.This overrides any previous subsecond nanosecond settings.
Errors
This returns an error when
ZonedWith::buildis called if the given subsecond nanosecond is outside the range0..=999,999,999, or if both this and one ofZonedWith::millisecond,ZonedWith::microsecondorZonedWith::nanosecondare set.Example
This shows the relationship between constructing a
Zonedvalue with subsecond nanoseconds and its individual subsecond fields:use time; let zdt1 = time.on.in_tz?; let zdt2 = zdt1.with.subsec_nanosecond.build?; assert_eq!; assert_eq!; assert_eq!; # Ok::fn offset(self: Self, offset: Offset) -> ZonedWithSet the offset to use in the new zoned datetime.
This can be used in some cases to explicitly disambiguate a datetime that could correspond to multiple instants in time.
How the offset is used to construct a new zoned datetime depends on the offset conflict resolution strategy set via
ZonedWith::offset_conflict. The default isOffsetConflict::PreferOffset, which will always try to use the offset to resolve a datetime to an instant, unless the offset is incorrect for this zoned datetime's time zone. In which case, only the time zone is used to select the correct offset (which may involve using the disambiguation strategy set viaZonedWith::disambiguation).Example
This example shows parsing the first time the 1 o'clock hour appeared on a clock in New York on 2024-11-03, and then changing only the offset to flip it to the second time 1 o'clock appeared on the clock:
use ; let zdt1: Zoned = "2024-11-03 01:30-04[America/New_York]".parse?; let zdt2 = zdt1.with.offset.build?; assert_eq!; // If we use an invalid offset for the America/New_York time zone, // then it will be ignored and the disambiguation strategy set will // be used. let zdt3 = zdt1.with.offset.build?; assert_eq!; // But we could change the disambiguation strategy to reject such // cases! let result = zdt1 .with .offset .disambiguation .build; assert!; # Ok::fn offset_conflict(self: Self, strategy: OffsetConflict) -> ZonedWithSet the conflict resolution strategy for when an offset is inconsistent with the time zone.
See the documentation on
OffsetConflictfor more details about the different strategies one can choose.Unlike parsing (where the default is
OffsetConflict::Reject), the default forZonedWithisOffsetConflict::PreferOffset, which avoids daylight saving time disambiguation causing unexpected 1-hour shifts after small changes to clock time.Example
use Zoned; // Set to the "second" time 1:30 is on the clocks in New York on // 2024-11-03. The offset in the datetime string makes this // unambiguous. let zdt1 = "2024-11-03T01:30-05[America/New_York]".?; // Now we change the minute field: let zdt2 = zdt1.with.minute.build?; assert_eq!; // But note that if we change the clock time such that the previous // offset is no longer valid (by moving back before DST ended), then // the default strategy will automatically adapt and change the offset. let zdt2 = zdt1.with.hour.build?; assert_eq!; # Ok::fn disambiguation(self: Self, strategy: Disambiguation) -> ZonedWithSet the disambiguation strategy for when a zoned datetime falls into a time zone transition "fold" or "gap."
The most common manifestation of such time zone transitions is daylight saving time. In most cases, the transition into daylight saving time moves the civil time ("the time you see on the clock") ahead one hour. This is called a "gap" because an hour on the clock is skipped. While the transition out of daylight saving time moves the civil time back one hour. This is called a "fold" because an hour on the clock is repeated.
In the case of a gap, an ambiguous datetime manifests as a time that never appears on a clock. (For example,
02:30on2024-03-10in New York.) In the case of a fold, an ambiguous datetime manifests as a time that repeats itself. (For example,01:30on2024-11-03in New York.) So when a fold occurs, you don't know whether it's the "first" occurrence of that time or the "second."Time zone transitions are not just limited to daylight saving time, although those are the most common. In other cases, a transition occurs because of a change in the offset of the time zone itself. (See the examples below.)
Example: time zone offset change
In this example, we explore a time zone offset change in Hawaii that occurred on
1947-06-08. Namely, Hawaii went from a-10:30offset to a-10:00offset at02:00. This results in a 30 minute gap in civil time.use ; // This datetime is unambiguous... let zdt1 = "1943-06-02T02:05[Pacific/Honolulu]".?; // but... 02:05 didn't exist on clocks on 1947-06-08. let zdt2 = zdt1 .with .disambiguation .year .day .build?; // Our parser is configured to select the later time, so we jump to // 02:35. But if we used `Disambiguation::Earlier`, then we'd get // 01:35. assert_eq!; assert_eq!; // If we subtract 10 minutes from 02:35, notice that we (correctly) // jump to 01:55 *and* our offset is corrected to -10:30. let zdt3 = zdt2.checked_sub?; assert_eq!; assert_eq!; # Ok::Example: offset conflict resolution and disambiguation
This example shows how the disambiguation configuration can interact with the default offset conflict resolution strategy of [
OffsetConflict::PreferOffset]:use ; // This datetime is unambiguous. let zdt1 = "2024-03-11T02:05[America/New_York]".?; assert_eq!; // But the same time on March 10 is ambiguous because there is a gap! let zdt2 = zdt1 .with .disambiguation .day .build?; assert_eq!; assert_eq!; # Ok::Namely, while we started with an offset of
-04, it (along with all other offsets) are considered invalid during civil time gaps due to time zone transitions (such as the beginning of daylight saving time in most locations).The default disambiguation strategy is
Disambiguation::Compatible, which in the case of gaps, chooses the time after the gap:use ; // This datetime is unambiguous. let zdt1 = "2024-03-11T02:05[America/New_York]".?; assert_eq!; // But the same time on March 10 is ambiguous because there is a gap! let zdt2 = zdt1 .with .day .build?; assert_eq!; assert_eq!; # Ok::Alternatively, one can choose to always respect the offset, and thus civil time for the provided time zone will be adjusted to match the instant prescribed by the offset. In this case, no disambiguation is performed:
use ; // This datetime is unambiguous. But `2024-03-10T02:05` is! let zdt1 = "2024-03-11T02:05[America/New_York]".?; assert_eq!; // But the same time on March 10 is ambiguous because there is a gap! let zdt2 = zdt1 .with .offset_conflict .day .build?; // Why do we get this result? Because `2024-03-10T02:05-04` is // `2024-03-10T06:05Z`. And in `America/New_York`, the civil time // for that timestamp is `2024-03-10T01:05-05`. assert_eq!; assert_eq!; # Ok::
impl Clone for ZonedWith
fn clone(self: &Self) -> ZonedWith
impl Debug for ZonedWith
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Freeze for ZonedWith
impl RefUnwindSafe for ZonedWith
impl Send for ZonedWith
impl Sync for ZonedWith
impl Unpin for ZonedWith
impl UnsafeUnpin for ZonedWith
impl UnwindSafe for ZonedWith
impl<T> Any for ZonedWith
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for ZonedWith
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for ZonedWith
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for ZonedWith
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> From for ZonedWith
fn from(t: T) -> TReturns the argument unchanged.
impl<T> ToOwned for ZonedWith
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T, U> Into for ZonedWith
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 ZonedWith
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for ZonedWith
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>