summaryrefslogtreecommitdiffstats
path: root/vendor/chrono/src/date.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chrono/src/date.rs')
-rw-r--r--vendor/chrono/src/date.rs221
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));
}
}