diff options
Diffstat (limited to 'vendor/chrono/src/date.rs')
-rw-r--r-- | vendor/chrono/src/date.rs | 221 |
1 files changed, 193 insertions, 28 deletions
diff --git a/vendor/chrono/src/date.rs b/vendor/chrono/src/date.rs index 0012d3604..bad4bfbb8 100644 --- a/vendor/chrono/src/date.rs +++ b/vendor/chrono/src/date.rs @@ -2,57 +2,74 @@ // See README.md and LICENSE.txt for details. //! ISO 8601 calendar date with time zone. +#![allow(deprecated)] #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; use core::cmp::Ordering; -use core::ops::{Add, Sub}; +use core::ops::{Add, AddAssign, Sub, SubAssign}; use core::{fmt, hash}; -use oldtime::Duration as OldDuration; + +#[cfg(feature = "rkyv")] +use rkyv::{Archive, Deserialize, Serialize}; #[cfg(feature = "unstable-locales")] -use format::Locale; +use crate::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}; +use crate::format::{DelayedFormat, Item, StrftimeItems}; +use crate::naive::{IsoWeek, NaiveDate, NaiveTime}; +use crate::offset::{TimeZone, Utc}; +use crate::oldtime::Duration as OldDuration; +use crate::DateTime; +use crate::{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. +/// You almost certainly want to be using a [`NaiveDate`] instead of this type. +/// +/// This type primarily exists to aid in the construction of DateTimes that +/// have a timezone by way of the [`TimeZone`] datelike constructors (e.g. +/// [`TimeZone::ymd`]). +/// +/// This type should be considered ambiguous at best, due to the inherent lack +/// of precision required for the time zone resolution. +/// /// There are some guarantees on the usage of `Date<Tz>`: /// -/// - If properly constructed via `TimeZone::ymd` and others without an error, +/// - 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. +/// - The `TimeZone` is free to assign *any* [`Offset`](crate::offset::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)`. +/// - 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_opt(y,m,d).unwrap().hms(h,n,s)` were valid, `dt.date() == tz.ymd_opt(y,m,d).unwrap()`. /// /// - 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. +#[deprecated(since = "0.4.23", note = "Use `NaiveDate` or `DateTime<Tz>` instead")] #[derive(Clone)] +#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))] pub struct Date<Tz: TimeZone> { date: NaiveDate, offset: Tz::Offset, } /// The minimum possible `Date`. -pub const MIN_DATE: Date<Utc> = Date { date: naive::MIN_DATE, offset: Utc }; +#[allow(deprecated)] +#[deprecated(since = "0.4.20", note = "Use Date::MIN_UTC instead")] +pub const MIN_DATE: Date<Utc> = Date::<Utc>::MIN_UTC; /// The maximum possible `Date`. -pub const MAX_DATE: Date<Utc> = Date { date: naive::MAX_DATE, offset: Utc }; +#[allow(deprecated)] +#[deprecated(since = "0.4.20", note = "Use Date::MAX_UTC instead")] +pub const MAX_DATE: Date<Utc> = Date::<Utc>::MAX_UTC; impl<Tz: TimeZone> Date<Tz> { /// Makes a new `Date` with given *UTC* date and offset. @@ -61,7 +78,7 @@ impl<Tz: TimeZone> Date<Tz> { // note: this constructor is purposely not named to `new` to discourage the direct usage. #[inline] pub fn from_utc(date: NaiveDate, offset: Tz::Offset) -> Date<Tz> { - Date { date: date, offset: offset } + Date { date, offset } } /// Makes a new `DateTime` from the current date and given `NaiveTime`. @@ -78,6 +95,7 @@ impl<Tz: TimeZone> Date<Tz> { /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute and/or second. + #[deprecated(since = "0.4.23", note = "Use and_hms_opt() instead")] #[inline] pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> DateTime<Tz> { self.and_hms_opt(hour, min, sec).expect("invalid time") @@ -97,6 +115,7 @@ impl<Tz: TimeZone> Date<Tz> { /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or millisecond. + #[deprecated(since = "0.4.23", note = "Use and_hms_milli_opt() instead")] #[inline] pub fn 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") @@ -123,6 +142,7 @@ impl<Tz: TimeZone> Date<Tz> { /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or microsecond. + #[deprecated(since = "0.4.23", note = "Use and_hms_micro_opt() instead")] #[inline] pub fn 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") @@ -149,6 +169,7 @@ impl<Tz: TimeZone> Date<Tz> { /// The offset in the current date is preserved. /// /// Panics on invalid hour, minute, second and/or nanosecond. + #[deprecated(since = "0.4.23", note = "Use and_hms_nano_opt() instead")] #[inline] pub fn 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") @@ -173,6 +194,7 @@ impl<Tz: TimeZone> Date<Tz> { /// Makes a new `Date` for the next date. /// /// Panics when `self` is the last representable date. + #[deprecated(since = "0.4.23", note = "Use succ_opt() instead")] #[inline] pub fn succ(&self) -> Date<Tz> { self.succ_opt().expect("out of bound") @@ -189,6 +211,7 @@ impl<Tz: TimeZone> Date<Tz> { /// Makes a new `Date` for the prior date. /// /// Panics when `self` is the first representable date. + #[deprecated(since = "0.4.23", note = "Use pred_opt() instead")] #[inline] pub fn pred(&self) -> Date<Tz> { self.pred_opt().expect("out of bound") @@ -226,8 +249,8 @@ impl<Tz: TimeZone> Date<Tz> { /// Returns `None` when it will result in overflow. #[inline] pub fn 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 }) + let date = self.date.checked_add_signed(rhs)?; + Some(Date { date, offset: self.offset }) } /// Subtracts given `Duration` from the current date. @@ -235,8 +258,8 @@ impl<Tz: TimeZone> Date<Tz> { /// Returns `None` when it will result in overflow. #[inline] pub fn 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 }) + let date = self.date.checked_sub_signed(rhs)?; + Some(Date { date, offset: self.offset }) } /// Subtracts another `Date` from the current date. @@ -264,6 +287,16 @@ impl<Tz: TimeZone> Date<Tz> { pub fn naive_local(&self) -> NaiveDate { self.date } + + /// Returns the number of whole years from the given `base` until `self`. + pub fn years_since(&self, base: Self) -> Option<u32> { + self.date.years_since(base.date) + } + + /// The minimum possible `Date`. + pub const MIN_UTC: Date<Utc> = Date { date: NaiveDate::MIN, offset: Utc }; + /// The maximum possible `Date`. + pub const MAX_UTC: Date<Utc> = Date { date: NaiveDate::MAX, offset: Utc }; } /// Maps the local date to other date with given conversion function. @@ -280,6 +313,7 @@ where { /// Formats the date with the specified formatting items. #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] #[inline] pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I> where @@ -290,9 +324,10 @@ where } /// Formats the date with the specified format string. - /// See the [`format::strftime` module](./format/strftime/index.html) + /// See the [`crate::format::strftime`] module /// on the supported escape sequences. #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> { self.format_with_items(StrftimeItems::new(fmt)) @@ -300,6 +335,7 @@ where /// Formats the date with the specified formatting items and locale. #[cfg(feature = "unstable-locales")] + #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))] #[inline] pub fn format_localized_with_items<'a, I, B>( &self, @@ -320,9 +356,10 @@ where } /// Formats the date with the specified format string and locale. - /// See the [`format::strftime` module](./format/strftime/index.html) + /// See the [`crate::format::strftime`] module /// on the supported escape sequences. #[cfg(feature = "unstable-locales")] + #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))] #[inline] pub fn format_localized<'a>( &self, @@ -446,6 +483,13 @@ impl<Tz: TimeZone> Add<OldDuration> for Date<Tz> { } } +impl<Tz: TimeZone> AddAssign<OldDuration> for Date<Tz> { + #[inline] + fn add_assign(&mut self, rhs: OldDuration) { + self.date = self.date.checked_add_signed(rhs).expect("`Date + Duration` overflowed"); + } +} + impl<Tz: TimeZone> Sub<OldDuration> for Date<Tz> { type Output = Date<Tz>; @@ -455,6 +499,13 @@ impl<Tz: TimeZone> Sub<OldDuration> for Date<Tz> { } } +impl<Tz: TimeZone> SubAssign<OldDuration> for Date<Tz> { + #[inline] + fn sub_assign(&mut self, rhs: OldDuration) { + self.date = self.date.checked_sub_signed(rhs).expect("`Date - Duration` overflowed"); + } +} + impl<Tz: TimeZone> Sub<Date<Tz>> for Date<Tz> { type Output = OldDuration; @@ -466,7 +517,8 @@ impl<Tz: TimeZone> Sub<Date<Tz>> for Date<Tz> { impl<Tz: TimeZone> fmt::Debug for Date<Tz> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}{:?}", self.naive_local(), self.offset) + self.naive_local().fmt(f)?; + self.offset.fmt(f) } } @@ -475,6 +527,119 @@ where Tz::Offset: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}{}", self.naive_local(), self.offset) + self.naive_local().fmt(f)?; + self.offset.fmt(f) + } +} + +// Note that implementation of Arbitrary cannot be automatically derived for Date<Tz>, due to +// the nontrivial bound <Tz as TimeZone>::Offset: Arbitrary. +#[cfg(feature = "arbitrary")] +impl<'a, Tz> arbitrary::Arbitrary<'a> for Date<Tz> +where + Tz: TimeZone, + <Tz as TimeZone>::Offset: arbitrary::Arbitrary<'a>, +{ + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Date<Tz>> { + let date = NaiveDate::arbitrary(u)?; + let offset = <Tz as TimeZone>::Offset::arbitrary(u)?; + Ok(Date::from_utc(date, offset)) + } +} + +#[cfg(test)] +mod tests { + use super::Date; + + use crate::oldtime::Duration; + use crate::{FixedOffset, NaiveDate, Utc}; + + #[cfg(feature = "clock")] + use crate::offset::{Local, TimeZone}; + + #[test] + #[cfg(feature = "clock")] + fn test_years_elapsed() { + const WEEKS_PER_YEAR: f32 = 52.1775; + + // This is always at least one year because 1 year = 52.1775 weeks. + let one_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 1.5).ceil() as i64); + // A bit more than 2 years. + let two_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 2.5).ceil() as i64); + + assert_eq!(Utc::today().years_since(one_year_ago), Some(1)); + assert_eq!(Utc::today().years_since(two_year_ago), Some(2)); + + // If the given DateTime is later than now, the function will always return 0. + let future = Utc::today() + Duration::weeks(12); + assert_eq!(Utc::today().years_since(future), None); + } + + #[test] + fn test_date_add_assign() { + let naivedate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(); + let date = Date::<Utc>::from_utc(naivedate, Utc); + let mut date_add = date; + + date_add += Duration::days(5); + assert_eq!(date_add, date + Duration::days(5)); + + let timezone = FixedOffset::east_opt(60 * 60).unwrap(); + let date = date.with_timezone(&timezone); + let date_add = date_add.with_timezone(&timezone); + + assert_eq!(date_add, date + Duration::days(5)); + + let timezone = FixedOffset::west_opt(2 * 60 * 60).unwrap(); + let date = date.with_timezone(&timezone); + let date_add = date_add.with_timezone(&timezone); + + assert_eq!(date_add, date + Duration::days(5)); + } + + #[test] + #[cfg(feature = "clock")] + fn test_date_add_assign_local() { + let naivedate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(); + + let date = Local.from_utc_date(&naivedate); + let mut date_add = date; + + date_add += Duration::days(5); + assert_eq!(date_add, date + Duration::days(5)); + } + + #[test] + fn test_date_sub_assign() { + let naivedate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(); + let date = Date::<Utc>::from_utc(naivedate, Utc); + let mut date_sub = date; + + date_sub -= Duration::days(5); + assert_eq!(date_sub, date - Duration::days(5)); + + let timezone = FixedOffset::east_opt(60 * 60).unwrap(); + let date = date.with_timezone(&timezone); + let date_sub = date_sub.with_timezone(&timezone); + + assert_eq!(date_sub, date - Duration::days(5)); + + let timezone = FixedOffset::west_opt(2 * 60 * 60).unwrap(); + let date = date.with_timezone(&timezone); + let date_sub = date_sub.with_timezone(&timezone); + + assert_eq!(date_sub, date - Duration::days(5)); + } + + #[test] + #[cfg(feature = "clock")] + fn test_date_sub_assign_local() { + let naivedate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(); + + let date = Local.from_utc_date(&naivedate); + let mut date_sub = date; + + date_sub -= Duration::days(5); + assert_eq!(date_sub, date - Duration::days(5)); } } |