// This is a part of Chrono. // See README.md and LICENSE.txt for details.
//! ISO 8601 calendar date with time zone.
#[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; use core::cmp::Ordering; use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration;
#[cfg(feature = "unstable-locales")] use format::Locale; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; use naive::{self, IsoWeek, NaiveDate, NaiveTime}; use offset::{TimeZone, Utc}; use DateTime; use {Datelike, Weekday};
/// ISO 8601 calendar date with time zone. /// /// This type should be considered ambiguous at best, /// due to the inherent lack of precision required for the time zone resolution. /// For serialization and deserialization uses, it is best to use `NaiveDate` instead. /// There are some guarantees on the usage of `Date<Tz>`: /// /// - If properly constructed via `TimeZone::ymd` and others without an error, /// the corresponding local date should exist for at least a moment. /// (It may still have a gap from the offset changes.) /// /// - The `TimeZone` is free to assign *any* `Offset` to the local date, /// as long as that offset did occur in given day. /// For example, if `2015-03-08T01:59-08:00` is followed by `2015-03-08T03:00-07:00`, /// it may produce either `2015-03-08-08:00` or `2015-03-08-07:00` /// but *not* `2015-03-08+00:00` and others. /// /// - Once constructed as a full `DateTime`, /// `DateTime::date` and other associated methods should return those for the original `Date`. /// For example, if `dt = tz.ymd(y,m,d).hms(h,n,s)` were valid, `dt.date() == tz.ymd(y,m,d)`. /// /// - The date is timezone-agnostic up to one day (i.e. practically always), /// so the local date and UTC date should be equal for most cases /// even though the raw calculation between `NaiveDate` and `Duration` may not. #[derive(Clone)] pubstruct Date<Tz: TimeZone> {
date: NaiveDate,
offset: Tz::Offset,
}
/// The minimum possible `Date`. pubconst MIN_DATE: Date<Utc> = Date { date: naive::MIN_DATE, offset: Utc }; /// The maximum possible `Date`. pubconst MAX_DATE: Date<Utc> = Date { date: naive::MAX_DATE, offset: Utc };
impl<Tz: TimeZone> Date<Tz> { /// Makes a new `Date` with given *UTC* date and offset. /// The local date should be constructed via the `TimeZone` trait. // // note: this constructor is purposely not named to `new` to discourage the direct usage. #[inline] pubfn from_utc(date: NaiveDate, offset: Tz::Offset) -> Date<Tz> {
Date { date: date, offset: offset }
}
/// Makes a new `DateTime` from the current date and given `NaiveTime`. /// The offset in the current date is preserved. /// /// Panics on invalid datetime. #[inline] pubfn and_time(&self, time: NaiveTime) -> Option<DateTime<Tz>> { let localdt = self.naive_local().and_time(time); self.timezone().from_local_datetime(&localdt).single()
}
/// Makes a new `DateTime` from the current date, hour, minute and second. /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute and/or second. #[inline] pubfn and_hms(&self, hour: u32, min: u32, sec: u32) -> DateTime<Tz> { self.and_hms_opt(hour, min, sec).expect("invalid time")
}
/// Makes a new `DateTime` from the current date, hour, minute and second. /// The offset in the current date is preserved. /// /// Returns `None` on invalid hour, minute and/or second. #[inline] pubfn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<DateTime<Tz>> {
NaiveTime::from_hms_opt(hour, min, sec).and_then(|time| self.and_time(time))
}
/// Makes a new `DateTime` from the current date, hour, minute, second and millisecond. /// The millisecond part can exceed 1,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or millisecond. #[inline] pubfn and_hms_milli(&self, hour: u32, min: u32, sec: u32, milli: u32) -> DateTime<Tz> { self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
}
/// Makes a new `DateTime` from the current date, hour, minute, second and millisecond. /// The millisecond part can exceed 1,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Returns `None` on invalid hour, minute, second and/or millisecond. #[inline] pubfn and_hms_milli_opt(
&self,
hour: u32,
min: u32,
sec: u32,
milli: u32,
) -> Option<DateTime<Tz>> {
NaiveTime::from_hms_milli_opt(hour, min, sec, milli).and_then(|time| self.and_time(time))
}
/// Makes a new `DateTime` from the current date, hour, minute, second and microsecond. /// The microsecond part can exceed 1,000,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or microsecond. #[inline] pubfn and_hms_micro(&self, hour: u32, min: u32, sec: u32, micro: u32) -> DateTime<Tz> { self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
}
/// Makes a new `DateTime` from the current date, hour, minute, second and microsecond. /// The microsecond part can exceed 1,000,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Returns `None` on invalid hour, minute, second and/or microsecond. #[inline] pubfn and_hms_micro_opt(
&self,
hour: u32,
min: u32,
sec: u32,
micro: u32,
) -> Option<DateTime<Tz>> {
NaiveTime::from_hms_micro_opt(hour, min, sec, micro).and_then(|time| self.and_time(time))
}
/// Makes a new `DateTime` from the current date, hour, minute, second and nanosecond. /// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or nanosecond. #[inline] pubfn and_hms_nano(&self, hour: u32, min: u32, sec: u32, nano: u32) -> DateTime<Tz> { self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
}
/// Makes a new `DateTime` from the current date, hour, minute, second and nanosecond. /// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second. /// The offset in the current date is preserved. /// /// Returns `None` on invalid hour, minute, second and/or nanosecond. #[inline] pubfn and_hms_nano_opt(
&self,
hour: u32,
min: u32,
sec: u32,
nano: u32,
) -> Option<DateTime<Tz>> {
NaiveTime::from_hms_nano_opt(hour, min, sec, nano).and_then(|time| self.and_time(time))
}
/// Makes a new `Date` for the next date. /// /// Panics when `self` is the last representable date. #[inline] pubfn succ(&self) -> Date<Tz> { self.succ_opt().expect("out of bound")
}
/// Makes a new `Date` for the next date. /// /// Returns `None` when `self` is the last representable date. #[inline] pubfn succ_opt(&self) -> Option<Date<Tz>> { self.date.succ_opt().map(|date| Date::from_utc(date, self.offset.clone()))
}
/// Makes a new `Date` for the prior date. /// /// Panics when `self` is the first representable date. #[inline] pubfn pred(&self) -> Date<Tz> { self.pred_opt().expect("out of bound")
}
/// Makes a new `Date` for the prior date. /// /// Returns `None` when `self` is the first representable date. #[inline] pubfn pred_opt(&self) -> Option<Date<Tz>> { self.date.pred_opt().map(|date| Date::from_utc(date, self.offset.clone()))
}
/// Retrieves an associated offset from UTC. #[inline] pubfn offset(&self) -> &Tz::Offset {
&self.offset
}
/// Retrieves an associated time zone. #[inline] pubfn timezone(&self) -> Tz {
TimeZone::from_offset(&self.offset)
}
/// Changes the associated time zone. /// This does not change the actual `Date` (but will change the string representation). #[inline] pubfn with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> Date<Tz2> {
tz.from_utc_date(&self.date)
}
/// Adds given `Duration` to the current date. /// /// Returns `None` when it will result in overflow. #[inline] pubfn checked_add_signed(self, rhs: OldDuration) -> Option<Date<Tz>> { let date = try_opt!(self.date.checked_add_signed(rhs));
Some(Date { date: date, offset: self.offset })
}
/// Subtracts given `Duration` from the current date. /// /// Returns `None` when it will result in overflow. #[inline] pubfn checked_sub_signed(self, rhs: OldDuration) -> Option<Date<Tz>> { let date = try_opt!(self.date.checked_sub_signed(rhs));
Some(Date { date: date, offset: self.offset })
}
/// Subtracts another `Date` from the current date. /// Returns a `Duration` of integral numbers. /// /// This does not overflow or underflow at all, /// as all possible output fits in the range of `Duration`. #[inline] pubfn signed_duration_since<Tz2: TimeZone>(self, rhs: Date<Tz2>) -> OldDuration { self.date.signed_duration_since(rhs.date)
}
/// Returns a view to the naive UTC date. #[inline] pubfn naive_utc(&self) -> NaiveDate { self.date
}
/// Returns a view to the naive local date. /// /// This is technically the same as [`naive_utc`](#method.naive_utc) /// because the offset is restricted to never exceed one day, /// but provided for the consistency. #[inline] pubfn naive_local(&self) -> NaiveDate { self.date
}
}
/// Maps the local date to other date with given conversion function. fn map_local<Tz: TimeZone, F>(d: &Date<Tz>, mut f: F) -> Option<Date<Tz>> where
F: FnMut(NaiveDate) -> Option<NaiveDate>,
{
f(d.naive_local()).and_then(|date| d.timezone().from_local_date(&date).single())
}
impl<Tz: TimeZone> Date<Tz> where
Tz::Offset: fmt::Display,
{ /// Formats the date with the specified formatting items. #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pubfn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I> where
I: Iterator<Item = B> + Clone,
B: Borrow<Item<'a>>,
{
DelayedFormat::new_with_offset(Some(self.naive_local()), None, &self.offset, items)
}
/// Formats the date with the specified format string. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. #[cfg(any(feature = "alloc", feature = "std", test))] #[inline] pubfn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> { self.format_with_items(StrftimeItems::new(fmt))
}
/// Formats the date with the specified formatting items and locale. #[cfg(feature = "unstable-locales")] #[inline] pubfn format_localized_with_items<'a, I, B>(
&self,
items: I,
locale: Locale,
) -> DelayedFormat<I> where
I: Iterator<Item = B> + Clone,
B: Borrow<Item<'a>>,
{
DelayedFormat::new_with_offset_and_locale(
Some(self.naive_local()),
None,
&self.offset,
items,
locale,
)
}
/// Formats the date with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. #[cfg(feature = "unstable-locales")] #[inline] pubfn format_localized<'a>(
&self,
fmt: &'a str,
locale: Locale,
) -> DelayedFormat<StrftimeItems<'a>> { self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale)
}
}
// we need them as automatic impls cannot handle associated types impl<Tz: TimeZone> Copy for Date<Tz> where <Tz as TimeZone>::Offset: Copy {} unsafeimpl<Tz: TimeZone> Send for Date<Tz> where <Tz as TimeZone>::Offset: Send {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.