diff options
Diffstat (limited to 'vendor/chrono/src/naive')
-rw-r--r-- | vendor/chrono/src/naive/date.rs | 1765 | ||||
-rw-r--r-- | vendor/chrono/src/naive/datetime.rs | 2507 | ||||
-rw-r--r-- | vendor/chrono/src/naive/datetime/mod.rs | 1946 | ||||
-rw-r--r-- | vendor/chrono/src/naive/datetime/rustc_serialize.rs | 73 | ||||
-rw-r--r-- | vendor/chrono/src/naive/datetime/serde.rs | 1133 | ||||
-rw-r--r-- | vendor/chrono/src/naive/datetime/tests.rs | 343 | ||||
-rw-r--r-- | vendor/chrono/src/naive/internals.rs | 277 | ||||
-rw-r--r-- | vendor/chrono/src/naive/isoweek.rs | 66 | ||||
-rw-r--r-- | vendor/chrono/src/naive/mod.rs | 39 | ||||
-rw-r--r-- | vendor/chrono/src/naive/time/mod.rs (renamed from vendor/chrono/src/naive/time.rs) | 940 | ||||
-rw-r--r-- | vendor/chrono/src/naive/time/rustc_serialize.rs | 29 | ||||
-rw-r--r-- | vendor/chrono/src/naive/time/serde.rs | 65 | ||||
-rw-r--r-- | vendor/chrono/src/naive/time/tests.rs | 317 |
13 files changed, 5562 insertions, 3938 deletions
diff --git a/vendor/chrono/src/naive/date.rs b/vendor/chrono/src/naive/date.rs index 3e34e2074..64af978f3 100644 --- a/vendor/chrono/src/naive/date.rs +++ b/vendor/chrono/src/naive/date.rs @@ -5,18 +5,27 @@ #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; -use core::ops::{Add, AddAssign, Sub, SubAssign}; +use core::convert::TryFrom; +use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign}; use core::{fmt, str}; + +use num_integer::div_mod_floor; use num_traits::ToPrimitive; -use oldtime::Duration as OldDuration; +#[cfg(feature = "rkyv")] +use rkyv::{Archive, Deserialize, Serialize}; + +/// L10n locales. +#[cfg(feature = "unstable-locales")] +use pure_rust_locales::Locale; -use div::div_mod_floor; #[cfg(any(feature = "alloc", feature = "std", test))] -use format::DelayedFormat; -use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; -use format::{Item, Numeric, Pad}; -use naive::{IsoWeek, NaiveDateTime, NaiveTime}; -use {Datelike, Weekday}; +use crate::format::DelayedFormat; +use crate::format::{parse, write_hundreds, ParseError, ParseResult, Parsed, StrftimeItems}; +use crate::format::{Item, Numeric, Pad}; +use crate::month::Months; +use crate::naive::{IsoWeek, NaiveDateTime, NaiveTime}; +use crate::oldtime::Duration as OldDuration; +use crate::{Datelike, Duration, Weekday}; use super::internals::{self, DateImpl, Mdf, Of, YearFlags}; use super::isoweek; @@ -42,11 +51,91 @@ const MAX_DAYS_FROM_YEAR_0: i32 = const MIN_DAYS_FROM_YEAR_0: i32 = (MIN_YEAR + 400_000) * 365 + (MIN_YEAR + 400_000) / 4 - (MIN_YEAR + 400_000) / 100 + (MIN_YEAR + 400_000) / 400 - - 146097_000; + - 146_097_000; #[cfg(test)] // only used for testing, but duplicated in naive::datetime const MAX_BITS: usize = 44; +/// A week represented by a [`NaiveDate`] and a [`Weekday`] which is the first +/// day of the week. +#[derive(Debug)] +pub struct NaiveWeek { + date: NaiveDate, + start: Weekday, +} + +impl NaiveWeek { + /// Returns a date representing the first day of the week. + /// + /// # Examples + /// + /// ``` + /// use chrono::{NaiveDate, Weekday}; + /// + /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap(); + /// let week = date.week(Weekday::Mon); + /// assert!(week.first_day() <= date); + /// ``` + #[inline] + pub fn first_day(&self) -> NaiveDate { + let start = self.start.num_days_from_monday(); + let end = self.date.weekday().num_days_from_monday(); + let days = if start > end { 7 - start + end } else { end - start }; + self.date - Duration::days(days.into()) + } + + /// Returns a date representing the last day of the week. + /// + /// # Examples + /// + /// ``` + /// use chrono::{NaiveDate, Weekday}; + /// + /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap(); + /// let week = date.week(Weekday::Mon); + /// assert!(week.last_day() >= date); + /// ``` + #[inline] + pub fn last_day(&self) -> NaiveDate { + self.first_day() + Duration::days(6) + } + + /// Returns a [`RangeInclusive<T>`] representing the whole week bounded by + /// [first_day](./struct.NaiveWeek.html#method.first_day) and + /// [last_day](./struct.NaiveWeek.html#method.last_day) functions. + /// + /// # Examples + /// + /// ``` + /// use chrono::{NaiveDate, Weekday}; + /// + /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap(); + /// let week = date.week(Weekday::Mon); + /// let days = week.days(); + /// assert!(days.contains(&date)); + /// ``` + #[inline] + pub fn days(&self) -> RangeInclusive<NaiveDate> { + self.first_day()..=self.last_day() + } +} + +/// A duration in calendar days. +/// +/// This is useful because when using `Duration` it is possible +/// that adding `Duration::days(1)` doesn't increment the day value as expected due to it being a +/// fixed number of seconds. This difference applies only when dealing with `DateTime<TimeZone>` data types +/// and in other cases `Duration::days(n)` and `Days::new(n)` are equivalent. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)] +pub struct Days(pub(crate) u64); + +impl Days { + /// Construct a new `Days` from a number of days + pub const fn new(num: u64) -> Self { + Self(num) + } +} + /// ISO 8601 calendar date without timezone. /// Allows for every [proleptic Gregorian date](#calendar-date) /// from Jan 1, 262145 BCE to Dec 31, 262143 CE. @@ -96,35 +185,48 @@ const MAX_BITS: usize = 44; /// /// This is currently the internal format of Chrono's date types. #[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)] +#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))] pub struct NaiveDate { ymdf: DateImpl, // (year << 13) | of } /// The minimum possible `NaiveDate` (January 1, 262145 BCE). -pub const MIN_DATE: NaiveDate = NaiveDate { ymdf: (MIN_YEAR << 13) | (1 << 4) | 0o07 /*FE*/ }; +#[deprecated(since = "0.4.20", note = "Use NaiveDate::MIN instead")] +pub const MIN_DATE: NaiveDate = NaiveDate::MIN; /// The maximum possible `NaiveDate` (December 31, 262143 CE). -pub const MAX_DATE: NaiveDate = NaiveDate { ymdf: (MAX_YEAR << 13) | (365 << 4) | 0o17 /*F*/ }; +#[deprecated(since = "0.4.20", note = "Use NaiveDate::MAX instead")] +pub const MAX_DATE: NaiveDate = NaiveDate::MAX; + +#[cfg(feature = "arbitrary")] +impl arbitrary::Arbitrary<'_> for NaiveDate { + fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<NaiveDate> { + let year = u.int_in_range(MIN_YEAR..=MAX_YEAR)?; + let max_days = YearFlags::from_year(year).ndays(); + let ord = u.int_in_range(1..=max_days)?; + NaiveDate::from_yo_opt(year, ord).ok_or(arbitrary::Error::IncorrectFormat) + } +} -// as it is hard to verify year flags in `MIN_DATE` and `MAX_DATE`, +// as it is hard to verify year flags in `NaiveDate::MIN` and `NaiveDate::MAX`, // we use a separate run-time test. #[test] fn test_date_bounds() { - let calculated_min = NaiveDate::from_ymd(MIN_YEAR, 1, 1); - let calculated_max = NaiveDate::from_ymd(MAX_YEAR, 12, 31); + let calculated_min = NaiveDate::from_ymd_opt(MIN_YEAR, 1, 1).unwrap(); + let calculated_max = NaiveDate::from_ymd_opt(MAX_YEAR, 12, 31).unwrap(); assert!( - MIN_DATE == calculated_min, - "`MIN_DATE` should have a year flag {:?}", + NaiveDate::MIN == calculated_min, + "`NaiveDate::MIN` should have a year flag {:?}", calculated_min.of().flags() ); assert!( - MAX_DATE == calculated_max, - "`MAX_DATE` should have a year flag {:?}", + NaiveDate::MAX == calculated_max, + "`NaiveDate::MAX` should have a year flag {:?}", calculated_max.of().flags() ); // let's also check that the entire range do not exceed 2^44 seconds // (sometimes used for bounding `Duration` against overflow) - let maxsecs = MAX_DATE.signed_duration_since(MIN_DATE).num_seconds(); + let maxsecs = NaiveDate::MAX.signed_duration_since(NaiveDate::MIN).num_seconds(); let maxsecs = maxsecs + 86401; // also take care of DateTime assert!( maxsecs < (1 << MAX_BITS), @@ -134,9 +236,12 @@ fn test_date_bounds() { } impl NaiveDate { + pub(crate) fn weeks_from(&self, day: Weekday) -> i32 { + (self.ordinal() as i32 - self.weekday().num_days_from(day) as i32 + 6) / 7 + } /// Makes a new `NaiveDate` from year and packed ordinal-flags, with a verification. fn from_of(year: i32, of: Of) -> Option<NaiveDate> { - if year >= MIN_YEAR && year <= MAX_YEAR && of.valid() { + if (MIN_YEAR..=MAX_YEAR).contains(&year) && of.valid() { let Of(of) = of; Some(NaiveDate { ymdf: (year << 13) | (of as DateImpl) }) } else { @@ -153,22 +258,7 @@ impl NaiveDate { /// (year, month and day). /// /// Panics on the out-of-range date, invalid month and/or day. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, Datelike, Weekday}; - /// - /// let d = NaiveDate::from_ymd(2015, 3, 14); - /// assert_eq!(d.year(), 2015); - /// assert_eq!(d.month(), 3); - /// assert_eq!(d.day(), 14); - /// assert_eq!(d.ordinal(), 73); // day of year - /// assert_eq!(d.iso_week().year(), 2015); - /// assert_eq!(d.iso_week().week(), 11); - /// assert_eq!(d.weekday(), Weekday::Sat); - /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_ymd_opt()` instead")] pub fn from_ymd(year: i32, month: u32, day: u32) -> NaiveDate { NaiveDate::from_ymd_opt(year, month, day).expect("invalid or out-of-range date") } @@ -180,7 +270,7 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// /// let from_ymd_opt = NaiveDate::from_ymd_opt; @@ -191,32 +281,17 @@ impl NaiveDate { /// assert!(from_ymd_opt(-4, 2, 29).is_some()); // 5 BCE is a leap year /// assert!(from_ymd_opt(400000, 1, 1).is_none()); /// assert!(from_ymd_opt(-400000, 1, 1).is_none()); - /// ~~~~ + /// ``` pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<NaiveDate> { let flags = YearFlags::from_year(year); - NaiveDate::from_mdf(year, Mdf::new(month, day, flags)) + NaiveDate::from_mdf(year, Mdf::new(month, day, flags)?) } /// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date) /// (year and day of the year). /// /// Panics on the out-of-range date and/or invalid day of year. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, Datelike, Weekday}; - /// - /// let d = NaiveDate::from_yo(2015, 73); - /// assert_eq!(d.ordinal(), 73); - /// assert_eq!(d.year(), 2015); - /// assert_eq!(d.month(), 3); - /// assert_eq!(d.day(), 14); - /// assert_eq!(d.iso_week().year(), 2015); - /// assert_eq!(d.iso_week().week(), 11); - /// assert_eq!(d.weekday(), Weekday::Sat); - /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_yo_opt()` instead")] pub fn from_yo(year: i32, ordinal: u32) -> NaiveDate { NaiveDate::from_yo_opt(year, ordinal).expect("invalid or out-of-range date") } @@ -228,7 +303,7 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// /// let from_yo_opt = NaiveDate::from_yo_opt; @@ -240,10 +315,10 @@ impl NaiveDate { /// assert!(from_yo_opt(-4, 366).is_some()); // 5 BCE is a leap year /// assert!(from_yo_opt(400000, 1).is_none()); /// assert!(from_yo_opt(-400000, 1).is_none()); - /// ~~~~ + /// ``` pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> { let flags = YearFlags::from_year(year); - NaiveDate::from_of(year, Of::new(ordinal, flags)) + NaiveDate::from_of(year, Of::new(ordinal, flags)?) } /// Makes a new `NaiveDate` from the [ISO week date](#week-date) @@ -251,22 +326,7 @@ impl NaiveDate { /// The resulting `NaiveDate` may have a different year from the input year. /// /// Panics on the out-of-range date and/or invalid week number. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, Datelike, Weekday}; - /// - /// let d = NaiveDate::from_isoywd(2015, 11, Weekday::Sat); - /// assert_eq!(d.iso_week().year(), 2015); - /// assert_eq!(d.iso_week().week(), 11); - /// assert_eq!(d.weekday(), Weekday::Sat); - /// assert_eq!(d.year(), 2015); - /// assert_eq!(d.month(), 3); - /// assert_eq!(d.day(), 14); - /// assert_eq!(d.ordinal(), 73); // day of year - /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_isoywd_opt()` instead")] pub fn from_isoywd(year: i32, week: u32, weekday: Weekday) -> NaiveDate { NaiveDate::from_isoywd_opt(year, week, weekday).expect("invalid or out-of-range date") } @@ -279,7 +339,7 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Weekday}; /// /// let from_ymd = NaiveDate::from_ymd; @@ -292,11 +352,11 @@ impl NaiveDate { /// /// assert_eq!(from_isoywd_opt(400000, 10, Weekday::Fri), None); /// assert_eq!(from_isoywd_opt(-400000, 10, Weekday::Sat), None); - /// ~~~~ + /// ``` /// /// The year number of ISO week date may differ from that of the calendar date. /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveDate, Weekday}; /// # let from_ymd = NaiveDate::from_ymd; /// # let from_isoywd_opt = NaiveDate::from_isoywd_opt; @@ -314,7 +374,7 @@ impl NaiveDate { /// assert_eq!(from_isoywd_opt(2015, 53, Weekday::Sun), Some(from_ymd(2016, 1, 3))); /// assert_eq!(from_isoywd_opt(2015, 54, Weekday::Mon), None); /// assert_eq!(from_isoywd_opt(2016, 1, Weekday::Mon), Some(from_ymd(2016, 1, 4))); - /// ~~~~ + /// ``` pub fn from_isoywd_opt(year: i32, week: u32, weekday: Weekday) -> Option<NaiveDate> { let flags = YearFlags::from_year(year); let nweeks = flags.nisoweeks(); @@ -327,18 +387,18 @@ impl NaiveDate { let prevflags = YearFlags::from_year(year - 1); NaiveDate::from_of( year - 1, - Of::new(weekord + prevflags.ndays() - delta, prevflags), + Of::new(weekord + prevflags.ndays() - delta, prevflags)?, ) } else { let ordinal = weekord - delta; let ndays = flags.ndays(); if ordinal <= ndays { // this year - NaiveDate::from_of(year, Of::new(ordinal, flags)) + NaiveDate::from_of(year, Of::new(ordinal, flags)?) } else { // ordinal > ndays, next year let nextflags = YearFlags::from_year(year + 1); - NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags)) + NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags)?) } } } else { @@ -350,45 +410,7 @@ impl NaiveDate { /// January 1, 1 being day 1. /// /// Panics if the date is out of range. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, Datelike, Weekday}; - /// - /// let d = NaiveDate::from_num_days_from_ce(735671); - /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE - /// assert_eq!(d.year(), 2015); - /// assert_eq!(d.month(), 3); - /// assert_eq!(d.day(), 14); - /// assert_eq!(d.ordinal(), 73); // day of year - /// assert_eq!(d.iso_week().year(), 2015); - /// assert_eq!(d.iso_week().week(), 11); - /// assert_eq!(d.weekday(), Weekday::Sat); - /// ~~~~ - /// - /// While not directly supported by Chrono, - /// it is easy to convert from the Julian day number - /// (January 1, 4713 BCE in the *Julian* calendar being Day 0) - /// to Gregorian with this method. - /// (Note that this panics when `jd` is out of range.) - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// fn jd_to_date(jd: i32) -> NaiveDate { - /// // keep in mind that the Julian day number is 0-based - /// // while this method requires an 1-based number. - /// NaiveDate::from_num_days_from_ce(jd - 1721425) - /// } - /// - /// // January 1, 4713 BCE in Julian = November 24, 4714 BCE in Gregorian - /// assert_eq!(jd_to_date(0), NaiveDate::from_ymd(-4713, 11, 24)); - /// - /// assert_eq!(jd_to_date(1721426), NaiveDate::from_ymd(1, 1, 1)); - /// assert_eq!(jd_to_date(2450000), NaiveDate::from_ymd(1995, 10, 9)); - /// assert_eq!(jd_to_date(2451545), NaiveDate::from_ymd(2000, 1, 1)); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_num_days_from_ce_opt()` instead")] #[inline] pub fn from_num_days_from_ce(days: i32) -> NaiveDate { NaiveDate::from_num_days_from_ce_opt(days).expect("out-of-range date") @@ -401,11 +423,11 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// /// let from_ndays_opt = NaiveDate::from_num_days_from_ce_opt; - /// let from_ymd = NaiveDate::from_ymd; + /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); /// /// assert_eq!(from_ndays_opt(730_000), Some(from_ymd(1999, 9, 3))); /// assert_eq!(from_ndays_opt(1), Some(from_ymd(1, 1, 1))); @@ -413,13 +435,13 @@ impl NaiveDate { /// assert_eq!(from_ndays_opt(-1), Some(from_ymd(0, 12, 30))); /// assert_eq!(from_ndays_opt(100_000_000), None); /// assert_eq!(from_ndays_opt(-100_000_000), None); - /// ~~~~ + /// ``` pub fn from_num_days_from_ce_opt(days: i32) -> Option<NaiveDate> { let days = days + 365; // make December 31, 1 BCE equal to day 0 let (year_div_400, cycle) = div_mod_floor(days, 146_097); let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32); let flags = YearFlags::from_year_mod_400(year_mod_400 as i32); - NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)) + NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?) } /// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week @@ -432,21 +454,7 @@ impl NaiveDate { /// of `weekday` in `month` (eg. the 6th Friday of March 2017) then this function will panic. /// /// `n` is 1-indexed. Passing `n=0` will cause a panic. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, Weekday}; - /// - /// let from_weekday_of_month = NaiveDate::from_weekday_of_month; - /// let from_ymd = NaiveDate::from_ymd; - /// - /// assert_eq!(from_weekday_of_month(2018, 8, Weekday::Wed, 1), from_ymd(2018, 8, 1)); - /// assert_eq!(from_weekday_of_month(2018, 8, Weekday::Fri, 1), from_ymd(2018, 8, 3)); - /// assert_eq!(from_weekday_of_month(2018, 8, Weekday::Tue, 2), from_ymd(2018, 8, 14)); - /// assert_eq!(from_weekday_of_month(2018, 8, Weekday::Fri, 4), from_ymd(2018, 8, 24)); - /// assert_eq!(from_weekday_of_month(2018, 8, Weekday::Fri, 5), from_ymd(2018, 8, 31)); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_weekday_of_month_opt()` instead")] pub fn from_weekday_of_month(year: i32, month: u32, weekday: Weekday, n: u8) -> NaiveDate { NaiveDate::from_weekday_of_month_opt(year, month, weekday, n).expect("out-of-range date") } @@ -455,11 +463,11 @@ impl NaiveDate { /// since the beginning of the given month. For instance, if you want the 2nd Friday of March /// 2017, you would use `NaiveDate::from_weekday_of_month(2017, 3, Weekday::Fri, 2)`. `n` is 1-indexed. /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Weekday}; /// assert_eq!(NaiveDate::from_weekday_of_month_opt(2017, 3, Weekday::Fri, 2), /// NaiveDate::from_ymd_opt(2017, 3, 10)) - /// ~~~~ + /// ``` /// /// Returns `None` if `n` out-of-range; ie. if `n` is larger than the number of `weekday` in /// `month` (eg. the 6th Friday of March 2017), or if `n == 0`. @@ -472,7 +480,7 @@ impl NaiveDate { if n == 0 { return None; } - let first = NaiveDate::from_ymd(year, month, 1).weekday(); + let first = NaiveDate::from_ymd_opt(year, month, 1)?.weekday(); let first_to_dow = (7 + weekday.number_from_monday() - first.number_from_monday()) % 7; let day = (u32::from(n) - 1) * 7 + first_to_dow + 1; NaiveDate::from_ymd_opt(year, month, day) @@ -484,64 +492,223 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// /// let parse_from_str = NaiveDate::parse_from_str; /// /// assert_eq!(parse_from_str("2015-09-05", "%Y-%m-%d"), - /// Ok(NaiveDate::from_ymd(2015, 9, 5))); + /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap())); /// assert_eq!(parse_from_str("5sep2015", "%d%b%Y"), - /// Ok(NaiveDate::from_ymd(2015, 9, 5))); - /// ~~~~ + /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap())); + /// ``` /// /// Time and offset is ignored for the purpose of parsing. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveDate; /// # let parse_from_str = NaiveDate::parse_from_str; /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), - /// Ok(NaiveDate::from_ymd(2014, 5, 17))); - /// ~~~~ + /// Ok(NaiveDate::from_ymd_opt(2014, 5, 17).unwrap())); + /// ``` /// /// Out-of-bound dates or insufficient fields are errors. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveDate; /// # let parse_from_str = NaiveDate::parse_from_str; /// assert!(parse_from_str("2015/9", "%Y/%m").is_err()); /// assert!(parse_from_str("2015/9/31", "%Y/%m/%d").is_err()); - /// ~~~~ + /// ``` /// /// All parsed fields should be consistent to each other, otherwise it's an error. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveDate; /// # let parse_from_str = NaiveDate::parse_from_str; /// assert!(parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err()); - /// ~~~~ + /// ``` pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDate> { let mut parsed = Parsed::new(); parse(&mut parsed, s, StrftimeItems::new(fmt))?; parsed.to_naive_date() } + /// Add a duration in [`Months`] to the date + /// + /// If the day would be out of range for the resulting month, use the last day for that month. + /// + /// Returns `None` if the resulting date would be out of range. + /// + /// ``` + /// # use chrono::{NaiveDate, Months}; + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_add_months(Months::new(6)), + /// Some(NaiveDate::from_ymd_opt(2022, 8, 20).unwrap()) + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_months(Months::new(2)), + /// Some(NaiveDate::from_ymd_opt(2022, 9, 30).unwrap()) + /// ); + /// ``` + pub fn checked_add_months(self, months: Months) -> Option<Self> { + if months.0 == 0 { + return Some(self); + } + + match months.0 <= core::i32::MAX as u32 { + true => self.diff_months(months.0 as i32), + false => None, + } + } + + /// Subtract a duration in [`Months`] from the date + /// + /// If the day would be out of range for the resulting month, use the last day for that month. + /// + /// Returns `None` if the resulting date would be out of range. + /// + /// ``` + /// # use chrono::{NaiveDate, Months}; + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_months(Months::new(6)), + /// Some(NaiveDate::from_ymd_opt(2021, 8, 20).unwrap()) + /// ); + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap() + /// .checked_sub_months(Months::new(core::i32::MAX as u32 + 1)), + /// None + /// ); + /// ``` + pub fn checked_sub_months(self, months: Months) -> Option<Self> { + if months.0 == 0 { + return Some(self); + } + + // Copy `i32::MAX` here so we don't have to do a complicated cast + match months.0 <= 2_147_483_647 { + true => self.diff_months(-(months.0 as i32)), + false => None, + } + } + + fn diff_months(self, months: i32) -> Option<Self> { + let (years, left) = ((months / 12), (months % 12)); + + // Determine new year (without taking months into account for now + + let year = if (years > 0 && years > (MAX_YEAR - self.year())) + || (years < 0 && years < (MIN_YEAR - self.year())) + { + return None; + } else { + self.year() + years + }; + + // Determine new month + + let month = self.month() as i32 + left; + let (year, month) = if month <= 0 { + if year == MIN_YEAR { + return None; + } + + (year - 1, month + 12) + } else if month > 12 { + if year == MAX_YEAR { + return None; + } + + (year + 1, month - 12) + } else { + (year, month) + }; + + // Clamp original day in case new month is shorter + + let flags = YearFlags::from_year(year); + let feb_days = if flags.ndays() == 366 { 29 } else { 28 }; + let days = [31, feb_days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + let day = Ord::min(self.day(), days[(month - 1) as usize]); + + NaiveDate::from_mdf(year, Mdf::new(month as u32, day, flags)?) + } + + /// Add a duration in [`Days`] to the date + /// + /// Returns `None` if the resulting date would be out of range. + /// + /// ``` + /// # use chrono::{NaiveDate, Days}; + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_add_days(Days::new(9)), + /// Some(NaiveDate::from_ymd_opt(2022, 3, 1).unwrap()) + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_days(Days::new(2)), + /// Some(NaiveDate::from_ymd_opt(2022, 8, 2).unwrap()) + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_days(Days::new(1000000000000)), + /// None + /// ); + /// ``` + pub fn checked_add_days(self, days: Days) -> Option<Self> { + if days.0 == 0 { + return Some(self); + } + + i64::try_from(days.0).ok().and_then(|d| self.diff_days(d)) + } + + /// Subtract a duration in [`Days`] from the date + /// + /// Returns `None` if the resulting date would be out of range. + /// + /// ``` + /// # use chrono::{NaiveDate, Days}; + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_days(Days::new(6)), + /// Some(NaiveDate::from_ymd_opt(2022, 2, 14).unwrap()) + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_days(Days::new(1000000000000)), + /// None + /// ); + /// ``` + pub fn checked_sub_days(self, days: Days) -> Option<Self> { + if days.0 == 0 { + return Some(self); + } + + i64::try_from(days.0).ok().and_then(|d| self.diff_days(-d)) + } + + fn diff_days(self, days: i64) -> Option<Self> { + let secs = days.checked_mul(86400)?; // 86400 seconds in one day + if secs >= core::i64::MAX / 1000 || secs <= core::i64::MIN / 1000 { + return None; // See the `time` 0.1 crate. Outside these bounds, `Duration::seconds` will panic + } + self.checked_add_signed(Duration::seconds(secs)) + } + /// Makes a new `NaiveDateTime` from the current date and given `NaiveTime`. /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime}; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); - /// let t = NaiveTime::from_hms_milli(12, 34, 56, 789); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); + /// let t = NaiveTime::from_hms_milli_opt(12, 34, 56, 789).unwrap(); /// /// let dt: NaiveDateTime = d.and_time(t); /// assert_eq!(dt.date(), d); /// assert_eq!(dt.time(), t); - /// ~~~~ + /// ``` #[inline] - pub fn and_time(&self, time: NaiveTime) -> NaiveDateTime { + pub const fn and_time(&self, time: NaiveTime) -> NaiveDateTime { NaiveDateTime::new(*self, time) } @@ -551,19 +718,7 @@ impl NaiveDate { /// use `NaiveDate::and_hms_*` methods with a subsecond parameter instead. /// /// Panics on invalid hour, minute and/or second. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday}; - /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); - /// - /// let dt: NaiveDateTime = d.and_hms(12, 34, 56); - /// assert_eq!(dt.year(), 2015); - /// assert_eq!(dt.weekday(), Weekday::Wed); - /// assert_eq!(dt.second(), 56); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `and_hms_opt()` instead")] #[inline] pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> NaiveDateTime { self.and_hms_opt(hour, min, sec).expect("invalid time") @@ -578,15 +733,15 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); /// assert!(d.and_hms_opt(12, 34, 56).is_some()); /// assert!(d.and_hms_opt(12, 34, 60).is_none()); // use `and_hms_milli_opt` instead /// assert!(d.and_hms_opt(12, 60, 56).is_none()); /// assert!(d.and_hms_opt(24, 34, 56).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> { NaiveTime::from_hms_opt(hour, min, sec).map(|time| self.and_time(time)) @@ -598,20 +753,7 @@ impl NaiveDate { /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling). /// /// Panics on invalid hour, minute, second and/or millisecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday}; - /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); - /// - /// let dt: NaiveDateTime = d.and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.year(), 2015); - /// assert_eq!(dt.weekday(), Weekday::Wed); - /// assert_eq!(dt.second(), 56); - /// assert_eq!(dt.nanosecond(), 789_000_000); - /// ~~~~ + #[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) -> NaiveDateTime { self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time") @@ -626,17 +768,17 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); /// assert!(d.and_hms_milli_opt(12, 34, 56, 789).is_some()); /// assert!(d.and_hms_milli_opt(12, 34, 59, 1_789).is_some()); // leap second /// assert!(d.and_hms_milli_opt(12, 34, 59, 2_789).is_none()); /// assert!(d.and_hms_milli_opt(12, 34, 60, 789).is_none()); /// assert!(d.and_hms_milli_opt(12, 60, 56, 789).is_none()); /// assert!(d.and_hms_milli_opt(24, 34, 56, 789).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn and_hms_milli_opt( &self, @@ -657,17 +799,18 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday}; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); /// /// let dt: NaiveDateTime = d.and_hms_micro(12, 34, 56, 789_012); /// assert_eq!(dt.year(), 2015); /// assert_eq!(dt.weekday(), Weekday::Wed); /// assert_eq!(dt.second(), 56); /// assert_eq!(dt.nanosecond(), 789_012_000); - /// ~~~~ + /// ``` + #[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) -> NaiveDateTime { self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time") @@ -682,17 +825,17 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); /// assert!(d.and_hms_micro_opt(12, 34, 56, 789_012).is_some()); /// assert!(d.and_hms_micro_opt(12, 34, 59, 1_789_012).is_some()); // leap second /// assert!(d.and_hms_micro_opt(12, 34, 59, 2_789_012).is_none()); /// assert!(d.and_hms_micro_opt(12, 34, 60, 789_012).is_none()); /// assert!(d.and_hms_micro_opt(12, 60, 56, 789_012).is_none()); /// assert!(d.and_hms_micro_opt(24, 34, 56, 789_012).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn and_hms_micro_opt( &self, @@ -710,20 +853,7 @@ impl NaiveDate { /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling). /// /// Panics on invalid hour, minute, second and/or nanosecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday}; - /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); - /// - /// let dt: NaiveDateTime = d.and_hms_nano(12, 34, 56, 789_012_345); - /// assert_eq!(dt.year(), 2015); - /// assert_eq!(dt.weekday(), Weekday::Wed); - /// assert_eq!(dt.second(), 56); - /// assert_eq!(dt.nanosecond(), 789_012_345); - /// ~~~~ + #[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) -> NaiveDateTime { self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time") @@ -738,17 +868,17 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); /// assert!(d.and_hms_nano_opt(12, 34, 56, 789_012_345).is_some()); /// assert!(d.and_hms_nano_opt(12, 34, 59, 1_789_012_345).is_some()); // leap second /// assert!(d.and_hms_nano_opt(12, 34, 59, 2_789_012_345).is_none()); /// assert!(d.and_hms_nano_opt(12, 34, 60, 789_012_345).is_none()); /// assert!(d.and_hms_nano_opt(12, 60, 56, 789_012_345).is_none()); /// assert!(d.and_hms_nano_opt(24, 34, 56, 789_012_345).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn and_hms_nano_opt( &self, @@ -768,7 +898,7 @@ impl NaiveDate { /// Returns the packed ordinal-flags. #[inline] - fn of(&self) -> Of { + const fn of(&self) -> Of { Of((self.ymdf & 0b1_1111_1111_1111) as u32) } @@ -796,16 +926,7 @@ impl NaiveDate { /// Makes a new `NaiveDate` for the next calendar date. /// /// Panics when `self` is the last representable date. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).succ(), NaiveDate::from_ymd(2015, 6, 4)); - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 30).succ(), NaiveDate::from_ymd(2015, 7, 1)); - /// assert_eq!(NaiveDate::from_ymd(2015, 12, 31).succ(), NaiveDate::from_ymd(2016, 1, 1)); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `succ_opt()` instead")] #[inline] pub fn succ(&self) -> NaiveDate { self.succ_opt().expect("out of bound") @@ -817,14 +938,13 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; - /// use chrono::naive::MAX_DATE; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).succ_opt(), - /// Some(NaiveDate::from_ymd(2015, 6, 4))); - /// assert_eq!(MAX_DATE.succ_opt(), None); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 6, 3).unwrap().succ_opt(), + /// Some(NaiveDate::from_ymd_opt(2015, 6, 4).unwrap())); + /// assert_eq!(NaiveDate::MAX.succ_opt(), None); + /// ``` #[inline] pub fn succ_opt(&self) -> Option<NaiveDate> { self.with_of(self.of().succ()).or_else(|| NaiveDate::from_ymd_opt(self.year() + 1, 1, 1)) @@ -833,16 +953,7 @@ impl NaiveDate { /// Makes a new `NaiveDate` for the previous calendar date. /// /// Panics when `self` is the first representable date. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).pred(), NaiveDate::from_ymd(2015, 6, 2)); - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 1).pred(), NaiveDate::from_ymd(2015, 5, 31)); - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).pred(), NaiveDate::from_ymd(2014, 12, 31)); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `pred_opt()` instead")] #[inline] pub fn pred(&self) -> NaiveDate { self.pred_opt().expect("out of bound") @@ -854,14 +965,13 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; - /// use chrono::naive::MIN_DATE; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).pred_opt(), - /// Some(NaiveDate::from_ymd(2015, 6, 2))); - /// assert_eq!(MIN_DATE.pred_opt(), None); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 6, 3).unwrap().pred_opt(), + /// Some(NaiveDate::from_ymd_opt(2015, 6, 2).unwrap())); + /// assert_eq!(NaiveDate::MIN.pred_opt(), None); + /// ``` #[inline] pub fn pred_opt(&self) -> Option<NaiveDate> { self.with_of(self.of().pred()).or_else(|| NaiveDate::from_ymd_opt(self.year() - 1, 12, 31)) @@ -873,32 +983,29 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveDate}; - /// use chrono::naive::MAX_DATE; /// - /// let d = NaiveDate::from_ymd(2015, 9, 5); + /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(d.checked_add_signed(Duration::days(40)), - /// Some(NaiveDate::from_ymd(2015, 10, 15))); + /// Some(NaiveDate::from_ymd_opt(2015, 10, 15).unwrap())); /// assert_eq!(d.checked_add_signed(Duration::days(-40)), - /// Some(NaiveDate::from_ymd(2015, 7, 27))); + /// Some(NaiveDate::from_ymd_opt(2015, 7, 27).unwrap())); /// assert_eq!(d.checked_add_signed(Duration::days(1_000_000_000)), None); /// assert_eq!(d.checked_add_signed(Duration::days(-1_000_000_000)), None); - /// assert_eq!(MAX_DATE.checked_add_signed(Duration::days(1)), None); - /// # } - /// ~~~~ + /// assert_eq!(NaiveDate::MAX.checked_add_signed(Duration::days(1)), None); + /// ``` pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDate> { let year = self.year(); let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400); let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal()); - let cycle = try_opt!((cycle as i32).checked_add(try_opt!(rhs.num_days().to_i32()))); + let cycle = (cycle as i32).checked_add(rhs.num_days().to_i32()?)?; let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097); year_div_400 += cycle_div_400y; let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32); let flags = YearFlags::from_year_mod_400(year_mod_400 as i32); - NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)) + NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?) } /// Subtracts the `days` part of given `Duration` from the current date. @@ -907,32 +1014,29 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveDate}; - /// use chrono::naive::MIN_DATE; /// - /// let d = NaiveDate::from_ymd(2015, 9, 5); + /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(d.checked_sub_signed(Duration::days(40)), - /// Some(NaiveDate::from_ymd(2015, 7, 27))); + /// Some(NaiveDate::from_ymd_opt(2015, 7, 27).unwrap())); /// assert_eq!(d.checked_sub_signed(Duration::days(-40)), - /// Some(NaiveDate::from_ymd(2015, 10, 15))); + /// Some(NaiveDate::from_ymd_opt(2015, 10, 15).unwrap())); /// assert_eq!(d.checked_sub_signed(Duration::days(1_000_000_000)), None); /// assert_eq!(d.checked_sub_signed(Duration::days(-1_000_000_000)), None); - /// assert_eq!(MIN_DATE.checked_sub_signed(Duration::days(1)), None); - /// # } - /// ~~~~ + /// assert_eq!(NaiveDate::MIN.checked_sub_signed(Duration::days(1)), None); + /// ``` pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDate> { let year = self.year(); let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400); let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal()); - let cycle = try_opt!((cycle as i32).checked_sub(try_opt!(rhs.num_days().to_i32()))); + let cycle = (cycle as i32).checked_sub(rhs.num_days().to_i32()?)?; let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097); year_div_400 += cycle_div_400y; let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32); let flags = YearFlags::from_year_mod_400(year_mod_400 as i32); - NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)) + NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?) } /// Subtracts another `NaiveDate` from the current date. @@ -943,8 +1047,7 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveDate}; /// /// let from_ymd = NaiveDate::from_ymd; @@ -957,8 +1060,7 @@ impl NaiveDate { /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 1, 1)), Duration::days(365)); /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2010, 1, 1)), Duration::days(365*4 + 1)); /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(1614, 1, 1)), Duration::days(365*400 + 97)); - /// # } - /// ~~~~ + /// ``` pub fn signed_duration_since(self, rhs: NaiveDate) -> OldDuration { let year1 = self.year(); let year2 = rhs.year(); @@ -971,6 +1073,19 @@ impl NaiveDate { ) } + /// Returns the number of whole years from the given `base` until `self`. + pub fn years_since(&self, base: Self) -> Option<u32> { + let mut years = self.year() - base.year(); + if (self.month(), self.day()) < (base.month(), base.day()) { + years -= 1; + } + + match years >= 0 { + true => Some(years as u32), + false => None, + } + } + /// Formats the date with the specified formatting items. /// Otherwise it is the same as the ordinary `format` method. /// @@ -979,26 +1094,27 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// use chrono::format::strftime::StrftimeItems; /// /// let fmt = StrftimeItems::new("%Y-%m-%d"); - /// let d = NaiveDate::from_ymd(2015, 9, 5); + /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(d.format_with_items(fmt.clone()).to_string(), "2015-09-05"); /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05"); - /// ~~~~ + /// ``` /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveDate; /// # use chrono::format::strftime::StrftimeItems; /// # let fmt = StrftimeItems::new("%Y-%m-%d").clone(); - /// # let d = NaiveDate::from_ymd(2015, 9, 5); + /// # let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(format!("{}", d.format_with_items(fmt)), "2015-09-05"); - /// ~~~~ + /// ``` #[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 @@ -1024,29 +1140,61 @@ impl NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveDate; /// - /// let d = NaiveDate::from_ymd(2015, 9, 5); + /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05"); /// assert_eq!(d.format("%A, %-d %B, %C%y").to_string(), "Saturday, 5 September, 2015"); - /// ~~~~ + /// ``` /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveDate; - /// # let d = NaiveDate::from_ymd(2015, 9, 5); + /// # let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(format!("{}", d.format("%Y-%m-%d")), "2015-09-05"); /// assert_eq!(format!("{}", d.format("%A, %-d %B, %C%y")), "Saturday, 5 September, 2015"); - /// ~~~~ + /// ``` #[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)) } - /// Returns an iterator that steps by days until the last representable date. + /// 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, + items: I, + locale: Locale, + ) -> DelayedFormat<I> + where + I: Iterator<Item = B> + Clone, + B: Borrow<Item<'a>>, + { + DelayedFormat::new_with_locale(Some(*self), None, items, locale) + } + + /// Formats the date with the specified format string and locale. + /// + /// 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, + fmt: &'a str, + locale: Locale, + ) -> DelayedFormat<StrftimeItems<'a>> { + self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale) + } + + /// Returns an iterator that steps by days across all representable dates. /// /// # Example /// @@ -1054,25 +1202,30 @@ impl NaiveDate { /// # use chrono::NaiveDate; /// /// let expected = [ - /// NaiveDate::from_ymd(2016, 2, 27), - /// NaiveDate::from_ymd(2016, 2, 28), - /// NaiveDate::from_ymd(2016, 2, 29), - /// NaiveDate::from_ymd(2016, 3, 1), + /// NaiveDate::from_ymd_opt(2016, 2, 27).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 2, 28).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 2, 29).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 3, 1).unwrap(), /// ]; /// /// let mut count = 0; - /// for (idx, d) in NaiveDate::from_ymd(2016, 2, 27).iter_days().take(4).enumerate() { + /// for (idx, d) in NaiveDate::from_ymd_opt(2016, 2, 27).unwrap().iter_days().take(4).enumerate() { /// assert_eq!(d, expected[idx]); /// count += 1; /// } /// assert_eq!(count, 4); + /// + /// for d in NaiveDate::from_ymd_opt(2016, 3, 1).unwrap().iter_days().rev().take(4) { + /// count -= 1; + /// assert_eq!(d, expected[count]); + /// } /// ``` #[inline] - pub fn iter_days(&self) -> NaiveDateDaysIterator { + pub const fn iter_days(&self) -> NaiveDateDaysIterator { NaiveDateDaysIterator { value: *self } } - /// Returns an iterator that steps by weeks until the last representable date. + /// Returns an iterator that steps by weeks across all representable dates. /// /// # Example /// @@ -1080,23 +1233,40 @@ impl NaiveDate { /// # use chrono::NaiveDate; /// /// let expected = [ - /// NaiveDate::from_ymd(2016, 2, 27), - /// NaiveDate::from_ymd(2016, 3, 5), - /// NaiveDate::from_ymd(2016, 3, 12), - /// NaiveDate::from_ymd(2016, 3, 19), + /// NaiveDate::from_ymd_opt(2016, 2, 27).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 3, 5).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 3, 12).unwrap(), + /// NaiveDate::from_ymd_opt(2016, 3, 19).unwrap(), /// ]; /// /// let mut count = 0; - /// for (idx, d) in NaiveDate::from_ymd(2016, 2, 27).iter_weeks().take(4).enumerate() { + /// for (idx, d) in NaiveDate::from_ymd_opt(2016, 2, 27).unwrap().iter_weeks().take(4).enumerate() { /// assert_eq!(d, expected[idx]); /// count += 1; /// } /// assert_eq!(count, 4); + /// + /// for d in NaiveDate::from_ymd_opt(2016, 3, 19).unwrap().iter_weeks().rev().take(4) { + /// count -= 1; + /// assert_eq!(d, expected[count]); + /// } /// ``` #[inline] - pub fn iter_weeks(&self) -> NaiveDateWeeksIterator { + pub const fn iter_weeks(&self) -> NaiveDateWeeksIterator { NaiveDateWeeksIterator { value: *self } } + + /// Returns the [`NaiveWeek`] that the date belongs to, starting with the [`Weekday`] + /// specified. + #[inline] + pub const fn week(&self, start: Weekday) -> NaiveWeek { + NaiveWeek { date: *self, start } + } + + /// The minimum possible `NaiveDate` (January 1, 262145 BCE). + pub const MIN: NaiveDate = NaiveDate { ymdf: (MIN_YEAR << 13) | (1 << 4) | 0o07 /*FE*/ }; + /// The maximum possible `NaiveDate` (December 31, 262143 CE). + pub const MAX: NaiveDate = NaiveDate { ymdf: (MAX_YEAR << 13) | (365 << 4) | 0o17 /*F*/ }; } impl Datelike for NaiveDate { @@ -1104,12 +1274,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).year(), 2015); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).year(), -308); // 309 BCE - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().year(), 2015); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().year(), -308); // 309 BCE + /// ``` #[inline] fn year(&self) -> i32 { self.ymdf >> 13 @@ -1121,12 +1291,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).month(), 9); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).month(), 3); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().month(), 9); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().month(), 3); + /// ``` #[inline] fn month(&self) -> u32 { self.mdf().month() @@ -1138,12 +1308,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).month0(), 8); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).month0(), 2); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().month0(), 8); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().month0(), 2); + /// ``` #[inline] fn month0(&self) -> u32 { self.mdf().month() - 1 @@ -1155,24 +1325,24 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).day(), 8); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).day(), 14); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().day(), 8); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().day(), 14); + /// ``` /// /// Combined with [`NaiveDate::pred`](#method.pred), /// one can determine the number of days in a particular month. /// (Note that this panics when `year` is out of range.) /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// /// fn ndays_in_month(year: i32, month: u32) -> u32 { /// // the first day of the next month... /// let (y, m) = if month == 12 { (year + 1, 1) } else { (year, month + 1) }; - /// let d = NaiveDate::from_ymd(y, m, 1); + /// let d = NaiveDate::from_ymd_opt(y, m, 1).unwrap(); /// /// // ...is preceded by the last day of the original month /// d.pred().day() @@ -1183,7 +1353,7 @@ impl Datelike for NaiveDate { /// assert_eq!(ndays_in_month(2015, 12), 31); /// assert_eq!(ndays_in_month(2016, 2), 29); /// assert_eq!(ndays_in_month(2017, 2), 28); - /// ~~~~ + /// ``` #[inline] fn day(&self) -> u32 { self.mdf().day() @@ -1195,12 +1365,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).day0(), 7); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).day0(), 13); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().day0(), 7); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().day0(), 13); + /// ``` #[inline] fn day0(&self) -> u32 { self.mdf().day() - 1 @@ -1212,23 +1382,23 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).ordinal(), 251); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).ordinal(), 74); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().ordinal(), 251); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().ordinal(), 74); + /// ``` /// /// Combined with [`NaiveDate::pred`](#method.pred), /// one can determine the number of days in a particular year. /// (Note that this panics when `year` is out of range.) /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// /// fn ndays_in_year(year: i32) -> u32 { /// // the first day of the next year... - /// let d = NaiveDate::from_ymd(year + 1, 1, 1); + /// let d = NaiveDate::from_ymd_opt(year + 1, 1, 1).unwrap(); /// /// // ...is preceded by the last day of the original year /// d.pred().ordinal() @@ -1239,7 +1409,7 @@ impl Datelike for NaiveDate { /// assert_eq!(ndays_in_year(2017), 365); /// assert_eq!(ndays_in_year(2000), 366); /// assert_eq!(ndays_in_year(2100), 365); - /// ~~~~ + /// ``` #[inline] fn ordinal(&self) -> u32 { self.of().ordinal() @@ -1251,12 +1421,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).ordinal0(), 250); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).ordinal0(), 73); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().ordinal0(), 250); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().ordinal0(), 73); + /// ``` #[inline] fn ordinal0(&self) -> u32 { self.of().ordinal() - 1 @@ -1266,12 +1436,12 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike, Weekday}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).weekday(), Weekday::Tue); - /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).weekday(), Weekday::Fri); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().weekday(), Weekday::Tue); + /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().weekday(), Weekday::Fri); + /// ``` #[inline] fn weekday(&self) -> Weekday { self.of().weekday() @@ -1288,22 +1458,22 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_year(2016), - /// Some(NaiveDate::from_ymd(2016, 9, 8))); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_year(-308), - /// Some(NaiveDate::from_ymd(-308, 9, 8))); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_year(2016), + /// Some(NaiveDate::from_ymd_opt(2016, 9, 8).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_year(-308), + /// Some(NaiveDate::from_ymd_opt(-308, 9, 8).unwrap())); + /// ``` /// /// A leap day (February 29) is a good example that this method can return `None`. /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveDate, Datelike}; - /// assert!(NaiveDate::from_ymd(2016, 2, 29).with_year(2015).is_none()); - /// assert!(NaiveDate::from_ymd(2016, 2, 29).with_year(2020).is_some()); - /// ~~~~ + /// assert!(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().with_year(2015).is_none()); + /// assert!(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().with_year(2020).is_some()); + /// ``` #[inline] fn with_year(&self, year: i32) -> Option<NaiveDate> { // we need to operate with `mdf` since we should keep the month and day number as is @@ -1322,17 +1492,17 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month(10), - /// Some(NaiveDate::from_ymd(2015, 10, 8))); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month(13), None); // no month 13 - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).with_month(2), None); // no February 30 - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month(10), + /// Some(NaiveDate::from_ymd_opt(2015, 10, 8).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month(13), None); // no month 13 + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().with_month(2), None); // no February 30 + /// ``` #[inline] fn with_month(&self, month: u32) -> Option<NaiveDate> { - self.with_mdf(self.mdf().with_month(month)) + self.with_mdf(self.mdf().with_month(month)?) } /// Makes a new `NaiveDate` with the month number (starting from 0) changed. @@ -1341,17 +1511,17 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month0(9), - /// Some(NaiveDate::from_ymd(2015, 10, 8))); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month0(12), None); // no month 13 - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).with_month0(1), None); // no February 30 - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month0(9), + /// Some(NaiveDate::from_ymd_opt(2015, 10, 8).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month0(12), None); // no month 13 + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().with_month0(1), None); // no February 30 + /// ``` #[inline] fn with_month0(&self, month0: u32) -> Option<NaiveDate> { - self.with_mdf(self.mdf().with_month(month0 + 1)) + self.with_mdf(self.mdf().with_month(month0 + 1)?) } /// Makes a new `NaiveDate` with the day of month (starting from 1) changed. @@ -1360,17 +1530,17 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day(30), - /// Some(NaiveDate::from_ymd(2015, 9, 30))); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day(31), + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day(30), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day(31), /// None); // no September 31 - /// ~~~~ + /// ``` #[inline] fn with_day(&self, day: u32) -> Option<NaiveDate> { - self.with_mdf(self.mdf().with_day(day)) + self.with_mdf(self.mdf().with_day(day)?) } /// Makes a new `NaiveDate` with the day of month (starting from 0) changed. @@ -1379,17 +1549,17 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day0(29), - /// Some(NaiveDate::from_ymd(2015, 9, 30))); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day0(30), + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day0(29), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day0(30), /// None); // no September 31 - /// ~~~~ + /// ``` #[inline] fn with_day0(&self, day0: u32) -> Option<NaiveDate> { - self.with_mdf(self.mdf().with_day(day0 + 1)) + self.with_mdf(self.mdf().with_day(day0 + 1)?) } /// Makes a new `NaiveDate` with the day of year (starting from 1) changed. @@ -1398,22 +1568,22 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal(60), - /// Some(NaiveDate::from_ymd(2015, 3, 1))); - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal(366), + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal(60), + /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal(366), /// None); // 2015 had only 365 days /// - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal(60), - /// Some(NaiveDate::from_ymd(2016, 2, 29))); - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal(366), - /// Some(NaiveDate::from_ymd(2016, 12, 31))); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal(60), + /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal(366), + /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap())); + /// ``` #[inline] fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> { - self.with_of(self.of().with_ordinal(ordinal)) + self.with_of(self.of().with_ordinal(ordinal)?) } /// Makes a new `NaiveDate` with the day of year (starting from 0) changed. @@ -1422,22 +1592,22 @@ impl Datelike for NaiveDate { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike}; /// - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2015, 3, 1))); - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal0(365), + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal0(59), + /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal0(365), /// None); // 2015 had only 365 days /// - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2016, 2, 29))); - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal0(365), - /// Some(NaiveDate::from_ymd(2016, 12, 31))); - /// ~~~~ + /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal0(59), + /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap())); + /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal0(365), + /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap())); + /// ``` #[inline] fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> { - self.with_of(self.of().with_ordinal(ordinal0 + 1)) + self.with_of(self.of().with_ordinal(ordinal0 + 1)?) } } @@ -1449,8 +1619,7 @@ impl Datelike for NaiveDate { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveDate}; /// /// let from_ymd = NaiveDate::from_ymd; @@ -1463,8 +1632,7 @@ impl Datelike for NaiveDate { /// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(364), from_ymd(2014, 12, 31)); /// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*4 + 1), from_ymd(2018, 1, 1)); /// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*400 + 97), from_ymd(2414, 1, 1)); -/// # } -/// ~~~~ +/// ``` impl Add<OldDuration> for NaiveDate { type Output = NaiveDate; @@ -1481,6 +1649,75 @@ impl AddAssign<OldDuration> for NaiveDate { } } +impl Add<Months> for NaiveDate { + type Output = NaiveDate; + + /// An addition of months to `NaiveDate` clamped to valid days in resulting month. + /// + /// # Panics + /// + /// Panics if the resulting date would be out of range. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDate, Months}; + /// + /// let from_ymd = NaiveDate::from_ymd; + /// + /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(1), from_ymd(2014, 2, 1)); + /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(11), from_ymd(2014, 12, 1)); + /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(12), from_ymd(2015, 1, 1)); + /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(13), from_ymd(2015, 2, 1)); + /// assert_eq!(from_ymd(2014, 1, 31) + Months::new(1), from_ymd(2014, 2, 28)); + /// assert_eq!(from_ymd(2020, 1, 31) + Months::new(1), from_ymd(2020, 2, 29)); + /// ``` + fn add(self, months: Months) -> Self::Output { + self.checked_add_months(months).unwrap() + } +} + +impl Sub<Months> for NaiveDate { + type Output = NaiveDate; + + /// A subtraction of Months from `NaiveDate` clamped to valid days in resulting month. + /// + /// # Panics + /// + /// Panics if the resulting date would be out of range. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDate, Months}; + /// + /// let from_ymd = NaiveDate::from_ymd; + /// + /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(11), from_ymd(2013, 2, 1)); + /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(12), from_ymd(2013, 1, 1)); + /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(13), from_ymd(2012, 12, 1)); + /// ``` + fn sub(self, months: Months) -> Self::Output { + self.checked_sub_months(months).unwrap() + } +} + +impl Add<Days> for NaiveDate { + type Output = NaiveDate; + + fn add(self, days: Days) -> Self::Output { + self.checked_add_days(days).unwrap() + } +} + +impl Sub<Days> for NaiveDate { + type Output = NaiveDate; + + fn sub(self, days: Days) -> Self::Output { + self.checked_sub_days(days).unwrap() + } +} + /// A subtraction of `Duration` from `NaiveDate` discards the fractional days, /// rounding to the closest integral number of days towards `Duration::zero()`. /// It is the same as the addition with a negated `Duration`. @@ -1490,8 +1727,7 @@ impl AddAssign<OldDuration> for NaiveDate { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveDate}; /// /// let from_ymd = NaiveDate::from_ymd; @@ -1504,8 +1740,7 @@ impl AddAssign<OldDuration> for NaiveDate { /// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(364), from_ymd(2013, 1, 2)); /// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*4 + 1), from_ymd(2010, 1, 1)); /// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*400 + 97), from_ymd(1614, 1, 1)); -/// # } -/// ~~~~ +/// ``` impl Sub<OldDuration> for NaiveDate { type Output = NaiveDate; @@ -1533,8 +1768,7 @@ impl SubAssign<OldDuration> for NaiveDate { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveDate}; /// /// let from_ymd = NaiveDate::from_ymd; @@ -1546,8 +1780,7 @@ impl SubAssign<OldDuration> for NaiveDate { /// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2013, 1, 1), Duration::days(365)); /// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2010, 1, 1), Duration::days(365*4 + 1)); /// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(1614, 1, 1), Duration::days(365*400 + 97)); -/// # } -/// ~~~~ +/// ``` impl Sub<NaiveDate> for NaiveDate { type Output = OldDuration; @@ -1567,24 +1800,35 @@ impl Iterator for NaiveDateDaysIterator { type Item = NaiveDate; fn next(&mut self) -> Option<Self::Item> { - if self.value == MAX_DATE { + if self.value == NaiveDate::MAX { return None; } - // current < MAX_DATE from here on: + // current < NaiveDate::MAX from here on: let current = self.value; - // This can't panic because current is < MAX_DATE: - self.value = current.succ(); + // This can't panic because current is < NaiveDate::MAX: + self.value = current.succ_opt().unwrap(); Some(current) } fn size_hint(&self) -> (usize, Option<usize>) { - let exact_size = MAX_DATE.signed_duration_since(self.value).num_days(); + let exact_size = NaiveDate::MAX.signed_duration_since(self.value).num_days(); (exact_size as usize, Some(exact_size as usize)) } } impl ExactSizeIterator for NaiveDateDaysIterator {} +impl DoubleEndedIterator for NaiveDateDaysIterator { + fn next_back(&mut self) -> Option<Self::Item> { + if self.value == NaiveDate::MIN { + return None; + } + let current = self.value; + self.value = current.pred_opt().unwrap(); + Some(current) + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)] pub struct NaiveDateWeeksIterator { value: NaiveDate, @@ -1594,7 +1838,7 @@ impl Iterator for NaiveDateWeeksIterator { type Item = NaiveDate; fn next(&mut self) -> Option<Self::Item> { - if MAX_DATE - self.value < OldDuration::weeks(1) { + if NaiveDate::MAX - self.value < OldDuration::weeks(1) { return None; } let current = self.value; @@ -1603,13 +1847,24 @@ impl Iterator for NaiveDateWeeksIterator { } fn size_hint(&self) -> (usize, Option<usize>) { - let exact_size = MAX_DATE.signed_duration_since(self.value).num_weeks(); + let exact_size = NaiveDate::MAX.signed_duration_since(self.value).num_weeks(); (exact_size as usize, Some(exact_size as usize)) } } impl ExactSizeIterator for NaiveDateWeeksIterator {} +impl DoubleEndedIterator for NaiveDateWeeksIterator { + fn next_back(&mut self) -> Option<Self::Item> { + if self.value - NaiveDate::MIN < OldDuration::weeks(1) { + return None; + } + let current = self.value; + self.value = current - OldDuration::weeks(1); + Some(current) + } +} + // TODO: NaiveDateDaysIterator and NaiveDateWeeksIterator should implement FusedIterator, // TrustedLen, and Step once they becomes stable. // See: https://github.com/chronotope/chrono/issues/208 @@ -1621,31 +1876,39 @@ impl ExactSizeIterator for NaiveDateWeeksIterator {} /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveDate; /// -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(2015, 9, 5)), "2015-09-05"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( 0, 1, 1)), "0000-01-01"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(9999, 12, 31)), "9999-12-31"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()), "2015-09-05"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( 0, 1, 1).unwrap()), "0000-01-01"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(9999, 12, 31).unwrap()), "9999-12-31"); +/// ``` /// /// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE. /// -/// ~~~~ +/// ``` /// # use chrono::NaiveDate; -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( -1, 1, 1)), "-0001-01-01"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(10000, 12, 31)), "+10000-12-31"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( -1, 1, 1).unwrap()), "-0001-01-01"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(10000, 12, 31).unwrap()), "+10000-12-31"); +/// ``` impl fmt::Debug for NaiveDate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use core::fmt::Write; + let year = self.year(); let mdf = self.mdf(); - if 0 <= year && year <= 9999 { - write!(f, "{:04}-{:02}-{:02}", year, mdf.month(), mdf.day()) + if (0..=9999).contains(&year) { + write_hundreds(f, (year / 100) as u8)?; + write_hundreds(f, (year % 100) as u8)?; } else { // ISO 8601 requires the explicit sign for out-of-range years - write!(f, "{:+05}-{:02}-{:02}", year, mdf.month(), mdf.day()) + write!(f, "{:+05}", year)?; } + + f.write_char('-')?; + write_hundreds(f, mdf.month() as u8)?; + f.write_char('-')?; + write_hundreds(f, mdf.day() as u8) } } @@ -1656,21 +1919,21 @@ impl fmt::Debug for NaiveDate { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveDate; /// -/// assert_eq!(format!("{}", NaiveDate::from_ymd(2015, 9, 5)), "2015-09-05"); -/// assert_eq!(format!("{}", NaiveDate::from_ymd( 0, 1, 1)), "0000-01-01"); -/// assert_eq!(format!("{}", NaiveDate::from_ymd(9999, 12, 31)), "9999-12-31"); -/// ~~~~ +/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()), "2015-09-05"); +/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt( 0, 1, 1).unwrap()), "0000-01-01"); +/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(9999, 12, 31).unwrap()), "9999-12-31"); +/// ``` /// /// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE. /// -/// ~~~~ +/// ``` /// # use chrono::NaiveDate; -/// assert_eq!(format!("{}", NaiveDate::from_ymd( -1, 1, 1)), "-0001-01-01"); -/// assert_eq!(format!("{}", NaiveDate::from_ymd(10000, 12, 31)), "+10000-12-31"); -/// ~~~~ +/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt( -1, 1, 1).unwrap()), "-0001-01-01"); +/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(10000, 12, 31).unwrap()), "+10000-12-31"); +/// ``` impl fmt::Display for NaiveDate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) @@ -1682,22 +1945,22 @@ impl fmt::Display for NaiveDate { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveDate; /// -/// let d = NaiveDate::from_ymd(2015, 9, 18); +/// let d = NaiveDate::from_ymd_opt(2015, 9, 18).unwrap(); /// assert_eq!("2015-09-18".parse::<NaiveDate>(), Ok(d)); /// -/// let d = NaiveDate::from_ymd(12345, 6, 7); +/// let d = NaiveDate::from_ymd_opt(12345, 6, 7).unwrap(); /// assert_eq!("+12345-6-7".parse::<NaiveDate>(), Ok(d)); /// /// assert!("foo".parse::<NaiveDate>().is_err()); -/// ~~~~ +/// ``` impl str::FromStr for NaiveDate { type Err = ParseError; fn from_str(s: &str) -> ParseResult<NaiveDate> { - const ITEMS: &'static [Item<'static>] = &[ + const ITEMS: &[Item<'static>] = &[ Item::Numeric(Numeric::Year, Pad::Zero), Item::Space(""), Item::Literal("-"), @@ -1714,17 +1977,42 @@ impl str::FromStr for NaiveDate { } } +/// The default value for a NaiveDate is 1st of January 1970. +/// +/// # Example +/// +/// ```rust +/// use chrono::NaiveDate; +/// +/// let default_date = NaiveDate::default(); +/// assert_eq!(default_date, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()); +/// ``` +impl Default for NaiveDate { + fn default() -> Self { + NaiveDate::from_ymd_opt(1970, 1, 1).unwrap() + } +} + #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] fn test_encodable_json<F, E>(to_string: F) where F: Fn(&NaiveDate) -> Result<String, E>, E: ::std::fmt::Debug, { - assert_eq!(to_string(&NaiveDate::from_ymd(2014, 7, 24)).ok(), Some(r#""2014-07-24""#.into())); - assert_eq!(to_string(&NaiveDate::from_ymd(0, 1, 1)).ok(), Some(r#""0000-01-01""#.into())); - assert_eq!(to_string(&NaiveDate::from_ymd(-1, 12, 31)).ok(), Some(r#""-0001-12-31""#.into())); - assert_eq!(to_string(&MIN_DATE).ok(), Some(r#""-262144-01-01""#.into())); - assert_eq!(to_string(&MAX_DATE).ok(), Some(r#""+262143-12-31""#.into())); + assert_eq!( + to_string(&NaiveDate::from_ymd_opt(2014, 7, 24).unwrap()).ok(), + Some(r#""2014-07-24""#.into()) + ); + assert_eq!( + to_string(&NaiveDate::from_ymd_opt(0, 1, 1).unwrap()).ok(), + Some(r#""0000-01-01""#.into()) + ); + assert_eq!( + to_string(&NaiveDate::from_ymd_opt(-1, 12, 31).unwrap()).ok(), + Some(r#""-0001-12-31""#.into()) + ); + assert_eq!(to_string(&NaiveDate::MIN).ok(), Some(r#""-262144-01-01""#.into())); + assert_eq!(to_string(&NaiveDate::MAX).ok(), Some(r#""+262143-12-31""#.into())); } #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] @@ -1735,14 +2023,20 @@ where { use std::{i32, i64}; - assert_eq!(from_str(r#""2016-07-08""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8))); - assert_eq!(from_str(r#""2016-7-8""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8))); - assert_eq!(from_str(r#""+002016-07-08""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8))); - assert_eq!(from_str(r#""0000-01-01""#).ok(), Some(NaiveDate::from_ymd(0, 1, 1))); - assert_eq!(from_str(r#""0-1-1""#).ok(), Some(NaiveDate::from_ymd(0, 1, 1))); - assert_eq!(from_str(r#""-0001-12-31""#).ok(), Some(NaiveDate::from_ymd(-1, 12, 31))); - assert_eq!(from_str(r#""-262144-01-01""#).ok(), Some(MIN_DATE)); - assert_eq!(from_str(r#""+262143-12-31""#).ok(), Some(MAX_DATE)); + assert_eq!( + from_str(r#""2016-07-08""#).ok(), + Some(NaiveDate::from_ymd_opt(2016, 7, 8).unwrap()) + ); + assert_eq!(from_str(r#""2016-7-8""#).ok(), Some(NaiveDate::from_ymd_opt(2016, 7, 8).unwrap())); + assert_eq!(from_str(r#""+002016-07-08""#).ok(), NaiveDate::from_ymd_opt(2016, 7, 8)); + assert_eq!(from_str(r#""0000-01-01""#).ok(), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap())); + assert_eq!(from_str(r#""0-1-1""#).ok(), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap())); + assert_eq!( + from_str(r#""-0001-12-31""#).ok(), + Some(NaiveDate::from_ymd_opt(-1, 12, 31).unwrap()) + ); + assert_eq!(from_str(r#""-262144-01-01""#).ok(), Some(NaiveDate::MIN)); + assert_eq!(from_str(r#""+262143-12-31""#).ok(), Some(NaiveDate::MAX)); // bad formats assert!(from_str(r#""""#).is_err()); @@ -1765,6 +2059,7 @@ where } #[cfg(feature = "rustc-serialize")] +#[cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))] mod rustc_serialize { use super::NaiveDate; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -1796,10 +2091,11 @@ mod rustc_serialize { } #[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] mod serde { use super::NaiveDate; use core::fmt; - use serdelib::{de, ser}; + use serde::{de, ser}; // TODO not very optimized for space (binary formats would want something better) @@ -1828,11 +2124,11 @@ mod serde { type Value = NaiveDate; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a formatted date string") + formatter.write_str("a formatted date string") } #[cfg(any(feature = "std", test))] - fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E> + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: de::Error, { @@ -1840,7 +2136,7 @@ mod serde { } #[cfg(not(any(feature = "std", test)))] - fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E> + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: de::Error, { @@ -1857,29 +2153,24 @@ mod serde { } } - #[cfg(test)] - extern crate bincode; - #[cfg(test)] - extern crate serde_json; - #[test] fn test_serde_serialize() { - super::test_encodable_json(self::serde_json::to_string); + super::test_encodable_json(serde_json::to_string); } #[test] fn test_serde_deserialize() { - super::test_decodable_json(|input| self::serde_json::from_str(&input)); + super::test_decodable_json(|input| serde_json::from_str(input)); } #[test] fn test_serde_bincode() { // Bincode is relevant to test separately from JSON because // it is not self-describing. - use self::bincode::{deserialize, serialize, Infinite}; + use bincode::{deserialize, serialize}; - let d = NaiveDate::from_ymd(2014, 7, 24); - let encoded = serialize(&d, Infinite).unwrap(); + let d = NaiveDate::from_ymd_opt(2014, 7, 24).unwrap(); + let encoded = serialize(&d).unwrap(); let decoded: NaiveDate = deserialize(&encoded).unwrap(); assert_eq!(d, decoded); } @@ -1887,16 +2178,131 @@ mod serde { #[cfg(test)] mod tests { - use super::NaiveDate; - use super::{MAX_DATE, MAX_DAYS_FROM_YEAR_0, MAX_YEAR}; - use super::{MIN_DATE, MIN_DAYS_FROM_YEAR_0, MIN_YEAR}; - use oldtime::Duration; - use std::{i32, u32}; - use {Datelike, Weekday}; + use super::{ + Days, Months, NaiveDate, MAX_DAYS_FROM_YEAR_0, MAX_YEAR, MIN_DAYS_FROM_YEAR_0, MIN_YEAR, + }; + use crate::oldtime::Duration; + use crate::{Datelike, Weekday}; + use std::{ + convert::{TryFrom, TryInto}, + i32, u32, + }; + + #[test] + fn diff_months() { + // identity + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(0)), + Some(NaiveDate::from_ymd_opt(2022, 8, 3).unwrap()) + ); + + // add with months exceeding `i32::MAX` + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3) + .unwrap() + .checked_add_months(Months::new(i32::MAX as u32 + 1)), + None + ); + + // sub with months exceeding `i32::MIN` + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3) + .unwrap() + .checked_sub_months(Months::new((i32::MIN as i64).abs() as u32 + 1)), + None + ); + + // add overflowing year + assert_eq!(NaiveDate::MAX.checked_add_months(Months::new(1)), None); + + // add underflowing year + assert_eq!(NaiveDate::MIN.checked_sub_months(Months::new(1)), None); + + // sub crossing year 0 boundary + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(2050 * 12)), + Some(NaiveDate::from_ymd_opt(-28, 8, 3).unwrap()) + ); + + // add crossing year boundary + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(6)), + Some(NaiveDate::from_ymd_opt(2023, 2, 3).unwrap()) + ); + + // sub crossing year boundary + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(10)), + Some(NaiveDate::from_ymd_opt(2021, 10, 3).unwrap()) + ); + + // add clamping day, non-leap year + assert_eq!( + NaiveDate::from_ymd_opt(2022, 1, 29).unwrap().checked_add_months(Months::new(1)), + Some(NaiveDate::from_ymd_opt(2022, 2, 28).unwrap()) + ); + + // add to leap day + assert_eq!( + NaiveDate::from_ymd_opt(2022, 10, 29).unwrap().checked_add_months(Months::new(16)), + Some(NaiveDate::from_ymd_opt(2024, 2, 29).unwrap()) + ); + + // add into december + assert_eq!( + NaiveDate::from_ymd_opt(2022, 10, 31).unwrap().checked_add_months(Months::new(2)), + Some(NaiveDate::from_ymd_opt(2022, 12, 31).unwrap()) + ); + + // sub into december + assert_eq!( + NaiveDate::from_ymd_opt(2022, 10, 31).unwrap().checked_sub_months(Months::new(10)), + Some(NaiveDate::from_ymd_opt(2021, 12, 31).unwrap()) + ); + + // add into january + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(5)), + Some(NaiveDate::from_ymd_opt(2023, 1, 3).unwrap()) + ); + + // sub into january + assert_eq!( + NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(7)), + Some(NaiveDate::from_ymd_opt(2022, 1, 3).unwrap()) + ); + } + + #[test] + fn test_readme_doomsday() { + use num_iter::range_inclusive; + + for y in range_inclusive(NaiveDate::MIN.year(), NaiveDate::MAX.year()) { + // even months + let d4 = NaiveDate::from_ymd_opt(y, 4, 4).unwrap(); + let d6 = NaiveDate::from_ymd_opt(y, 6, 6).unwrap(); + let d8 = NaiveDate::from_ymd_opt(y, 8, 8).unwrap(); + let d10 = NaiveDate::from_ymd_opt(y, 10, 10).unwrap(); + let d12 = NaiveDate::from_ymd_opt(y, 12, 12).unwrap(); + + // nine to five, seven-eleven + let d59 = NaiveDate::from_ymd_opt(y, 5, 9).unwrap(); + let d95 = NaiveDate::from_ymd_opt(y, 9, 5).unwrap(); + let d711 = NaiveDate::from_ymd_opt(y, 7, 11).unwrap(); + let d117 = NaiveDate::from_ymd_opt(y, 11, 7).unwrap(); + + // "March 0" + let d30 = NaiveDate::from_ymd_opt(y, 3, 1).unwrap().pred_opt().unwrap(); + + let weekday = d30.weekday(); + let other_dates = [d4, d6, d8, d10, d12, d59, d95, d711, d117]; + assert!(other_dates.iter().all(|d| d.weekday() == weekday)); + } + } #[test] fn test_date_from_ymd() { - let ymd_opt = |y, m, d| NaiveDate::from_ymd_opt(y, m, d); + let ymd_opt = NaiveDate::from_ymd_opt; assert!(ymd_opt(2012, 0, 1).is_none()); assert!(ymd_opt(2012, 1, 1).is_some()); @@ -1912,8 +2318,8 @@ mod tests { #[test] fn test_date_from_yo() { - let yo_opt = |y, o| NaiveDate::from_yo_opt(y, o); - let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d); + let yo_opt = NaiveDate::from_yo_opt; + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); assert_eq!(yo_opt(2012, 0), None); assert_eq!(yo_opt(2012, 1), Some(ymd(2012, 1, 1))); @@ -1942,8 +2348,8 @@ mod tests { #[test] fn test_date_from_isoywd() { - let isoywd_opt = |y, w, d| NaiveDate::from_isoywd_opt(y, w, d); - let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d); + let isoywd_opt = NaiveDate::from_isoywd_opt; + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); assert_eq!(isoywd_opt(2004, 0, Weekday::Sun), None); assert_eq!(isoywd_opt(2004, 1, Weekday::Mon), Some(ymd(2003, 12, 29))); @@ -1985,8 +2391,7 @@ mod tests { .iter() { let d = NaiveDate::from_isoywd_opt(year, week, weekday); - if d.is_some() { - let d = d.unwrap(); + if let Some(d) = d { assert_eq!(d.weekday(), weekday); let w = d.iso_week(); assert_eq!(w.year(), year); @@ -2000,11 +2405,10 @@ mod tests { for month in 1..13 { for day in 1..32 { let d = NaiveDate::from_ymd_opt(year, month, day); - if d.is_some() { - let d = d.unwrap(); + if let Some(d) = d { let w = d.iso_week(); - let d_ = NaiveDate::from_isoywd(w.year(), w.week(), d.weekday()); - assert_eq!(d, d_); + let d_ = NaiveDate::from_isoywd_opt(w.year(), w.week(), d.weekday()); + assert_eq!(d, d_.unwrap()); } } } @@ -2013,63 +2417,111 @@ mod tests { #[test] fn test_date_from_num_days_from_ce() { - let from_ndays_from_ce = |days| NaiveDate::from_num_days_from_ce_opt(days); - assert_eq!(from_ndays_from_ce(1), Some(NaiveDate::from_ymd(1, 1, 1))); - assert_eq!(from_ndays_from_ce(2), Some(NaiveDate::from_ymd(1, 1, 2))); - assert_eq!(from_ndays_from_ce(31), Some(NaiveDate::from_ymd(1, 1, 31))); - assert_eq!(from_ndays_from_ce(32), Some(NaiveDate::from_ymd(1, 2, 1))); - assert_eq!(from_ndays_from_ce(59), Some(NaiveDate::from_ymd(1, 2, 28))); - assert_eq!(from_ndays_from_ce(60), Some(NaiveDate::from_ymd(1, 3, 1))); - assert_eq!(from_ndays_from_ce(365), Some(NaiveDate::from_ymd(1, 12, 31))); - assert_eq!(from_ndays_from_ce(365 * 1 + 1), Some(NaiveDate::from_ymd(2, 1, 1))); - assert_eq!(from_ndays_from_ce(365 * 2 + 1), Some(NaiveDate::from_ymd(3, 1, 1))); - assert_eq!(from_ndays_from_ce(365 * 3 + 1), Some(NaiveDate::from_ymd(4, 1, 1))); - assert_eq!(from_ndays_from_ce(365 * 4 + 2), Some(NaiveDate::from_ymd(5, 1, 1))); - assert_eq!(from_ndays_from_ce(146097 + 1), Some(NaiveDate::from_ymd(401, 1, 1))); - assert_eq!(from_ndays_from_ce(146097 * 5 + 1), Some(NaiveDate::from_ymd(2001, 1, 1))); - assert_eq!(from_ndays_from_ce(719163), Some(NaiveDate::from_ymd(1970, 1, 1))); - assert_eq!(from_ndays_from_ce(0), Some(NaiveDate::from_ymd(0, 12, 31))); // 1 BCE - assert_eq!(from_ndays_from_ce(-365), Some(NaiveDate::from_ymd(0, 1, 1))); - assert_eq!(from_ndays_from_ce(-366), Some(NaiveDate::from_ymd(-1, 12, 31))); // 2 BCE + let from_ndays_from_ce = NaiveDate::from_num_days_from_ce_opt; + assert_eq!(from_ndays_from_ce(1), Some(NaiveDate::from_ymd_opt(1, 1, 1).unwrap())); + assert_eq!(from_ndays_from_ce(2), Some(NaiveDate::from_ymd_opt(1, 1, 2).unwrap())); + assert_eq!(from_ndays_from_ce(31), Some(NaiveDate::from_ymd_opt(1, 1, 31).unwrap())); + assert_eq!(from_ndays_from_ce(32), Some(NaiveDate::from_ymd_opt(1, 2, 1).unwrap())); + assert_eq!(from_ndays_from_ce(59), Some(NaiveDate::from_ymd_opt(1, 2, 28).unwrap())); + assert_eq!(from_ndays_from_ce(60), Some(NaiveDate::from_ymd_opt(1, 3, 1).unwrap())); + assert_eq!(from_ndays_from_ce(365), Some(NaiveDate::from_ymd_opt(1, 12, 31).unwrap())); + assert_eq!(from_ndays_from_ce(365 + 1), Some(NaiveDate::from_ymd_opt(2, 1, 1).unwrap())); + assert_eq!( + from_ndays_from_ce(365 * 2 + 1), + Some(NaiveDate::from_ymd_opt(3, 1, 1).unwrap()) + ); + assert_eq!( + from_ndays_from_ce(365 * 3 + 1), + Some(NaiveDate::from_ymd_opt(4, 1, 1).unwrap()) + ); + assert_eq!( + from_ndays_from_ce(365 * 4 + 2), + Some(NaiveDate::from_ymd_opt(5, 1, 1).unwrap()) + ); + assert_eq!( + from_ndays_from_ce(146097 + 1), + Some(NaiveDate::from_ymd_opt(401, 1, 1).unwrap()) + ); + assert_eq!( + from_ndays_from_ce(146097 * 5 + 1), + Some(NaiveDate::from_ymd_opt(2001, 1, 1).unwrap()) + ); + assert_eq!(from_ndays_from_ce(719163), Some(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap())); + assert_eq!(from_ndays_from_ce(0), Some(NaiveDate::from_ymd_opt(0, 12, 31).unwrap())); // 1 BCE + assert_eq!(from_ndays_from_ce(-365), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap())); + assert_eq!(from_ndays_from_ce(-366), Some(NaiveDate::from_ymd_opt(-1, 12, 31).unwrap())); // 2 BCE for days in (-9999..10001).map(|x| x * 100) { assert_eq!(from_ndays_from_ce(days).map(|d| d.num_days_from_ce()), Some(days)); } - assert_eq!(from_ndays_from_ce(MIN_DATE.num_days_from_ce()), Some(MIN_DATE)); - assert_eq!(from_ndays_from_ce(MIN_DATE.num_days_from_ce() - 1), None); - assert_eq!(from_ndays_from_ce(MAX_DATE.num_days_from_ce()), Some(MAX_DATE)); - assert_eq!(from_ndays_from_ce(MAX_DATE.num_days_from_ce() + 1), None); + assert_eq!(from_ndays_from_ce(NaiveDate::MIN.num_days_from_ce()), Some(NaiveDate::MIN)); + assert_eq!(from_ndays_from_ce(NaiveDate::MIN.num_days_from_ce() - 1), None); + assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce()), Some(NaiveDate::MAX)); + assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce() + 1), None); } #[test] fn test_date_from_weekday_of_month_opt() { - let ymwd = |y, m, w, n| NaiveDate::from_weekday_of_month_opt(y, m, w, n); + let ymwd = NaiveDate::from_weekday_of_month_opt; assert_eq!(ymwd(2018, 8, Weekday::Tue, 0), None); - assert_eq!(ymwd(2018, 8, Weekday::Wed, 1), Some(NaiveDate::from_ymd(2018, 8, 1))); - assert_eq!(ymwd(2018, 8, Weekday::Thu, 1), Some(NaiveDate::from_ymd(2018, 8, 2))); - assert_eq!(ymwd(2018, 8, Weekday::Sun, 1), Some(NaiveDate::from_ymd(2018, 8, 5))); - assert_eq!(ymwd(2018, 8, Weekday::Mon, 1), Some(NaiveDate::from_ymd(2018, 8, 6))); - assert_eq!(ymwd(2018, 8, Weekday::Tue, 1), Some(NaiveDate::from_ymd(2018, 8, 7))); - assert_eq!(ymwd(2018, 8, Weekday::Wed, 2), Some(NaiveDate::from_ymd(2018, 8, 8))); - assert_eq!(ymwd(2018, 8, Weekday::Sun, 2), Some(NaiveDate::from_ymd(2018, 8, 12))); - assert_eq!(ymwd(2018, 8, Weekday::Thu, 3), Some(NaiveDate::from_ymd(2018, 8, 16))); - assert_eq!(ymwd(2018, 8, Weekday::Thu, 4), Some(NaiveDate::from_ymd(2018, 8, 23))); - assert_eq!(ymwd(2018, 8, Weekday::Thu, 5), Some(NaiveDate::from_ymd(2018, 8, 30))); - assert_eq!(ymwd(2018, 8, Weekday::Fri, 5), Some(NaiveDate::from_ymd(2018, 8, 31))); + assert_eq!( + ymwd(2018, 8, Weekday::Wed, 1), + Some(NaiveDate::from_ymd_opt(2018, 8, 1).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Thu, 1), + Some(NaiveDate::from_ymd_opt(2018, 8, 2).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Sun, 1), + Some(NaiveDate::from_ymd_opt(2018, 8, 5).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Mon, 1), + Some(NaiveDate::from_ymd_opt(2018, 8, 6).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Tue, 1), + Some(NaiveDate::from_ymd_opt(2018, 8, 7).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Wed, 2), + Some(NaiveDate::from_ymd_opt(2018, 8, 8).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Sun, 2), + Some(NaiveDate::from_ymd_opt(2018, 8, 12).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Thu, 3), + Some(NaiveDate::from_ymd_opt(2018, 8, 16).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Thu, 4), + Some(NaiveDate::from_ymd_opt(2018, 8, 23).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Thu, 5), + Some(NaiveDate::from_ymd_opt(2018, 8, 30).unwrap()) + ); + assert_eq!( + ymwd(2018, 8, Weekday::Fri, 5), + Some(NaiveDate::from_ymd_opt(2018, 8, 31).unwrap()) + ); assert_eq!(ymwd(2018, 8, Weekday::Sat, 5), None); } #[test] fn test_date_fields() { fn check(year: i32, month: u32, day: u32, ordinal: u32) { - let d1 = NaiveDate::from_ymd(year, month, day); + let d1 = NaiveDate::from_ymd_opt(year, month, day).unwrap(); assert_eq!(d1.year(), year); assert_eq!(d1.month(), month); assert_eq!(d1.day(), day); assert_eq!(d1.ordinal(), ordinal); - let d2 = NaiveDate::from_yo(year, ordinal); + let d2 = NaiveDate::from_yo_opt(year, ordinal).unwrap(); assert_eq!(d2.year(), year); assert_eq!(d2.month(), month); assert_eq!(d2.day(), day); @@ -2101,88 +2553,88 @@ mod tests { #[test] fn test_date_weekday() { - assert_eq!(NaiveDate::from_ymd(1582, 10, 15).weekday(), Weekday::Fri); + assert_eq!(NaiveDate::from_ymd_opt(1582, 10, 15).unwrap().weekday(), Weekday::Fri); // May 20, 1875 = ISO 8601 reference date - assert_eq!(NaiveDate::from_ymd(1875, 5, 20).weekday(), Weekday::Thu); - assert_eq!(NaiveDate::from_ymd(2000, 1, 1).weekday(), Weekday::Sat); + assert_eq!(NaiveDate::from_ymd_opt(1875, 5, 20).unwrap().weekday(), Weekday::Thu); + assert_eq!(NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().weekday(), Weekday::Sat); } #[test] fn test_date_with_fields() { - let d = NaiveDate::from_ymd(2000, 2, 29); - assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd(-400, 2, 29))); + let d = NaiveDate::from_ymd_opt(2000, 2, 29).unwrap(); + assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd_opt(-400, 2, 29).unwrap())); assert_eq!(d.with_year(-100), None); - assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd(1600, 2, 29))); + assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd_opt(1600, 2, 29).unwrap())); assert_eq!(d.with_year(1900), None); - assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd(2000, 2, 29))); + assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap())); assert_eq!(d.with_year(2001), None); - assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd(2004, 2, 29))); + assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd_opt(2004, 2, 29).unwrap())); assert_eq!(d.with_year(i32::MAX), None); - let d = NaiveDate::from_ymd(2000, 4, 30); + let d = NaiveDate::from_ymd_opt(2000, 4, 30).unwrap(); assert_eq!(d.with_month(0), None); - assert_eq!(d.with_month(1), Some(NaiveDate::from_ymd(2000, 1, 30))); + assert_eq!(d.with_month(1), Some(NaiveDate::from_ymd_opt(2000, 1, 30).unwrap())); assert_eq!(d.with_month(2), None); - assert_eq!(d.with_month(3), Some(NaiveDate::from_ymd(2000, 3, 30))); - assert_eq!(d.with_month(4), Some(NaiveDate::from_ymd(2000, 4, 30))); - assert_eq!(d.with_month(12), Some(NaiveDate::from_ymd(2000, 12, 30))); + assert_eq!(d.with_month(3), Some(NaiveDate::from_ymd_opt(2000, 3, 30).unwrap())); + assert_eq!(d.with_month(4), Some(NaiveDate::from_ymd_opt(2000, 4, 30).unwrap())); + assert_eq!(d.with_month(12), Some(NaiveDate::from_ymd_opt(2000, 12, 30).unwrap())); assert_eq!(d.with_month(13), None); assert_eq!(d.with_month(u32::MAX), None); - let d = NaiveDate::from_ymd(2000, 2, 8); + let d = NaiveDate::from_ymd_opt(2000, 2, 8).unwrap(); assert_eq!(d.with_day(0), None); - assert_eq!(d.with_day(1), Some(NaiveDate::from_ymd(2000, 2, 1))); - assert_eq!(d.with_day(29), Some(NaiveDate::from_ymd(2000, 2, 29))); + assert_eq!(d.with_day(1), Some(NaiveDate::from_ymd_opt(2000, 2, 1).unwrap())); + assert_eq!(d.with_day(29), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap())); assert_eq!(d.with_day(30), None); assert_eq!(d.with_day(u32::MAX), None); - let d = NaiveDate::from_ymd(2000, 5, 5); + let d = NaiveDate::from_ymd_opt(2000, 5, 5).unwrap(); assert_eq!(d.with_ordinal(0), None); - assert_eq!(d.with_ordinal(1), Some(NaiveDate::from_ymd(2000, 1, 1))); - assert_eq!(d.with_ordinal(60), Some(NaiveDate::from_ymd(2000, 2, 29))); - assert_eq!(d.with_ordinal(61), Some(NaiveDate::from_ymd(2000, 3, 1))); - assert_eq!(d.with_ordinal(366), Some(NaiveDate::from_ymd(2000, 12, 31))); + assert_eq!(d.with_ordinal(1), Some(NaiveDate::from_ymd_opt(2000, 1, 1).unwrap())); + assert_eq!(d.with_ordinal(60), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap())); + assert_eq!(d.with_ordinal(61), Some(NaiveDate::from_ymd_opt(2000, 3, 1).unwrap())); + assert_eq!(d.with_ordinal(366), Some(NaiveDate::from_ymd_opt(2000, 12, 31).unwrap())); assert_eq!(d.with_ordinal(367), None); assert_eq!(d.with_ordinal(u32::MAX), None); } #[test] fn test_date_num_days_from_ce() { - assert_eq!(NaiveDate::from_ymd(1, 1, 1).num_days_from_ce(), 1); + assert_eq!(NaiveDate::from_ymd_opt(1, 1, 1).unwrap().num_days_from_ce(), 1); for year in -9999..10001 { assert_eq!( - NaiveDate::from_ymd(year, 1, 1).num_days_from_ce(), - NaiveDate::from_ymd(year - 1, 12, 31).num_days_from_ce() + 1 + NaiveDate::from_ymd_opt(year, 1, 1).unwrap().num_days_from_ce(), + NaiveDate::from_ymd_opt(year - 1, 12, 31).unwrap().num_days_from_ce() + 1 ); } } #[test] fn test_date_succ() { - let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d); + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); assert_eq!(ymd(2014, 5, 6).succ_opt(), Some(ymd(2014, 5, 7))); assert_eq!(ymd(2014, 5, 31).succ_opt(), Some(ymd(2014, 6, 1))); assert_eq!(ymd(2014, 12, 31).succ_opt(), Some(ymd(2015, 1, 1))); assert_eq!(ymd(2016, 2, 28).succ_opt(), Some(ymd(2016, 2, 29))); - assert_eq!(ymd(MAX_DATE.year(), 12, 31).succ_opt(), None); + assert_eq!(ymd(NaiveDate::MAX.year(), 12, 31).succ_opt(), None); } #[test] fn test_date_pred() { - let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d); + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); assert_eq!(ymd(2016, 3, 1).pred_opt(), Some(ymd(2016, 2, 29))); assert_eq!(ymd(2015, 1, 1).pred_opt(), Some(ymd(2014, 12, 31))); assert_eq!(ymd(2014, 6, 1).pred_opt(), Some(ymd(2014, 5, 31))); assert_eq!(ymd(2014, 5, 7).pred_opt(), Some(ymd(2014, 5, 6))); - assert_eq!(ymd(MIN_DATE.year(), 1, 1).pred_opt(), None); + assert_eq!(ymd(NaiveDate::MIN.year(), 1, 1).pred_opt(), None); } #[test] fn test_date_add() { fn check((y1, m1, d1): (i32, u32, u32), rhs: Duration, ymd: Option<(i32, u32, u32)>) { - let lhs = NaiveDate::from_ymd(y1, m1, d1); - let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd(y, m, d)); + let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap(); + let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd_opt(y, m, d).unwrap()); assert_eq!(lhs.checked_add_signed(rhs), sum); assert_eq!(lhs.checked_sub_signed(-rhs), sum); } @@ -2211,8 +2663,8 @@ mod tests { #[test] fn test_date_sub() { fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: Duration) { - let lhs = NaiveDate::from_ymd(y1, m1, d1); - let rhs = NaiveDate::from_ymd(y2, m2, d2); + let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap(); + let rhs = NaiveDate::from_ymd_opt(y2, m2, d2).unwrap(); assert_eq!(lhs.signed_duration_since(rhs), diff); assert_eq!(rhs.signed_duration_since(lhs), -diff); } @@ -2229,8 +2681,53 @@ mod tests { } #[test] + fn test_date_add_days() { + fn check((y1, m1, d1): (i32, u32, u32), rhs: Days, ymd: Option<(i32, u32, u32)>) { + let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap(); + let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd_opt(y, m, d).unwrap()); + assert_eq!(lhs.checked_add_days(rhs), sum); + } + + check((2014, 1, 1), Days::new(0), Some((2014, 1, 1))); + // always round towards zero + check((2014, 1, 1), Days::new(1), Some((2014, 1, 2))); + check((2014, 1, 1), Days::new(364), Some((2014, 12, 31))); + check((2014, 1, 1), Days::new(365 * 4 + 1), Some((2018, 1, 1))); + check((2014, 1, 1), Days::new(365 * 400 + 97), Some((2414, 1, 1))); + + check((-7, 1, 1), Days::new(365 * 12 + 3), Some((5, 1, 1))); + + // overflow check + check( + (0, 1, 1), + Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()), + Some((MAX_YEAR, 12, 31)), + ); + check((0, 1, 1), Days::new(u64::try_from(MAX_DAYS_FROM_YEAR_0).unwrap() + 1), None); + } + + #[test] + fn test_date_sub_days() { + fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: Days) { + let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap(); + let rhs = NaiveDate::from_ymd_opt(y2, m2, d2).unwrap(); + assert_eq!(lhs - diff, rhs); + } + + check((2014, 1, 1), (2014, 1, 1), Days::new(0)); + check((2014, 1, 2), (2014, 1, 1), Days::new(1)); + check((2014, 12, 31), (2014, 1, 1), Days::new(364)); + check((2015, 1, 3), (2014, 1, 1), Days::new(365 + 2)); + check((2018, 1, 1), (2014, 1, 1), Days::new(365 * 4 + 1)); + check((2414, 1, 1), (2014, 1, 1), Days::new(365 * 400 + 97)); + + check((MAX_YEAR, 12, 31), (0, 1, 1), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap())); + check((0, 1, 1), (MIN_YEAR, 1, 1), Days::new((-MIN_DAYS_FROM_YEAR_0).try_into().unwrap())); + } + + #[test] fn test_date_addassignment() { - let ymd = NaiveDate::from_ymd; + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); let mut date = ymd(2016, 10, 1); date += Duration::days(10); assert_eq!(date, ymd(2016, 10, 11)); @@ -2240,7 +2737,7 @@ mod tests { #[test] fn test_date_subassignment() { - let ymd = NaiveDate::from_ymd; + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); let mut date = ymd(2016, 10, 11); date -= Duration::days(10); assert_eq!(date, ymd(2016, 10, 1)); @@ -2250,19 +2747,22 @@ mod tests { #[test] fn test_date_fmt() { - assert_eq!(format!("{:?}", NaiveDate::from_ymd(2012, 3, 4)), "2012-03-04"); - assert_eq!(format!("{:?}", NaiveDate::from_ymd(0, 3, 4)), "0000-03-04"); - assert_eq!(format!("{:?}", NaiveDate::from_ymd(-307, 3, 4)), "-0307-03-04"); - assert_eq!(format!("{:?}", NaiveDate::from_ymd(12345, 3, 4)), "+12345-03-04"); + assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(2012, 3, 4).unwrap()), "2012-03-04"); + assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(0, 3, 4).unwrap()), "0000-03-04"); + assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(-307, 3, 4).unwrap()), "-0307-03-04"); + assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(12345, 3, 4).unwrap()), "+12345-03-04"); - assert_eq!(NaiveDate::from_ymd(2012, 3, 4).to_string(), "2012-03-04"); - assert_eq!(NaiveDate::from_ymd(0, 3, 4).to_string(), "0000-03-04"); - assert_eq!(NaiveDate::from_ymd(-307, 3, 4).to_string(), "-0307-03-04"); - assert_eq!(NaiveDate::from_ymd(12345, 3, 4).to_string(), "+12345-03-04"); + assert_eq!(NaiveDate::from_ymd_opt(2012, 3, 4).unwrap().to_string(), "2012-03-04"); + assert_eq!(NaiveDate::from_ymd_opt(0, 3, 4).unwrap().to_string(), "0000-03-04"); + assert_eq!(NaiveDate::from_ymd_opt(-307, 3, 4).unwrap().to_string(), "-0307-03-04"); + assert_eq!(NaiveDate::from_ymd_opt(12345, 3, 4).unwrap().to_string(), "+12345-03-04"); // the format specifier should have no effect on `NaiveTime` - assert_eq!(format!("{:+30?}", NaiveDate::from_ymd(1234, 5, 6)), "1234-05-06"); - assert_eq!(format!("{:30?}", NaiveDate::from_ymd(12345, 6, 7)), "+12345-06-07"); + assert_eq!(format!("{:+30?}", NaiveDate::from_ymd_opt(1234, 5, 6).unwrap()), "1234-05-06"); + assert_eq!( + format!("{:30?}", NaiveDate::from_ymd_opt(12345, 6, 7).unwrap()), + "+12345-06-07" + ); } #[test] @@ -2318,7 +2818,7 @@ mod tests { #[test] fn test_date_parse_from_str() { - let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d); + let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); assert_eq!( NaiveDate::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), Ok(ymd(2014, 5, 7)) @@ -2334,11 +2834,21 @@ mod tests { assert!(NaiveDate::parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err()); assert!(NaiveDate::parse_from_str("2014-57", "%Y-%m-%d").is_err()); assert!(NaiveDate::parse_from_str("2014", "%Y").is_err()); // insufficient + + assert_eq!( + NaiveDate::parse_from_str("2020-01-0", "%Y-%W-%w").ok(), + NaiveDate::from_ymd_opt(2020, 1, 12), + ); + + assert_eq!( + NaiveDate::parse_from_str("2019-01-0", "%Y-%W-%w").ok(), + NaiveDate::from_ymd_opt(2019, 1, 13), + ); } #[test] fn test_date_format() { - let d = NaiveDate::from_ymd(2012, 3, 4); + let d = NaiveDate::from_ymd_opt(2012, 3, 4).unwrap(); assert_eq!(d.format("%Y,%C,%y,%G,%g").to_string(), "2012,20,12,2012,12"); assert_eq!(d.format("%m,%b,%h,%B").to_string(), "03,Mar,Mar,March"); assert_eq!(d.format("%d,%e").to_string(), "04, 4"); @@ -2351,33 +2861,40 @@ mod tests { assert_eq!(d.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); // non-four-digit years - assert_eq!(NaiveDate::from_ymd(12345, 1, 1).format("%Y").to_string(), "+12345"); - assert_eq!(NaiveDate::from_ymd(1234, 1, 1).format("%Y").to_string(), "1234"); - assert_eq!(NaiveDate::from_ymd(123, 1, 1).format("%Y").to_string(), "0123"); - assert_eq!(NaiveDate::from_ymd(12, 1, 1).format("%Y").to_string(), "0012"); - assert_eq!(NaiveDate::from_ymd(1, 1, 1).format("%Y").to_string(), "0001"); - assert_eq!(NaiveDate::from_ymd(0, 1, 1).format("%Y").to_string(), "0000"); - assert_eq!(NaiveDate::from_ymd(-1, 1, 1).format("%Y").to_string(), "-0001"); - assert_eq!(NaiveDate::from_ymd(-12, 1, 1).format("%Y").to_string(), "-0012"); - assert_eq!(NaiveDate::from_ymd(-123, 1, 1).format("%Y").to_string(), "-0123"); - assert_eq!(NaiveDate::from_ymd(-1234, 1, 1).format("%Y").to_string(), "-1234"); - assert_eq!(NaiveDate::from_ymd(-12345, 1, 1).format("%Y").to_string(), "-12345"); + assert_eq!( + NaiveDate::from_ymd_opt(12345, 1, 1).unwrap().format("%Y").to_string(), + "+12345" + ); + assert_eq!(NaiveDate::from_ymd_opt(1234, 1, 1).unwrap().format("%Y").to_string(), "1234"); + assert_eq!(NaiveDate::from_ymd_opt(123, 1, 1).unwrap().format("%Y").to_string(), "0123"); + assert_eq!(NaiveDate::from_ymd_opt(12, 1, 1).unwrap().format("%Y").to_string(), "0012"); + assert_eq!(NaiveDate::from_ymd_opt(1, 1, 1).unwrap().format("%Y").to_string(), "0001"); + assert_eq!(NaiveDate::from_ymd_opt(0, 1, 1).unwrap().format("%Y").to_string(), "0000"); + assert_eq!(NaiveDate::from_ymd_opt(-1, 1, 1).unwrap().format("%Y").to_string(), "-0001"); + assert_eq!(NaiveDate::from_ymd_opt(-12, 1, 1).unwrap().format("%Y").to_string(), "-0012"); + assert_eq!(NaiveDate::from_ymd_opt(-123, 1, 1).unwrap().format("%Y").to_string(), "-0123"); + assert_eq!(NaiveDate::from_ymd_opt(-1234, 1, 1).unwrap().format("%Y").to_string(), "-1234"); + assert_eq!( + NaiveDate::from_ymd_opt(-12345, 1, 1).unwrap().format("%Y").to_string(), + "-12345" + ); // corner cases assert_eq!( - NaiveDate::from_ymd(2007, 12, 31).format("%G,%g,%U,%W,%V").to_string(), - "2008,08,53,53,01" + NaiveDate::from_ymd_opt(2007, 12, 31).unwrap().format("%G,%g,%U,%W,%V").to_string(), + "2008,08,52,53,01" ); assert_eq!( - NaiveDate::from_ymd(2010, 1, 3).format("%G,%g,%U,%W,%V").to_string(), + NaiveDate::from_ymd_opt(2010, 1, 3).unwrap().format("%G,%g,%U,%W,%V").to_string(), "2009,09,01,00,53" ); } #[test] fn test_day_iterator_limit() { + assert_eq!(NaiveDate::from_ymd_opt(262143, 12, 29).unwrap().iter_days().take(4).count(), 2); assert_eq!( - NaiveDate::from_ymd(262143, 12, 29).iter_days().take(4).collect::<Vec<_>>().len(), + NaiveDate::from_ymd_opt(-262144, 1, 3).unwrap().iter_days().rev().take(4).count(), 2 ); } @@ -2385,8 +2902,96 @@ mod tests { #[test] fn test_week_iterator_limit() { assert_eq!( - NaiveDate::from_ymd(262143, 12, 12).iter_weeks().take(4).collect::<Vec<_>>().len(), + NaiveDate::from_ymd_opt(262143, 12, 12).unwrap().iter_weeks().take(4).count(), + 2 + ); + assert_eq!( + NaiveDate::from_ymd_opt(-262144, 1, 15).unwrap().iter_weeks().rev().take(4).count(), 2 ); } + + #[test] + fn test_naiveweek() { + let date = NaiveDate::from_ymd_opt(2022, 5, 18).unwrap(); + let asserts = vec![ + (Weekday::Mon, "2022-05-16", "2022-05-22"), + (Weekday::Tue, "2022-05-17", "2022-05-23"), + (Weekday::Wed, "2022-05-18", "2022-05-24"), + (Weekday::Thu, "2022-05-12", "2022-05-18"), + (Weekday::Fri, "2022-05-13", "2022-05-19"), + (Weekday::Sat, "2022-05-14", "2022-05-20"), + (Weekday::Sun, "2022-05-15", "2022-05-21"), + ]; + for (start, first_day, last_day) in asserts { + let week = date.week(start); + let days = week.days(); + assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%Y-%m-%d")); + assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%Y-%m-%d")); + assert!(days.contains(&date)); + } + } + + #[test] + fn test_weeks_from() { + // tests per: https://github.com/chronotope/chrono/issues/961 + // these internally use `weeks_from` via the parsing infrastructure + assert_eq!( + NaiveDate::parse_from_str("2020-01-0", "%Y-%W-%w").ok(), + NaiveDate::from_ymd_opt(2020, 1, 12), + ); + assert_eq!( + NaiveDate::parse_from_str("2019-01-0", "%Y-%W-%w").ok(), + NaiveDate::from_ymd_opt(2019, 1, 13), + ); + + // direct tests + for (y, starts_on) in &[ + (2019, Weekday::Tue), + (2020, Weekday::Wed), + (2021, Weekday::Fri), + (2022, Weekday::Sat), + (2023, Weekday::Sun), + (2024, Weekday::Mon), + (2025, Weekday::Wed), + (2026, Weekday::Thu), + ] { + for day in &[ + Weekday::Mon, + Weekday::Tue, + Weekday::Wed, + Weekday::Thu, + Weekday::Fri, + Weekday::Sat, + Weekday::Sun, + ] { + assert_eq!( + NaiveDate::from_ymd_opt(*y, 1, 1).map(|d| d.weeks_from(*day)), + Some(if day == starts_on { 1 } else { 0 }) + ); + + // last day must always be in week 52 or 53 + assert!([52, 53] + .contains(&NaiveDate::from_ymd_opt(*y, 12, 31).unwrap().weeks_from(*day)),); + } + } + + let base = NaiveDate::from_ymd_opt(2019, 1, 1).unwrap(); + + // 400 years covers all year types + for day in &[ + Weekday::Mon, + Weekday::Tue, + Weekday::Wed, + Weekday::Thu, + Weekday::Fri, + Weekday::Sat, + Weekday::Sun, + ] { + // must always be below 54 + for dplus in 1..(400 * 366) { + assert!((base + Days::new(dplus)).weeks_from(*day) < 54) + } + } + } } diff --git a/vendor/chrono/src/naive/datetime.rs b/vendor/chrono/src/naive/datetime.rs deleted file mode 100644 index 92d6c2855..000000000 --- a/vendor/chrono/src/naive/datetime.rs +++ /dev/null @@ -1,2507 +0,0 @@ -// This is a part of Chrono. -// See README.md and LICENSE.txt for details. - -//! ISO 8601 date and time without timezone. - -#[cfg(any(feature = "alloc", feature = "std", test))] -use core::borrow::Borrow; -use core::ops::{Add, AddAssign, Sub, SubAssign}; -use core::{fmt, hash, str}; -use num_traits::ToPrimitive; -use oldtime::Duration as OldDuration; - -use div::div_mod_floor; -#[cfg(any(feature = "alloc", feature = "std", test))] -use format::DelayedFormat; -use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; -use format::{Fixed, Item, Numeric, Pad}; -use naive::date::{MAX_DATE, MIN_DATE}; -use naive::time::{MAX_TIME, MIN_TIME}; -use naive::{IsoWeek, NaiveDate, NaiveTime}; -use {Datelike, Timelike, Weekday}; - -/// The tight upper bound guarantees that a duration with `|Duration| >= 2^MAX_SECS_BITS` -/// will always overflow the addition with any date and time type. -/// -/// So why is this needed? `Duration::seconds(rhs)` may overflow, and we don't have -/// an alternative returning `Option` or `Result`. Thus we need some early bound to avoid -/// touching that call when we are already sure that it WILL overflow... -const MAX_SECS_BITS: usize = 44; - -/// The minimum possible `NaiveDateTime`. -pub const MIN_DATETIME: NaiveDateTime = NaiveDateTime { date: MIN_DATE, time: MIN_TIME }; -/// The maximum possible `NaiveDateTime`. -pub const MAX_DATETIME: NaiveDateTime = NaiveDateTime { date: MAX_DATE, time: MAX_TIME }; - -/// ISO 8601 combined date and time without timezone. -/// -/// # Example -/// -/// `NaiveDateTime` is commonly created from [`NaiveDate`](./struct.NaiveDate.html). -/// -/// ~~~~ -/// use chrono::{NaiveDate, NaiveDateTime}; -/// -/// let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11); -/// # let _ = dt; -/// ~~~~ -/// -/// You can use typical [date-like](../trait.Datelike.html) and -/// [time-like](../trait.Timelike.html) methods, -/// provided that relevant traits are in the scope. -/// -/// ~~~~ -/// # use chrono::{NaiveDate, NaiveDateTime}; -/// # let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11); -/// use chrono::{Datelike, Timelike, Weekday}; -/// -/// assert_eq!(dt.weekday(), Weekday::Fri); -/// assert_eq!(dt.num_seconds_from_midnight(), 33011); -/// ~~~~ -#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] -pub struct NaiveDateTime { - date: NaiveDate, - time: NaiveTime, -} - -impl NaiveDateTime { - /// Makes a new `NaiveDateTime` from date and time components. - /// Equivalent to [`date.and_time(time)`](./struct.NaiveDate.html#method.and_time) - /// and many other helper constructors on `NaiveDate`. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime}; - /// - /// let d = NaiveDate::from_ymd(2015, 6, 3); - /// let t = NaiveTime::from_hms_milli(12, 34, 56, 789); - /// - /// let dt = NaiveDateTime::new(d, t); - /// assert_eq!(dt.date(), d); - /// assert_eq!(dt.time(), t); - /// ~~~~ - #[inline] - pub fn new(date: NaiveDate, time: NaiveTime) -> NaiveDateTime { - NaiveDateTime { date: date, time: time } - } - - /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, - /// from the number of non-leap seconds - /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") - /// and the number of nanoseconds since the last whole non-leap second. - /// - /// For a non-naive version of this function see - /// [`TimeZone::timestamp`](../offset/trait.TimeZone.html#method.timestamp). - /// - /// The nanosecond part can exceed 1,000,000,000 in order to represent the - /// [leap second](./struct.NaiveTime.html#leap-second-handling). (The true "UNIX - /// timestamp" cannot represent a leap second unambiguously.) - /// - /// Panics on the out-of-range number of seconds and/or invalid nanosecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDateTime, NaiveDate}; - /// - /// let dt = NaiveDateTime::from_timestamp(0, 42_000_000); - /// assert_eq!(dt, NaiveDate::from_ymd(1970, 1, 1).and_hms_milli(0, 0, 0, 42)); - /// - /// let dt = NaiveDateTime::from_timestamp(1_000_000_000, 0); - /// assert_eq!(dt, NaiveDate::from_ymd(2001, 9, 9).and_hms(1, 46, 40)); - /// ~~~~ - #[inline] - pub fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime { - let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs); - datetime.expect("invalid or out-of-range datetime") - } - - /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, - /// from the number of non-leap seconds - /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") - /// and the number of nanoseconds since the last whole non-leap second. - /// - /// The nanosecond part can exceed 1,000,000,000 - /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling). - /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.) - /// - /// Returns `None` on the out-of-range number of seconds and/or invalid nanosecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDateTime, NaiveDate}; - /// use std::i64; - /// - /// let from_timestamp_opt = NaiveDateTime::from_timestamp_opt; - /// - /// assert!(from_timestamp_opt(0, 0).is_some()); - /// assert!(from_timestamp_opt(0, 999_999_999).is_some()); - /// assert!(from_timestamp_opt(0, 1_500_000_000).is_some()); // leap second - /// assert!(from_timestamp_opt(0, 2_000_000_000).is_none()); - /// assert!(from_timestamp_opt(i64::MAX, 0).is_none()); - /// ~~~~ - #[inline] - pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> { - let (days, secs) = div_mod_floor(secs, 86_400); - let date = days - .to_i32() - .and_then(|days| days.checked_add(719_163)) - .and_then(NaiveDate::from_num_days_from_ce_opt); - let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs); - match (date, time) { - (Some(date), Some(time)) => Some(NaiveDateTime { date: date, time: time }), - (_, _) => None, - } - } - - /// Parses a string with the specified format string and returns a new `NaiveDateTime`. - /// See the [`format::strftime` module](../format/strftime/index.html) - /// on the supported escape sequences. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDateTime, NaiveDate}; - /// - /// let parse_from_str = NaiveDateTime::parse_from_str; - /// - /// assert_eq!(parse_from_str("2015-09-05 23:56:04", "%Y-%m-%d %H:%M:%S"), - /// Ok(NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4))); - /// assert_eq!(parse_from_str("5sep2015pm012345.6789", "%d%b%Y%p%I%M%S%.f"), - /// Ok(NaiveDate::from_ymd(2015, 9, 5).and_hms_micro(13, 23, 45, 678_900))); - /// ~~~~ - /// - /// Offset is ignored for the purpose of parsing. - /// - /// ~~~~ - /// # use chrono::{NaiveDateTime, NaiveDate}; - /// # let parse_from_str = NaiveDateTime::parse_from_str; - /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), - /// Ok(NaiveDate::from_ymd(2014, 5, 17).and_hms(12, 34, 56))); - /// ~~~~ - /// - /// [Leap seconds](./struct.NaiveTime.html#leap-second-handling) are correctly handled by - /// treating any time of the form `hh:mm:60` as a leap second. - /// (This equally applies to the formatting, so the round trip is possible.) - /// - /// ~~~~ - /// # use chrono::{NaiveDateTime, NaiveDate}; - /// # let parse_from_str = NaiveDateTime::parse_from_str; - /// assert_eq!(parse_from_str("2015-07-01 08:59:60.123", "%Y-%m-%d %H:%M:%S%.f"), - /// Ok(NaiveDate::from_ymd(2015, 7, 1).and_hms_milli(8, 59, 59, 1_123))); - /// ~~~~ - /// - /// Missing seconds are assumed to be zero, - /// but out-of-bound times or insufficient fields are errors otherwise. - /// - /// ~~~~ - /// # use chrono::{NaiveDateTime, NaiveDate}; - /// # let parse_from_str = NaiveDateTime::parse_from_str; - /// assert_eq!(parse_from_str("94/9/4 7:15", "%y/%m/%d %H:%M"), - /// Ok(NaiveDate::from_ymd(1994, 9, 4).and_hms(7, 15, 0))); - /// - /// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err()); - /// assert!(parse_from_str("94/9/4 12", "%y/%m/%d %H").is_err()); - /// assert!(parse_from_str("94/9/4 17:60", "%y/%m/%d %H:%M").is_err()); - /// assert!(parse_from_str("94/9/4 24:00:00", "%y/%m/%d %H:%M:%S").is_err()); - /// ~~~~ - /// - /// All parsed fields should be consistent to each other, otherwise it's an error. - /// - /// ~~~~ - /// # use chrono::NaiveDateTime; - /// # let parse_from_str = NaiveDateTime::parse_from_str; - /// let fmt = "%Y-%m-%d %H:%M:%S = UNIX timestamp %s"; - /// assert!(parse_from_str("2001-09-09 01:46:39 = UNIX timestamp 999999999", fmt).is_ok()); - /// assert!(parse_from_str("1970-01-01 00:00:00 = UNIX timestamp 1", fmt).is_err()); - /// ~~~~ - pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDateTime> { - let mut parsed = Parsed::new(); - parse(&mut parsed, s, StrftimeItems::new(fmt))?; - parsed.to_naive_datetime_with_offset(0) // no offset adjustment - } - - /// Retrieves a date component. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11); - /// assert_eq!(dt.date(), NaiveDate::from_ymd(2016, 7, 8)); - /// ~~~~ - #[inline] - pub fn date(&self) -> NaiveDate { - self.date - } - - /// Retrieves a time component. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveTime}; - /// - /// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11); - /// assert_eq!(dt.time(), NaiveTime::from_hms(9, 10, 11)); - /// ~~~~ - #[inline] - pub fn time(&self) -> NaiveTime { - self.time - } - - /// Returns the number of non-leap seconds since the midnight on January 1, 1970. - /// - /// Note that this does *not* account for the timezone! - /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_milli(0, 0, 1, 980); - /// assert_eq!(dt.timestamp(), 1); - /// - /// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms(1, 46, 40); - /// assert_eq!(dt.timestamp(), 1_000_000_000); - /// - /// let dt = NaiveDate::from_ymd(1969, 12, 31).and_hms(23, 59, 59); - /// assert_eq!(dt.timestamp(), -1); - /// - /// let dt = NaiveDate::from_ymd(-1, 1, 1).and_hms(0, 0, 0); - /// assert_eq!(dt.timestamp(), -62198755200); - /// ~~~~ - #[inline] - pub fn timestamp(&self) -> i64 { - const UNIX_EPOCH_DAY: i64 = 719_163; - let gregorian_day = i64::from(self.date.num_days_from_ce()); - let seconds_from_midnight = i64::from(self.time.num_seconds_from_midnight()); - (gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight - } - - /// Returns the number of non-leap *milliseconds* since midnight on January 1, 1970. - /// - /// Note that this does *not* account for the timezone! - /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. - /// - /// Note also that this does reduce the number of years that can be - /// represented from ~584 Billion to ~584 Million. (If this is a problem, - /// please file an issue to let me know what domain needs millisecond - /// precision over billions of years, I'm curious.) - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_milli(0, 0, 1, 444); - /// assert_eq!(dt.timestamp_millis(), 1_444); - /// - /// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms_milli(1, 46, 40, 555); - /// assert_eq!(dt.timestamp_millis(), 1_000_000_000_555); - /// - /// let dt = NaiveDate::from_ymd(1969, 12, 31).and_hms_milli(23, 59, 59, 100); - /// assert_eq!(dt.timestamp_millis(), -900); - /// ~~~~ - #[inline] - pub fn timestamp_millis(&self) -> i64 { - let as_ms = self.timestamp() * 1000; - as_ms + i64::from(self.timestamp_subsec_millis()) - } - - /// Returns the number of non-leap *nanoseconds* since midnight on January 1, 1970. - /// - /// Note that this does *not* account for the timezone! - /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. - /// - /// # Panics - /// - /// Note also that this does reduce the number of years that can be - /// represented from ~584 Billion to ~584 years. The dates that can be - /// represented as nanoseconds are between 1677-09-21T00:12:44.0 and - /// 2262-04-11T23:47:16.854775804. - /// - /// (If this is a problem, please file an issue to let me know what domain - /// needs nanosecond precision over millennia, I'm curious.) - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime}; - /// - /// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_nano(0, 0, 1, 444); - /// assert_eq!(dt.timestamp_nanos(), 1_000_000_444); - /// - /// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms_nano(1, 46, 40, 555); - /// - /// const A_BILLION: i64 = 1_000_000_000; - /// let nanos = dt.timestamp_nanos(); - /// assert_eq!(nanos, 1_000_000_000_000_000_555); - /// assert_eq!( - /// dt, - /// NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32) - /// ); - /// ~~~~ - #[inline] - pub fn timestamp_nanos(&self) -> i64 { - let as_ns = self.timestamp() * 1_000_000_000; - as_ns + i64::from(self.timestamp_subsec_nanos()) - } - - /// Returns the number of milliseconds since the last whole non-leap second. - /// - /// The return value ranges from 0 to 999, - /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789); - /// assert_eq!(dt.timestamp_subsec_millis(), 123); - /// - /// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890); - /// assert_eq!(dt.timestamp_subsec_millis(), 1_234); - /// ~~~~ - #[inline] - pub fn timestamp_subsec_millis(&self) -> u32 { - self.timestamp_subsec_nanos() / 1_000_000 - } - - /// Returns the number of microseconds since the last whole non-leap second. - /// - /// The return value ranges from 0 to 999,999, - /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999,999. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789); - /// assert_eq!(dt.timestamp_subsec_micros(), 123_456); - /// - /// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890); - /// assert_eq!(dt.timestamp_subsec_micros(), 1_234_567); - /// ~~~~ - #[inline] - pub fn timestamp_subsec_micros(&self) -> u32 { - self.timestamp_subsec_nanos() / 1_000 - } - - /// Returns the number of nanoseconds since the last whole non-leap second. - /// - /// The return value ranges from 0 to 999,999,999, - /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999,999,999. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789); - /// assert_eq!(dt.timestamp_subsec_nanos(), 123_456_789); - /// - /// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890); - /// assert_eq!(dt.timestamp_subsec_nanos(), 1_234_567_890); - /// ~~~~ - #[inline] - pub fn timestamp_subsec_nanos(&self) -> u32 { - self.time.nanosecond() - } - - /// Adds given `Duration` to the current date and time. - /// - /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), - /// the addition assumes that **there is no leap second ever**, - /// except when the `NaiveDateTime` itself represents a leap second - /// in which case the assumption becomes that **there is exactly a single leap second ever**. - /// - /// Returns `None` when it will result in overflow. - /// - /// # Example - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// use chrono::{Duration, NaiveDate}; - /// - /// let from_ymd = NaiveDate::from_ymd; - /// - /// let d = from_ymd(2016, 7, 8); - /// let hms = |h, m, s| d.and_hms(h, m, s); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::zero()), - /// Some(hms(3, 5, 7))); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(1)), - /// Some(hms(3, 5, 8))); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(-1)), - /// Some(hms(3, 5, 6))); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(3600 + 60)), - /// Some(hms(4, 6, 7))); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(86_400)), - /// Some(from_ymd(2016, 7, 9).and_hms(3, 5, 7))); - /// - /// let hmsm = |h, m, s, milli| d.and_hms_milli(h, m, s, milli); - /// assert_eq!(hmsm(3, 5, 7, 980).checked_add_signed(Duration::milliseconds(450)), - /// Some(hmsm(3, 5, 8, 430))); - /// # } - /// ~~~~ - /// - /// Overflow returns `None`. - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// # use chrono::{Duration, NaiveDate}; - /// # let hms = |h, m, s| NaiveDate::from_ymd(2016, 7, 8).and_hms(h, m, s); - /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::days(1_000_000_000)), None); - /// # } - /// ~~~~ - /// - /// Leap seconds are handled, - /// but the addition assumes that it is the only leap second happened. - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// # use chrono::{Duration, NaiveDate}; - /// # let from_ymd = NaiveDate::from_ymd; - /// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli(h, m, s, milli); - /// let leap = hmsm(3, 5, 59, 1_300); - /// assert_eq!(leap.checked_add_signed(Duration::zero()), - /// Some(hmsm(3, 5, 59, 1_300))); - /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(-500)), - /// Some(hmsm(3, 5, 59, 800))); - /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(500)), - /// Some(hmsm(3, 5, 59, 1_800))); - /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(800)), - /// Some(hmsm(3, 6, 0, 100))); - /// assert_eq!(leap.checked_add_signed(Duration::seconds(10)), - /// Some(hmsm(3, 6, 9, 300))); - /// assert_eq!(leap.checked_add_signed(Duration::seconds(-10)), - /// Some(hmsm(3, 5, 50, 300))); - /// assert_eq!(leap.checked_add_signed(Duration::days(1)), - /// Some(from_ymd(2016, 7, 9).and_hms_milli(3, 5, 59, 300))); - /// # } - /// ~~~~ - pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> { - let (time, rhs) = self.time.overflowing_add_signed(rhs); - - // early checking to avoid overflow in OldDuration::seconds - if rhs <= (-1 << MAX_SECS_BITS) || rhs >= (1 << MAX_SECS_BITS) { - return None; - } - - let date = try_opt!(self.date.checked_add_signed(OldDuration::seconds(rhs))); - Some(NaiveDateTime { date: date, time: time }) - } - - /// Subtracts given `Duration` from the current date and time. - /// - /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), - /// the subtraction assumes that **there is no leap second ever**, - /// except when the `NaiveDateTime` itself represents a leap second - /// in which case the assumption becomes that **there is exactly a single leap second ever**. - /// - /// Returns `None` when it will result in overflow. - /// - /// # Example - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// use chrono::{Duration, NaiveDate}; - /// - /// let from_ymd = NaiveDate::from_ymd; - /// - /// let d = from_ymd(2016, 7, 8); - /// let hms = |h, m, s| d.and_hms(h, m, s); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::zero()), - /// Some(hms(3, 5, 7))); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(1)), - /// Some(hms(3, 5, 6))); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(-1)), - /// Some(hms(3, 5, 8))); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(3600 + 60)), - /// Some(hms(2, 4, 7))); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(86_400)), - /// Some(from_ymd(2016, 7, 7).and_hms(3, 5, 7))); - /// - /// let hmsm = |h, m, s, milli| d.and_hms_milli(h, m, s, milli); - /// assert_eq!(hmsm(3, 5, 7, 450).checked_sub_signed(Duration::milliseconds(670)), - /// Some(hmsm(3, 5, 6, 780))); - /// # } - /// ~~~~ - /// - /// Overflow returns `None`. - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// # use chrono::{Duration, NaiveDate}; - /// # let hms = |h, m, s| NaiveDate::from_ymd(2016, 7, 8).and_hms(h, m, s); - /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::days(1_000_000_000)), None); - /// # } - /// ~~~~ - /// - /// Leap seconds are handled, - /// but the subtraction assumes that it is the only leap second happened. - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// # use chrono::{Duration, NaiveDate}; - /// # let from_ymd = NaiveDate::from_ymd; - /// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli(h, m, s, milli); - /// let leap = hmsm(3, 5, 59, 1_300); - /// assert_eq!(leap.checked_sub_signed(Duration::zero()), - /// Some(hmsm(3, 5, 59, 1_300))); - /// assert_eq!(leap.checked_sub_signed(Duration::milliseconds(200)), - /// Some(hmsm(3, 5, 59, 1_100))); - /// assert_eq!(leap.checked_sub_signed(Duration::milliseconds(500)), - /// Some(hmsm(3, 5, 59, 800))); - /// assert_eq!(leap.checked_sub_signed(Duration::seconds(60)), - /// Some(hmsm(3, 5, 0, 300))); - /// assert_eq!(leap.checked_sub_signed(Duration::days(1)), - /// Some(from_ymd(2016, 7, 7).and_hms_milli(3, 6, 0, 300))); - /// # } - /// ~~~~ - pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> { - let (time, rhs) = self.time.overflowing_sub_signed(rhs); - - // early checking to avoid overflow in OldDuration::seconds - if rhs <= (-1 << MAX_SECS_BITS) || rhs >= (1 << MAX_SECS_BITS) { - return None; - } - - let date = try_opt!(self.date.checked_sub_signed(OldDuration::seconds(rhs))); - Some(NaiveDateTime { date: date, time: time }) - } - - /// Subtracts another `NaiveDateTime` from the current date and time. - /// This does not overflow or underflow at all. - /// - /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), - /// the subtraction assumes that **there is no leap second ever**, - /// except when any of the `NaiveDateTime`s themselves represents a leap second - /// in which case the assumption becomes that - /// **there are exactly one (or two) leap second(s) ever**. - /// - /// # Example - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// use chrono::{Duration, NaiveDate}; - /// - /// let from_ymd = NaiveDate::from_ymd; - /// - /// let d = from_ymd(2016, 7, 8); - /// assert_eq!(d.and_hms(3, 5, 7).signed_duration_since(d.and_hms(2, 4, 6)), - /// Duration::seconds(3600 + 60 + 1)); - /// - /// // July 8 is 190th day in the year 2016 - /// let d0 = from_ymd(2016, 1, 1); - /// assert_eq!(d.and_hms_milli(0, 7, 6, 500).signed_duration_since(d0.and_hms(0, 0, 0)), - /// Duration::seconds(189 * 86_400 + 7 * 60 + 6) + Duration::milliseconds(500)); - /// # } - /// ~~~~ - /// - /// Leap seconds are handled, but the subtraction assumes that - /// there were no other leap seconds happened. - /// - /// ~~~~ - /// # extern crate chrono; fn main() { - /// # use chrono::{Duration, NaiveDate}; - /// # let from_ymd = NaiveDate::from_ymd; - /// let leap = from_ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_500); - /// assert_eq!(leap.signed_duration_since(from_ymd(2015, 6, 30).and_hms(23, 0, 0)), - /// Duration::seconds(3600) + Duration::milliseconds(500)); - /// assert_eq!(from_ymd(2015, 7, 1).and_hms(1, 0, 0).signed_duration_since(leap), - /// Duration::seconds(3600) - Duration::milliseconds(500)); - /// # } - /// ~~~~ - pub fn signed_duration_since(self, rhs: NaiveDateTime) -> OldDuration { - self.date.signed_duration_since(rhs.date) + self.time.signed_duration_since(rhs.time) - } - - /// Formats the combined date and time with the specified formatting items. - /// Otherwise it is the same as the ordinary [`format`](#method.format) method. - /// - /// The `Iterator` of items should be `Clone`able, - /// since the resulting `DelayedFormat` value may be formatted multiple times. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// use chrono::format::strftime::StrftimeItems; - /// - /// let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S"); - /// let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); - /// assert_eq!(dt.format_with_items(fmt.clone()).to_string(), "2015-09-05 23:56:04"); - /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); - /// ~~~~ - /// - /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. - /// - /// ~~~~ - /// # use chrono::NaiveDate; - /// # use chrono::format::strftime::StrftimeItems; - /// # let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S").clone(); - /// # let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); - /// assert_eq!(format!("{}", dt.format_with_items(fmt)), "2015-09-05 23:56:04"); - /// ~~~~ - #[cfg(any(feature = "alloc", feature = "std", test))] - #[inline] - pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I> - where - I: Iterator<Item = B> + Clone, - B: Borrow<Item<'a>>, - { - DelayedFormat::new(Some(self.date), Some(self.time), items) - } - - /// Formats the combined date and time with the specified format string. - /// See the [`format::strftime` module](../format/strftime/index.html) - /// on the supported escape sequences. - /// - /// This returns a `DelayedFormat`, - /// which gets converted to a string only when actual formatting happens. - /// You may use the `to_string` method to get a `String`, - /// or just feed it into `print!` and other formatting macros. - /// (In this way it avoids the redundant memory allocation.) - /// - /// A wrong format string does *not* issue an error immediately. - /// Rather, converting or formatting the `DelayedFormat` fails. - /// You are recommended to immediately use `DelayedFormat` for this reason. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); - /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); - /// assert_eq!(dt.format("around %l %p on %b %-d").to_string(), "around 11 PM on Sep 5"); - /// ~~~~ - /// - /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. - /// - /// ~~~~ - /// # use chrono::NaiveDate; - /// # let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); - /// assert_eq!(format!("{}", dt.format("%Y-%m-%d %H:%M:%S")), "2015-09-05 23:56:04"); - /// assert_eq!(format!("{}", dt.format("around %l %p on %b %-d")), "around 11 PM on Sep 5"); - /// ~~~~ - #[cfg(any(feature = "alloc", feature = "std", test))] - #[inline] - pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> { - self.format_with_items(StrftimeItems::new(fmt)) - } -} - -impl Datelike for NaiveDateTime { - /// Returns the year number in the [calendar date](./index.html#calendar-date). - /// - /// See also the [`NaiveDate::year`](./struct.NaiveDate.html#method.year) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.year(), 2015); - /// ~~~~ - #[inline] - fn year(&self) -> i32 { - self.date.year() - } - - /// Returns the month number starting from 1. - /// - /// The return value ranges from 1 to 12. - /// - /// See also the [`NaiveDate::month`](./struct.NaiveDate.html#method.month) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.month(), 9); - /// ~~~~ - #[inline] - fn month(&self) -> u32 { - self.date.month() - } - - /// Returns the month number starting from 0. - /// - /// The return value ranges from 0 to 11. - /// - /// See also the [`NaiveDate::month0`](./struct.NaiveDate.html#method.month0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.month0(), 8); - /// ~~~~ - #[inline] - fn month0(&self) -> u32 { - self.date.month0() - } - - /// Returns the day of month starting from 1. - /// - /// The return value ranges from 1 to 31. (The last day of month differs by months.) - /// - /// See also the [`NaiveDate::day`](./struct.NaiveDate.html#method.day) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.day(), 25); - /// ~~~~ - #[inline] - fn day(&self) -> u32 { - self.date.day() - } - - /// Returns the day of month starting from 0. - /// - /// The return value ranges from 0 to 30. (The last day of month differs by months.) - /// - /// See also the [`NaiveDate::day0`](./struct.NaiveDate.html#method.day0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.day0(), 24); - /// ~~~~ - #[inline] - fn day0(&self) -> u32 { - self.date.day0() - } - - /// Returns the day of year starting from 1. - /// - /// The return value ranges from 1 to 366. (The last day of year differs by years.) - /// - /// See also the [`NaiveDate::ordinal`](./struct.NaiveDate.html#method.ordinal) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.ordinal(), 268); - /// ~~~~ - #[inline] - fn ordinal(&self) -> u32 { - self.date.ordinal() - } - - /// Returns the day of year starting from 0. - /// - /// The return value ranges from 0 to 365. (The last day of year differs by years.) - /// - /// See also the [`NaiveDate::ordinal0`](./struct.NaiveDate.html#method.ordinal0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.ordinal0(), 267); - /// ~~~~ - #[inline] - fn ordinal0(&self) -> u32 { - self.date.ordinal0() - } - - /// Returns the day of week. - /// - /// See also the [`NaiveDate::weekday`](./struct.NaiveDate.html#method.weekday) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Weekday}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.weekday(), Weekday::Fri); - /// ~~~~ - #[inline] - fn weekday(&self) -> Weekday { - self.date.weekday() - } - - #[inline] - fn iso_week(&self) -> IsoWeek { - self.date.iso_week() - } - - /// Makes a new `NaiveDateTime` with the year number changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_year`](./struct.NaiveDate.html#method.with_year) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).and_hms(12, 34, 56); - /// assert_eq!(dt.with_year(2016), Some(NaiveDate::from_ymd(2016, 9, 25).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_year(-308), Some(NaiveDate::from_ymd(-308, 9, 25).and_hms(12, 34, 56))); - /// ~~~~ - #[inline] - fn with_year(&self, year: i32) -> Option<NaiveDateTime> { - self.date.with_year(year).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the month number (starting from 1) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_month`](./struct.NaiveDate.html#method.with_month) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 30).and_hms(12, 34, 56); - /// assert_eq!(dt.with_month(10), Some(NaiveDate::from_ymd(2015, 10, 30).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_month(13), None); // no month 13 - /// assert_eq!(dt.with_month(2), None); // no February 30 - /// ~~~~ - #[inline] - fn with_month(&self, month: u32) -> Option<NaiveDateTime> { - self.date.with_month(month).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the month number (starting from 0) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_month0`](./struct.NaiveDate.html#method.with_month0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 30).and_hms(12, 34, 56); - /// assert_eq!(dt.with_month0(9), Some(NaiveDate::from_ymd(2015, 10, 30).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_month0(12), None); // no month 13 - /// assert_eq!(dt.with_month0(1), None); // no February 30 - /// ~~~~ - #[inline] - fn with_month0(&self, month0: u32) -> Option<NaiveDateTime> { - self.date.with_month0(month0).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the day of month (starting from 1) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_day`](./struct.NaiveDate.html#method.with_day) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_day(30), Some(NaiveDate::from_ymd(2015, 9, 30).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_day(31), None); // no September 31 - /// ~~~~ - #[inline] - fn with_day(&self, day: u32) -> Option<NaiveDateTime> { - self.date.with_day(day).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the day of month (starting from 0) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_day0`](./struct.NaiveDate.html#method.with_day0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_day0(29), Some(NaiveDate::from_ymd(2015, 9, 30).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_day0(30), None); // no September 31 - /// ~~~~ - #[inline] - fn with_day0(&self, day0: u32) -> Option<NaiveDateTime> { - self.date.with_day0(day0).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the day of year (starting from 1) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_ordinal`](./struct.NaiveDate.html#method.with_ordinal) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_ordinal(60), - /// Some(NaiveDate::from_ymd(2015, 3, 1).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_ordinal(366), None); // 2015 had only 365 days - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_ordinal(60), - /// Some(NaiveDate::from_ymd(2016, 2, 29).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_ordinal(366), - /// Some(NaiveDate::from_ymd(2016, 12, 31).and_hms(12, 34, 56))); - /// ~~~~ - #[inline] - fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDateTime> { - self.date.with_ordinal(ordinal).map(|d| NaiveDateTime { date: d, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the day of year (starting from 0) changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveDate::with_ordinal0`](./struct.NaiveDate.html#method.with_ordinal0) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2015, 3, 1).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_ordinal0(365), None); // 2015 had only 365 days - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 9, 8).and_hms(12, 34, 56); - /// assert_eq!(dt.with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2016, 2, 29).and_hms(12, 34, 56))); - /// assert_eq!(dt.with_ordinal0(365), - /// Some(NaiveDate::from_ymd(2016, 12, 31).and_hms(12, 34, 56))); - /// ~~~~ - #[inline] - fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDateTime> { - self.date.with_ordinal0(ordinal0).map(|d| NaiveDateTime { date: d, ..*self }) - } -} - -impl Timelike for NaiveDateTime { - /// Returns the hour number from 0 to 23. - /// - /// See also the [`NaiveTime::hour`](./struct.NaiveTime.html#method.hour) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.hour(), 12); - /// ~~~~ - #[inline] - fn hour(&self) -> u32 { - self.time.hour() - } - - /// Returns the minute number from 0 to 59. - /// - /// See also the [`NaiveTime::minute`](./struct.NaiveTime.html#method.minute) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.minute(), 34); - /// ~~~~ - #[inline] - fn minute(&self) -> u32 { - self.time.minute() - } - - /// Returns the second number from 0 to 59. - /// - /// See also the [`NaiveTime::second`](./struct.NaiveTime.html#method.second) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.second(), 56); - /// ~~~~ - #[inline] - fn second(&self) -> u32 { - self.time.second() - } - - /// Returns the number of nanoseconds since the whole non-leap second. - /// The range from 1,000,000,000 to 1,999,999,999 represents - /// the [leap second](./struct.NaiveTime.html#leap-second-handling). - /// - /// See also the - /// [`NaiveTime::nanosecond`](./struct.NaiveTime.html#method.nanosecond) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.nanosecond(), 789_000_000); - /// ~~~~ - #[inline] - fn nanosecond(&self) -> u32 { - self.time.nanosecond() - } - - /// Makes a new `NaiveDateTime` with the hour number changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveTime::with_hour`](./struct.NaiveTime.html#method.with_hour) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.with_hour(7), - /// Some(NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(7, 34, 56, 789))); - /// assert_eq!(dt.with_hour(24), None); - /// ~~~~ - #[inline] - fn with_hour(&self, hour: u32) -> Option<NaiveDateTime> { - self.time.with_hour(hour).map(|t| NaiveDateTime { time: t, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the minute number changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// - /// See also the - /// [`NaiveTime::with_minute`](./struct.NaiveTime.html#method.with_minute) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.with_minute(45), - /// Some(NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 45, 56, 789))); - /// assert_eq!(dt.with_minute(60), None); - /// ~~~~ - #[inline] - fn with_minute(&self, min: u32) -> Option<NaiveDateTime> { - self.time.with_minute(min).map(|t| NaiveDateTime { time: t, ..*self }) - } - - /// Makes a new `NaiveDateTime` with the second number changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// As with the [`second`](#method.second) method, - /// the input range is restricted to 0 through 59. - /// - /// See also the - /// [`NaiveTime::with_second`](./struct.NaiveTime.html#method.with_second) method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.with_second(17), - /// Some(NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 17, 789))); - /// assert_eq!(dt.with_second(60), None); - /// ~~~~ - #[inline] - fn with_second(&self, sec: u32) -> Option<NaiveDateTime> { - self.time.with_second(sec).map(|t| NaiveDateTime { time: t, ..*self }) - } - - /// Makes a new `NaiveDateTime` with nanoseconds since the whole non-leap second changed. - /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. - /// As with the [`nanosecond`](#method.nanosecond) method, - /// the input range can exceed 1,000,000,000 for leap seconds. - /// - /// See also the - /// [`NaiveTime::with_nanosecond`](./struct.NaiveTime.html#method.with_nanosecond) - /// method. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 8).and_hms_milli(12, 34, 56, 789); - /// assert_eq!(dt.with_nanosecond(333_333_333), - /// Some(NaiveDate::from_ymd(2015, 9, 8).and_hms_nano(12, 34, 56, 333_333_333))); - /// assert_eq!(dt.with_nanosecond(1_333_333_333), // leap second - /// Some(NaiveDate::from_ymd(2015, 9, 8).and_hms_nano(12, 34, 56, 1_333_333_333))); - /// assert_eq!(dt.with_nanosecond(2_000_000_000), None); - /// ~~~~ - #[inline] - fn with_nanosecond(&self, nano: u32) -> Option<NaiveDateTime> { - self.time.with_nanosecond(nano).map(|t| NaiveDateTime { time: t, ..*self }) - } -} - -/// `NaiveDateTime` can be used as a key to the hash maps (in principle). -/// -/// Practically this also takes account of fractional seconds, so it is not recommended. -/// (For the obvious reason this also distinguishes leap seconds from non-leap seconds.) -impl hash::Hash for NaiveDateTime { - fn hash<H: hash::Hasher>(&self, state: &mut H) { - self.date.hash(state); - self.time.hash(state); - } -} - -/// An addition of `Duration` to `NaiveDateTime` yields another `NaiveDateTime`. -/// -/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), -/// the addition assumes that **there is no leap second ever**, -/// except when the `NaiveDateTime` itself represents a leap second -/// in which case the assumption becomes that **there is exactly a single leap second ever**. -/// -/// Panics on underflow or overflow. -/// Use [`NaiveDateTime::checked_add_signed`](#method.checked_add_signed) to detect that. -/// -/// # Example -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// use chrono::{Duration, NaiveDate}; -/// -/// let from_ymd = NaiveDate::from_ymd; -/// -/// let d = from_ymd(2016, 7, 8); -/// let hms = |h, m, s| d.and_hms(h, m, s); -/// assert_eq!(hms(3, 5, 7) + Duration::zero(), hms(3, 5, 7)); -/// assert_eq!(hms(3, 5, 7) + Duration::seconds(1), hms(3, 5, 8)); -/// assert_eq!(hms(3, 5, 7) + Duration::seconds(-1), hms(3, 5, 6)); -/// assert_eq!(hms(3, 5, 7) + Duration::seconds(3600 + 60), hms(4, 6, 7)); -/// assert_eq!(hms(3, 5, 7) + Duration::seconds(86_400), -/// from_ymd(2016, 7, 9).and_hms(3, 5, 7)); -/// assert_eq!(hms(3, 5, 7) + Duration::days(365), -/// from_ymd(2017, 7, 8).and_hms(3, 5, 7)); -/// -/// let hmsm = |h, m, s, milli| d.and_hms_milli(h, m, s, milli); -/// assert_eq!(hmsm(3, 5, 7, 980) + Duration::milliseconds(450), hmsm(3, 5, 8, 430)); -/// # } -/// ~~~~ -/// -/// Leap seconds are handled, -/// but the addition assumes that it is the only leap second happened. -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// # use chrono::{Duration, NaiveDate}; -/// # let from_ymd = NaiveDate::from_ymd; -/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli(h, m, s, milli); -/// let leap = hmsm(3, 5, 59, 1_300); -/// assert_eq!(leap + Duration::zero(), hmsm(3, 5, 59, 1_300)); -/// assert_eq!(leap + Duration::milliseconds(-500), hmsm(3, 5, 59, 800)); -/// assert_eq!(leap + Duration::milliseconds(500), hmsm(3, 5, 59, 1_800)); -/// assert_eq!(leap + Duration::milliseconds(800), hmsm(3, 6, 0, 100)); -/// assert_eq!(leap + Duration::seconds(10), hmsm(3, 6, 9, 300)); -/// assert_eq!(leap + Duration::seconds(-10), hmsm(3, 5, 50, 300)); -/// assert_eq!(leap + Duration::days(1), -/// from_ymd(2016, 7, 9).and_hms_milli(3, 5, 59, 300)); -/// # } -/// ~~~~ -impl Add<OldDuration> for NaiveDateTime { - type Output = NaiveDateTime; - - #[inline] - fn add(self, rhs: OldDuration) -> NaiveDateTime { - self.checked_add_signed(rhs).expect("`NaiveDateTime + Duration` overflowed") - } -} - -impl AddAssign<OldDuration> for NaiveDateTime { - #[inline] - fn add_assign(&mut self, rhs: OldDuration) { - *self = self.add(rhs); - } -} - -/// A subtraction of `Duration` from `NaiveDateTime` yields another `NaiveDateTime`. -/// It is the same as the addition with a negated `Duration`. -/// -/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), -/// the addition assumes that **there is no leap second ever**, -/// except when the `NaiveDateTime` itself represents a leap second -/// in which case the assumption becomes that **there is exactly a single leap second ever**. -/// -/// Panics on underflow or overflow. -/// Use [`NaiveDateTime::checked_sub_signed`](#method.checked_sub_signed) to detect that. -/// -/// # Example -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// use chrono::{Duration, NaiveDate}; -/// -/// let from_ymd = NaiveDate::from_ymd; -/// -/// let d = from_ymd(2016, 7, 8); -/// let hms = |h, m, s| d.and_hms(h, m, s); -/// assert_eq!(hms(3, 5, 7) - Duration::zero(), hms(3, 5, 7)); -/// assert_eq!(hms(3, 5, 7) - Duration::seconds(1), hms(3, 5, 6)); -/// assert_eq!(hms(3, 5, 7) - Duration::seconds(-1), hms(3, 5, 8)); -/// assert_eq!(hms(3, 5, 7) - Duration::seconds(3600 + 60), hms(2, 4, 7)); -/// assert_eq!(hms(3, 5, 7) - Duration::seconds(86_400), -/// from_ymd(2016, 7, 7).and_hms(3, 5, 7)); -/// assert_eq!(hms(3, 5, 7) - Duration::days(365), -/// from_ymd(2015, 7, 9).and_hms(3, 5, 7)); -/// -/// let hmsm = |h, m, s, milli| d.and_hms_milli(h, m, s, milli); -/// assert_eq!(hmsm(3, 5, 7, 450) - Duration::milliseconds(670), hmsm(3, 5, 6, 780)); -/// # } -/// ~~~~ -/// -/// Leap seconds are handled, -/// but the subtraction assumes that it is the only leap second happened. -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// # use chrono::{Duration, NaiveDate}; -/// # let from_ymd = NaiveDate::from_ymd; -/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli(h, m, s, milli); -/// let leap = hmsm(3, 5, 59, 1_300); -/// assert_eq!(leap - Duration::zero(), hmsm(3, 5, 59, 1_300)); -/// assert_eq!(leap - Duration::milliseconds(200), hmsm(3, 5, 59, 1_100)); -/// assert_eq!(leap - Duration::milliseconds(500), hmsm(3, 5, 59, 800)); -/// assert_eq!(leap - Duration::seconds(60), hmsm(3, 5, 0, 300)); -/// assert_eq!(leap - Duration::days(1), -/// from_ymd(2016, 7, 7).and_hms_milli(3, 6, 0, 300)); -/// # } -/// ~~~~ -impl Sub<OldDuration> for NaiveDateTime { - type Output = NaiveDateTime; - - #[inline] - fn sub(self, rhs: OldDuration) -> NaiveDateTime { - self.checked_sub_signed(rhs).expect("`NaiveDateTime - Duration` overflowed") - } -} - -impl SubAssign<OldDuration> for NaiveDateTime { - #[inline] - fn sub_assign(&mut self, rhs: OldDuration) { - *self = self.sub(rhs); - } -} - -/// Subtracts another `NaiveDateTime` from the current date and time. -/// This does not overflow or underflow at all. -/// -/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), -/// the subtraction assumes that **there is no leap second ever**, -/// except when any of the `NaiveDateTime`s themselves represents a leap second -/// in which case the assumption becomes that -/// **there are exactly one (or two) leap second(s) ever**. -/// -/// The implementation is a wrapper around -/// [`NaiveDateTime::signed_duration_since`](#method.signed_duration_since). -/// -/// # Example -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// use chrono::{Duration, NaiveDate}; -/// -/// let from_ymd = NaiveDate::from_ymd; -/// -/// let d = from_ymd(2016, 7, 8); -/// assert_eq!(d.and_hms(3, 5, 7) - d.and_hms(2, 4, 6), Duration::seconds(3600 + 60 + 1)); -/// -/// // July 8 is 190th day in the year 2016 -/// let d0 = from_ymd(2016, 1, 1); -/// assert_eq!(d.and_hms_milli(0, 7, 6, 500) - d0.and_hms(0, 0, 0), -/// Duration::seconds(189 * 86_400 + 7 * 60 + 6) + Duration::milliseconds(500)); -/// # } -/// ~~~~ -/// -/// Leap seconds are handled, but the subtraction assumes that -/// there were no other leap seconds happened. -/// -/// ~~~~ -/// # extern crate chrono; fn main() { -/// # use chrono::{Duration, NaiveDate}; -/// # let from_ymd = NaiveDate::from_ymd; -/// let leap = from_ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_500); -/// assert_eq!(leap - from_ymd(2015, 6, 30).and_hms(23, 0, 0), -/// Duration::seconds(3600) + Duration::milliseconds(500)); -/// assert_eq!(from_ymd(2015, 7, 1).and_hms(1, 0, 0) - leap, -/// Duration::seconds(3600) - Duration::milliseconds(500)); -/// # } -/// ~~~~ -impl Sub<NaiveDateTime> for NaiveDateTime { - type Output = OldDuration; - - #[inline] - fn sub(self, rhs: NaiveDateTime) -> OldDuration { - self.signed_duration_since(rhs) - } -} - -/// The `Debug` output of the naive date and time `dt` is the same as -/// [`dt.format("%Y-%m-%dT%H:%M:%S%.f")`](../format/strftime/index.html). -/// -/// The string printed can be readily parsed via the `parse` method on `str`. -/// -/// It should be noted that, for leap seconds not on the minute boundary, -/// it may print a representation not distinguishable from non-leap seconds. -/// This doesn't matter in practice, since such leap seconds never happened. -/// (By the time of the first leap second on 1972-06-30, -/// every time zone offset around the world has standardized to the 5-minute alignment.) -/// -/// # Example -/// -/// ~~~~ -/// use chrono::NaiveDate; -/// -/// let dt = NaiveDate::from_ymd(2016, 11, 15).and_hms(7, 39, 24); -/// assert_eq!(format!("{:?}", dt), "2016-11-15T07:39:24"); -/// ~~~~ -/// -/// Leap seconds may also be used. -/// -/// ~~~~ -/// # use chrono::NaiveDate; -/// let dt = NaiveDate::from_ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_500); -/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60.500"); -/// ~~~~ -impl fmt::Debug for NaiveDateTime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}T{:?}", self.date, self.time) - } -} - -/// The `Display` output of the naive date and time `dt` is the same as -/// [`dt.format("%Y-%m-%d %H:%M:%S%.f")`](../format/strftime/index.html). -/// -/// It should be noted that, for leap seconds not on the minute boundary, -/// it may print a representation not distinguishable from non-leap seconds. -/// This doesn't matter in practice, since such leap seconds never happened. -/// (By the time of the first leap second on 1972-06-30, -/// every time zone offset around the world has standardized to the 5-minute alignment.) -/// -/// # Example -/// -/// ~~~~ -/// use chrono::NaiveDate; -/// -/// let dt = NaiveDate::from_ymd(2016, 11, 15).and_hms(7, 39, 24); -/// assert_eq!(format!("{}", dt), "2016-11-15 07:39:24"); -/// ~~~~ -/// -/// Leap seconds may also be used. -/// -/// ~~~~ -/// # use chrono::NaiveDate; -/// let dt = NaiveDate::from_ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_500); -/// assert_eq!(format!("{}", dt), "2015-06-30 23:59:60.500"); -/// ~~~~ -impl fmt::Display for NaiveDateTime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} {}", self.date, self.time) - } -} - -/// Parsing a `str` into a `NaiveDateTime` uses the same format, -/// [`%Y-%m-%dT%H:%M:%S%.f`](../format/strftime/index.html), as in `Debug`. -/// -/// # Example -/// -/// ~~~~ -/// use chrono::{NaiveDateTime, NaiveDate}; -/// -/// let dt = NaiveDate::from_ymd(2015, 9, 18).and_hms(23, 56, 4); -/// assert_eq!("2015-09-18T23:56:04".parse::<NaiveDateTime>(), Ok(dt)); -/// -/// let dt = NaiveDate::from_ymd(12345, 6, 7).and_hms_milli(7, 59, 59, 1_500); // leap second -/// assert_eq!("+12345-6-7T7:59:60.5".parse::<NaiveDateTime>(), Ok(dt)); -/// -/// assert!("foo".parse::<NaiveDateTime>().is_err()); -/// ~~~~ -impl str::FromStr for NaiveDateTime { - type Err = ParseError; - - fn from_str(s: &str) -> ParseResult<NaiveDateTime> { - const ITEMS: &'static [Item<'static>] = &[ - Item::Numeric(Numeric::Year, Pad::Zero), - Item::Space(""), - Item::Literal("-"), - Item::Numeric(Numeric::Month, Pad::Zero), - Item::Space(""), - Item::Literal("-"), - Item::Numeric(Numeric::Day, Pad::Zero), - Item::Space(""), - Item::Literal("T"), // XXX shouldn't this be case-insensitive? - Item::Numeric(Numeric::Hour, Pad::Zero), - Item::Space(""), - Item::Literal(":"), - Item::Numeric(Numeric::Minute, Pad::Zero), - Item::Space(""), - Item::Literal(":"), - Item::Numeric(Numeric::Second, Pad::Zero), - Item::Fixed(Fixed::Nanosecond), - Item::Space(""), - ]; - - let mut parsed = Parsed::new(); - parse(&mut parsed, s, ITEMS.iter())?; - parsed.to_naive_datetime_with_offset(0) - } -} - -#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] -fn test_encodable_json<F, E>(to_string: F) -where - F: Fn(&NaiveDateTime) -> Result<String, E>, - E: ::std::fmt::Debug, -{ - use naive::{MAX_DATE, MIN_DATE}; - - assert_eq!( - to_string(&NaiveDate::from_ymd(2016, 7, 8).and_hms_milli(9, 10, 48, 90)).ok(), - Some(r#""2016-07-08T09:10:48.090""#.into()) - ); - assert_eq!( - to_string(&NaiveDate::from_ymd(2014, 7, 24).and_hms(12, 34, 6)).ok(), - Some(r#""2014-07-24T12:34:06""#.into()) - ); - assert_eq!( - to_string(&NaiveDate::from_ymd(0, 1, 1).and_hms_milli(0, 0, 59, 1_000)).ok(), - Some(r#""0000-01-01T00:00:60""#.into()) - ); - assert_eq!( - to_string(&NaiveDate::from_ymd(-1, 12, 31).and_hms_nano(23, 59, 59, 7)).ok(), - Some(r#""-0001-12-31T23:59:59.000000007""#.into()) - ); - assert_eq!( - to_string(&MIN_DATE.and_hms(0, 0, 0)).ok(), - Some(r#""-262144-01-01T00:00:00""#.into()) - ); - assert_eq!( - to_string(&MAX_DATE.and_hms_nano(23, 59, 59, 1_999_999_999)).ok(), - Some(r#""+262143-12-31T23:59:60.999999999""#.into()) - ); -} - -#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] -fn test_decodable_json<F, E>(from_str: F) -where - F: Fn(&str) -> Result<NaiveDateTime, E>, - E: ::std::fmt::Debug, -{ - use naive::{MAX_DATE, MIN_DATE}; - - assert_eq!( - from_str(r#""2016-07-08T09:10:48.090""#).ok(), - Some(NaiveDate::from_ymd(2016, 7, 8).and_hms_milli(9, 10, 48, 90)) - ); - assert_eq!( - from_str(r#""2016-7-8T9:10:48.09""#).ok(), - Some(NaiveDate::from_ymd(2016, 7, 8).and_hms_milli(9, 10, 48, 90)) - ); - assert_eq!( - from_str(r#""2014-07-24T12:34:06""#).ok(), - Some(NaiveDate::from_ymd(2014, 7, 24).and_hms(12, 34, 6)) - ); - assert_eq!( - from_str(r#""0000-01-01T00:00:60""#).ok(), - Some(NaiveDate::from_ymd(0, 1, 1).and_hms_milli(0, 0, 59, 1_000)) - ); - assert_eq!( - from_str(r#""0-1-1T0:0:60""#).ok(), - Some(NaiveDate::from_ymd(0, 1, 1).and_hms_milli(0, 0, 59, 1_000)) - ); - assert_eq!( - from_str(r#""-0001-12-31T23:59:59.000000007""#).ok(), - Some(NaiveDate::from_ymd(-1, 12, 31).and_hms_nano(23, 59, 59, 7)) - ); - assert_eq!(from_str(r#""-262144-01-01T00:00:00""#).ok(), Some(MIN_DATE.and_hms(0, 0, 0))); - assert_eq!( - from_str(r#""+262143-12-31T23:59:60.999999999""#).ok(), - Some(MAX_DATE.and_hms_nano(23, 59, 59, 1_999_999_999)) - ); - assert_eq!( - from_str(r#""+262143-12-31T23:59:60.9999999999997""#).ok(), // excess digits are ignored - Some(MAX_DATE.and_hms_nano(23, 59, 59, 1_999_999_999)) - ); - - // bad formats - assert!(from_str(r#""""#).is_err()); - assert!(from_str(r#""2016-07-08""#).is_err()); - assert!(from_str(r#""09:10:48.090""#).is_err()); - assert!(from_str(r#""20160708T091048.090""#).is_err()); - assert!(from_str(r#""2000-00-00T00:00:00""#).is_err()); - assert!(from_str(r#""2000-02-30T00:00:00""#).is_err()); - assert!(from_str(r#""2001-02-29T00:00:00""#).is_err()); - assert!(from_str(r#""2002-02-28T24:00:00""#).is_err()); - assert!(from_str(r#""2002-02-28T23:60:00""#).is_err()); - assert!(from_str(r#""2002-02-28T23:59:61""#).is_err()); - assert!(from_str(r#""2016-07-08T09:10:48,090""#).is_err()); - assert!(from_str(r#""2016-07-08 09:10:48.090""#).is_err()); - assert!(from_str(r#""2016-007-08T09:10:48.090""#).is_err()); - assert!(from_str(r#""yyyy-mm-ddThh:mm:ss.fffffffff""#).is_err()); - assert!(from_str(r#"20160708000000"#).is_err()); - assert!(from_str(r#"{}"#).is_err()); - // pre-0.3.0 rustc-serialize format is now invalid - assert!(from_str(r#"{"date":{"ymdf":20},"time":{"secs":0,"frac":0}}"#).is_err()); - assert!(from_str(r#"null"#).is_err()); -} - -#[cfg(all(test, feature = "rustc-serialize"))] -fn test_decodable_json_timestamp<F, E>(from_str: F) -where - F: Fn(&str) -> Result<rustc_serialize::TsSeconds, E>, - E: ::std::fmt::Debug, -{ - assert_eq!( - *from_str("0").unwrap(), - NaiveDate::from_ymd(1970, 1, 1).and_hms(0, 0, 0), - "should parse integers as timestamps" - ); - assert_eq!( - *from_str("-1").unwrap(), - NaiveDate::from_ymd(1969, 12, 31).and_hms(23, 59, 59), - "should parse integers as timestamps" - ); -} - -#[cfg(feature = "rustc-serialize")] -pub mod rustc_serialize { - use super::NaiveDateTime; - use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; - use std::ops::Deref; - - impl Encodable for NaiveDateTime { - fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { - format!("{:?}", self).encode(s) - } - } - - impl Decodable for NaiveDateTime { - fn decode<D: Decoder>(d: &mut D) -> Result<NaiveDateTime, D::Error> { - d.read_str()?.parse().map_err(|_| d.error("invalid date time string")) - } - } - - /// A `DateTime` that can be deserialized from a seconds-based timestamp - #[derive(Debug)] - #[deprecated( - since = "1.4.2", - note = "RustcSerialize will be removed before chrono 1.0, use Serde instead" - )] - pub struct TsSeconds(NaiveDateTime); - - #[allow(deprecated)] - impl From<TsSeconds> for NaiveDateTime { - /// Pull the internal NaiveDateTime out - #[allow(deprecated)] - fn from(obj: TsSeconds) -> NaiveDateTime { - obj.0 - } - } - - #[allow(deprecated)] - impl Deref for TsSeconds { - type Target = NaiveDateTime; - - #[allow(deprecated)] - fn deref(&self) -> &Self::Target { - &self.0 - } - } - - #[allow(deprecated)] - impl Decodable for TsSeconds { - #[allow(deprecated)] - fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds, D::Error> { - Ok(TsSeconds( - NaiveDateTime::from_timestamp_opt(d.read_i64()?, 0) - .ok_or_else(|| d.error("invalid timestamp"))?, - )) - } - } - - #[cfg(test)] - use rustc_serialize::json; - - #[test] - fn test_encodable() { - super::test_encodable_json(json::encode); - } - - #[test] - fn test_decodable() { - super::test_decodable_json(json::decode); - } - - #[test] - fn test_decodable_timestamps() { - super::test_decodable_json_timestamp(json::decode); - } -} - -/// Tools to help serializing/deserializing `NaiveDateTime`s -#[cfg(feature = "serde")] -pub mod serde { - use super::NaiveDateTime; - use core::fmt; - use serdelib::{de, ser}; - - /// Serialize a `NaiveDateTime` as an RFC 3339 string - /// - /// See [the `serde` module](./serde/index.html) for alternate - /// serialization formats. - impl ser::Serialize for NaiveDateTime { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: ser::Serializer, - { - struct FormatWrapped<'a, D: 'a> { - inner: &'a D, - } - - impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } - } - - serializer.collect_str(&FormatWrapped { inner: &self }) - } - } - - struct NaiveDateTimeVisitor; - - impl<'de> de::Visitor<'de> for NaiveDateTimeVisitor { - type Value = NaiveDateTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a formatted date and time string") - } - - fn visit_str<E>(self, value: &str) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - value.parse().map_err(E::custom) - } - } - - impl<'de> de::Deserialize<'de> for NaiveDateTime { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: de::Deserializer<'de>, - { - deserializer.deserialize_str(NaiveDateTimeVisitor) - } - } - - /// Used to serialize/deserialize from nanosecond-precision timestamps - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// use chrono::naive::serde::ts_nanoseconds; - /// #[derive(Deserialize, Serialize)] - /// struct S { - /// #[serde(with = "ts_nanoseconds")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let time = NaiveDate::from_ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733); - /// let my_s = S { - /// time: time.clone(), - /// }; - /// - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); - /// let my_s: S = serde_json::from_str(&as_string)?; - /// assert_eq!(my_s.time, time); - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub mod ts_nanoseconds { - use core::fmt; - use serdelib::{de, ser}; - - use {ne_timestamp, NaiveDateTime}; - - /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch - /// - /// Intended for use with `serde`s `serialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # #[macro_use] extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// # use serde::Serialize; - /// use chrono::naive::serde::ts_nanoseconds::serialize as to_nano_ts; - /// #[derive(Serialize)] - /// struct S { - /// #[serde(serialize_with = "to_nano_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<String, serde_json::Error> { - /// let my_s = S { - /// time: NaiveDate::from_ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733), - /// }; - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); - /// # Ok(as_string) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> - where - S: ser::Serializer, - { - serializer.serialize_i64(dt.timestamp_nanos()) - } - - /// Deserialize a `DateTime` from a nanoseconds timestamp - /// - /// Intended for use with `serde`s `deserialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{NaiveDateTime, Utc}; - /// # use serde::Deserialize; - /// use chrono::naive::serde::ts_nanoseconds::deserialize as from_nano_ts; - /// #[derive(Deserialize)] - /// struct S { - /// #[serde(deserialize_with = "from_nano_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?; - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> - where - D: de::Deserializer<'de>, - { - Ok(d.deserialize_i64(NaiveDateTimeFromNanoSecondsVisitor)?) - } - - struct NaiveDateTimeFromNanoSecondsVisitor; - - impl<'de> de::Visitor<'de> for NaiveDateTimeFromNanoSecondsVisitor { - type Value = NaiveDateTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a unix timestamp") - } - - fn visit_i64<E>(self, value: i64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt( - value / 1_000_000_000, - (value % 1_000_000_000) as u32, - ) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - - fn visit_u64<E>(self, value: u64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt( - value as i64 / 1_000_000_000, - (value as i64 % 1_000_000_000) as u32, - ) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - } - } - - /// Used to serialize/deserialize from millisecond-precision timestamps - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// use chrono::naive::serde::ts_milliseconds; - /// #[derive(Deserialize, Serialize)] - /// struct S { - /// #[serde(with = "ts_milliseconds")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let time = NaiveDate::from_ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918); - /// let my_s = S { - /// time: time.clone(), - /// }; - /// - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1526522699918}"#); - /// let my_s: S = serde_json::from_str(&as_string)?; - /// assert_eq!(my_s.time, time); - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub mod ts_milliseconds { - use core::fmt; - use serdelib::{de, ser}; - - use {ne_timestamp, NaiveDateTime}; - - /// Serialize a UTC datetime into an integer number of milliseconds since the epoch - /// - /// Intended for use with `serde`s `serialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # #[macro_use] extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// # use serde::Serialize; - /// use chrono::naive::serde::ts_milliseconds::serialize as to_milli_ts; - /// #[derive(Serialize)] - /// struct S { - /// #[serde(serialize_with = "to_milli_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<String, serde_json::Error> { - /// let my_s = S { - /// time: NaiveDate::from_ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918), - /// }; - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1526522699918}"#); - /// # Ok(as_string) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> - where - S: ser::Serializer, - { - serializer.serialize_i64(dt.timestamp_millis()) - } - - /// Deserialize a `DateTime` from a milliseconds timestamp - /// - /// Intended for use with `serde`s `deserialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{NaiveDateTime, Utc}; - /// # use serde::Deserialize; - /// use chrono::naive::serde::ts_milliseconds::deserialize as from_milli_ts; - /// #[derive(Deserialize)] - /// struct S { - /// #[serde(deserialize_with = "from_milli_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?; - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> - where - D: de::Deserializer<'de>, - { - Ok(d.deserialize_i64(NaiveDateTimeFromMilliSecondsVisitor)?) - } - - struct NaiveDateTimeFromMilliSecondsVisitor; - - impl<'de> de::Visitor<'de> for NaiveDateTimeFromMilliSecondsVisitor { - type Value = NaiveDateTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a unix timestamp") - } - - fn visit_i64<E>(self, value: i64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt(value / 1000, ((value % 1000) * 1_000_000) as u32) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - - fn visit_u64<E>(self, value: u64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt( - (value / 1000) as i64, - ((value % 1000) * 1_000_000) as u32, - ) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - } - } - - /// Used to serialize/deserialize from second-precision timestamps - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// use chrono::naive::serde::ts_seconds; - /// #[derive(Deserialize, Serialize)] - /// struct S { - /// #[serde(with = "ts_seconds")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let time = NaiveDate::from_ymd(2015, 5, 15).and_hms(10, 0, 0); - /// let my_s = S { - /// time: time.clone(), - /// }; - /// - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1431684000}"#); - /// let my_s: S = serde_json::from_str(&as_string)?; - /// assert_eq!(my_s.time, time); - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub mod ts_seconds { - use core::fmt; - use serdelib::{de, ser}; - - use {ne_timestamp, NaiveDateTime}; - - /// Serialize a UTC datetime into an integer number of seconds since the epoch - /// - /// Intended for use with `serde`s `serialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # #[macro_use] extern crate serde; - /// # extern crate chrono; - /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; - /// # use serde::Serialize; - /// use chrono::naive::serde::ts_seconds::serialize as to_ts; - /// #[derive(Serialize)] - /// struct S { - /// #[serde(serialize_with = "to_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<String, serde_json::Error> { - /// let my_s = S { - /// time: NaiveDate::from_ymd(2015, 5, 15).and_hms(10, 0, 0), - /// }; - /// let as_string = serde_json::to_string(&my_s)?; - /// assert_eq!(as_string, r#"{"time":1431684000}"#); - /// # Ok(as_string) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> - where - S: ser::Serializer, - { - serializer.serialize_i64(dt.timestamp()) - } - - /// Deserialize a `DateTime` from a seconds timestamp - /// - /// Intended for use with `serde`s `deserialize_with` attribute. - /// - /// # Example: - /// - /// ```rust - /// # // We mark this ignored so that we can test on 1.13 (which does not - /// # // support custom derive), and run tests with --ignored on beta and - /// # // nightly to actually trigger these. - /// # - /// # #[macro_use] extern crate serde_derive; - /// # #[macro_use] extern crate serde_json; - /// # extern crate serde; - /// # extern crate chrono; - /// # use chrono::{NaiveDateTime, Utc}; - /// # use serde::Deserialize; - /// use chrono::naive::serde::ts_seconds::deserialize as from_ts; - /// #[derive(Deserialize)] - /// struct S { - /// #[serde(deserialize_with = "from_ts")] - /// time: NaiveDateTime - /// } - /// - /// # fn example() -> Result<S, serde_json::Error> { - /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?; - /// # Ok(my_s) - /// # } - /// # fn main() { example().unwrap(); } - /// ``` - pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> - where - D: de::Deserializer<'de>, - { - Ok(d.deserialize_i64(NaiveDateTimeFromSecondsVisitor)?) - } - - struct NaiveDateTimeFromSecondsVisitor; - - impl<'de> de::Visitor<'de> for NaiveDateTimeFromSecondsVisitor { - type Value = NaiveDateTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a unix timestamp") - } - - fn visit_i64<E>(self, value: i64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt(value, 0) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - - fn visit_u64<E>(self, value: u64) -> Result<NaiveDateTime, E> - where - E: de::Error, - { - NaiveDateTime::from_timestamp_opt(value as i64, 0) - .ok_or_else(|| E::custom(ne_timestamp(value))) - } - } - } - - #[cfg(test)] - extern crate bincode; - #[cfg(test)] - extern crate serde_derive; - #[cfg(test)] - extern crate serde_json; - - #[test] - fn test_serde_serialize() { - super::test_encodable_json(self::serde_json::to_string); - } - - #[test] - fn test_serde_deserialize() { - super::test_decodable_json(|input| self::serde_json::from_str(&input)); - } - - // Bincode is relevant to test separately from JSON because - // it is not self-describing. - #[test] - fn test_serde_bincode() { - use self::bincode::{deserialize, serialize, Infinite}; - use naive::NaiveDate; - - let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_milli(9, 10, 48, 90); - let encoded = serialize(&dt, Infinite).unwrap(); - let decoded: NaiveDateTime = deserialize(&encoded).unwrap(); - assert_eq!(dt, decoded); - } - - #[test] - fn test_serde_bincode_optional() { - use self::bincode::{deserialize, serialize, Infinite}; - use self::serde_derive::{Deserialize, Serialize}; - use prelude::*; - use serde::ts_nanoseconds_option; - - #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] - struct Test { - one: Option<i64>, - #[serde(with = "ts_nanoseconds_option")] - two: Option<DateTime<Utc>>, - } - - let expected = Test { one: Some(1), two: Some(Utc.ymd(1970, 1, 1).and_hms(0, 1, 1)) }; - let bytes: Vec<u8> = serialize(&expected, Infinite).unwrap(); - let actual = deserialize::<Test>(&(bytes)).unwrap(); - - assert_eq!(expected, actual); - } -} - -#[cfg(test)] -mod tests { - use super::NaiveDateTime; - use naive::{NaiveDate, MAX_DATE, MIN_DATE}; - use oldtime::Duration; - use std::i64; - use Datelike; - - #[test] - fn test_datetime_from_timestamp() { - let from_timestamp = |secs| NaiveDateTime::from_timestamp_opt(secs, 0); - let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - assert_eq!(from_timestamp(-1), Some(ymdhms(1969, 12, 31, 23, 59, 59))); - assert_eq!(from_timestamp(0), Some(ymdhms(1970, 1, 1, 0, 0, 0))); - assert_eq!(from_timestamp(1), Some(ymdhms(1970, 1, 1, 0, 0, 1))); - assert_eq!(from_timestamp(1_000_000_000), Some(ymdhms(2001, 9, 9, 1, 46, 40))); - assert_eq!(from_timestamp(0x7fffffff), Some(ymdhms(2038, 1, 19, 3, 14, 7))); - assert_eq!(from_timestamp(i64::MIN), None); - assert_eq!(from_timestamp(i64::MAX), None); - } - - #[test] - fn test_datetime_add() { - fn check( - (y, m, d, h, n, s): (i32, u32, u32, u32, u32, u32), - rhs: Duration, - result: Option<(i32, u32, u32, u32, u32, u32)>, - ) { - let lhs = NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - let sum = - result.map(|(y, m, d, h, n, s)| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s)); - assert_eq!(lhs.checked_add_signed(rhs), sum); - assert_eq!(lhs.checked_sub_signed(-rhs), sum); - }; - - check( - (2014, 5, 6, 7, 8, 9), - Duration::seconds(3600 + 60 + 1), - Some((2014, 5, 6, 8, 9, 10)), - ); - check( - (2014, 5, 6, 7, 8, 9), - Duration::seconds(-(3600 + 60 + 1)), - Some((2014, 5, 6, 6, 7, 8)), - ); - check((2014, 5, 6, 7, 8, 9), Duration::seconds(86399), Some((2014, 5, 7, 7, 8, 8))); - check((2014, 5, 6, 7, 8, 9), Duration::seconds(86_400 * 10), Some((2014, 5, 16, 7, 8, 9))); - check((2014, 5, 6, 7, 8, 9), Duration::seconds(-86_400 * 10), Some((2014, 4, 26, 7, 8, 9))); - check((2014, 5, 6, 7, 8, 9), Duration::seconds(86_400 * 10), Some((2014, 5, 16, 7, 8, 9))); - - // overflow check - // assumes that we have correct values for MAX/MIN_DAYS_FROM_YEAR_0 from `naive::date`. - // (they are private constants, but the equivalence is tested in that module.) - let max_days_from_year_0 = MAX_DATE.signed_duration_since(NaiveDate::from_ymd(0, 1, 1)); - check((0, 1, 1, 0, 0, 0), max_days_from_year_0, Some((MAX_DATE.year(), 12, 31, 0, 0, 0))); - check( - (0, 1, 1, 0, 0, 0), - max_days_from_year_0 + Duration::seconds(86399), - Some((MAX_DATE.year(), 12, 31, 23, 59, 59)), - ); - check((0, 1, 1, 0, 0, 0), max_days_from_year_0 + Duration::seconds(86_400), None); - check((0, 1, 1, 0, 0, 0), Duration::max_value(), None); - - let min_days_from_year_0 = MIN_DATE.signed_duration_since(NaiveDate::from_ymd(0, 1, 1)); - check((0, 1, 1, 0, 0, 0), min_days_from_year_0, Some((MIN_DATE.year(), 1, 1, 0, 0, 0))); - check((0, 1, 1, 0, 0, 0), min_days_from_year_0 - Duration::seconds(1), None); - check((0, 1, 1, 0, 0, 0), Duration::min_value(), None); - } - - #[test] - fn test_datetime_sub() { - let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - let since = NaiveDateTime::signed_duration_since; - assert_eq!( - since(ymdhms(2014, 5, 6, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 9)), - Duration::zero() - ); - assert_eq!( - since(ymdhms(2014, 5, 6, 7, 8, 10), ymdhms(2014, 5, 6, 7, 8, 9)), - Duration::seconds(1) - ); - assert_eq!( - since(ymdhms(2014, 5, 6, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 10)), - Duration::seconds(-1) - ); - assert_eq!( - since(ymdhms(2014, 5, 7, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 10)), - Duration::seconds(86399) - ); - assert_eq!( - since(ymdhms(2001, 9, 9, 1, 46, 39), ymdhms(1970, 1, 1, 0, 0, 0)), - Duration::seconds(999_999_999) - ); - } - - #[test] - fn test_datetime_addassignment() { - let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - let mut date = ymdhms(2016, 10, 1, 10, 10, 10); - date += Duration::minutes(10_000_000); - assert_eq!(date, ymdhms(2035, 10, 6, 20, 50, 10)); - date += Duration::days(10); - assert_eq!(date, ymdhms(2035, 10, 16, 20, 50, 10)); - } - - #[test] - fn test_datetime_subassignment() { - let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - let mut date = ymdhms(2016, 10, 1, 10, 10, 10); - date -= Duration::minutes(10_000_000); - assert_eq!(date, ymdhms(1997, 9, 26, 23, 30, 10)); - date -= Duration::days(10); - assert_eq!(date, ymdhms(1997, 9, 16, 23, 30, 10)); - } - - #[test] - fn test_datetime_timestamp() { - let to_timestamp = - |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s).timestamp(); - assert_eq!(to_timestamp(1969, 12, 31, 23, 59, 59), -1); - assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 0), 0); - assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 1), 1); - assert_eq!(to_timestamp(2001, 9, 9, 1, 46, 40), 1_000_000_000); - assert_eq!(to_timestamp(2038, 1, 19, 3, 14, 7), 0x7fffffff); - } - - #[test] - fn test_datetime_from_str() { - // valid cases - let valid = [ - "2015-2-18T23:16:9.15", - "-77-02-18T23:16:09", - " +82701 - 05 - 6 T 15 : 9 : 60.898989898989 ", - ]; - for &s in &valid { - let d = match s.parse::<NaiveDateTime>() { - Ok(d) => d, - Err(e) => panic!("parsing `{}` has failed: {}", s, e), - }; - let s_ = format!("{:?}", d); - // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same - let d_ = match s_.parse::<NaiveDateTime>() { - Ok(d) => d, - Err(e) => { - panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}", s, d, e) - } - }; - assert!( - d == d_, - "`{}` is parsed into `{:?}`, but reparsed result \ - `{:?}` does not match", - s, - d, - d_ - ); - } - - // some invalid cases - // since `ParseErrorKind` is private, all we can do is to check if there was an error - assert!("".parse::<NaiveDateTime>().is_err()); - assert!("x".parse::<NaiveDateTime>().is_err()); - assert!("15".parse::<NaiveDateTime>().is_err()); - assert!("15:8:9".parse::<NaiveDateTime>().is_err()); - assert!("15-8-9".parse::<NaiveDateTime>().is_err()); - assert!("2015-15-15T15:15:15".parse::<NaiveDateTime>().is_err()); - assert!("2012-12-12T12:12:12x".parse::<NaiveDateTime>().is_err()); - assert!("2012-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); - assert!("+ 82701-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); - assert!("+802701-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); // out-of-bound - } - - #[test] - fn test_datetime_parse_from_str() { - let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd(y, m, d).and_hms(h, n, s); - let ymdhmsn = - |y, m, d, h, n, s, nano| NaiveDate::from_ymd(y, m, d).and_hms_nano(h, n, s, nano); - assert_eq!( - NaiveDateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), - Ok(ymdhms(2014, 5, 7, 12, 34, 56)) - ); // ignore offset - assert_eq!( - NaiveDateTime::parse_from_str("2015-W06-1 000000", "%G-W%V-%u%H%M%S"), - Ok(ymdhms(2015, 2, 2, 0, 0, 0)) - ); - assert_eq!( - NaiveDateTime::parse_from_str( - "Fri, 09 Aug 2013 23:54:35 GMT", - "%a, %d %b %Y %H:%M:%S GMT" - ), - Ok(ymdhms(2013, 8, 9, 23, 54, 35)) - ); - assert!(NaiveDateTime::parse_from_str( - "Sat, 09 Aug 2013 23:54:35 GMT", - "%a, %d %b %Y %H:%M:%S GMT" - ) - .is_err()); - assert!(NaiveDateTime::parse_from_str("2014-5-7 12:3456", "%Y-%m-%d %H:%M:%S").is_err()); - assert!(NaiveDateTime::parse_from_str("12:34:56", "%H:%M:%S").is_err()); // insufficient - assert_eq!( - NaiveDateTime::parse_from_str("1441497364", "%s"), - Ok(ymdhms(2015, 9, 5, 23, 56, 4)) - ); - assert_eq!( - NaiveDateTime::parse_from_str("1283929614.1234", "%s.%f"), - Ok(ymdhmsn(2010, 9, 8, 7, 6, 54, 1234)) - ); - assert_eq!( - NaiveDateTime::parse_from_str("1441497364.649", "%s%.3f"), - Ok(ymdhmsn(2015, 9, 5, 23, 56, 4, 649000000)) - ); - assert_eq!( - NaiveDateTime::parse_from_str("1497854303.087654", "%s%.6f"), - Ok(ymdhmsn(2017, 6, 19, 6, 38, 23, 87654000)) - ); - assert_eq!( - NaiveDateTime::parse_from_str("1437742189.918273645", "%s%.9f"), - Ok(ymdhmsn(2015, 7, 24, 12, 49, 49, 918273645)) - ); - } - - #[test] - fn test_datetime_format() { - let dt = NaiveDate::from_ymd(2010, 9, 8).and_hms_milli(7, 6, 54, 321); - assert_eq!(dt.format("%c").to_string(), "Wed Sep 8 07:06:54 2010"); - assert_eq!(dt.format("%s").to_string(), "1283929614"); - assert_eq!(dt.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); - - // a horror of leap second: coming near to you. - let dt = NaiveDate::from_ymd(2012, 6, 30).and_hms_milli(23, 59, 59, 1_000); - assert_eq!(dt.format("%c").to_string(), "Sat Jun 30 23:59:60 2012"); - assert_eq!(dt.format("%s").to_string(), "1341100799"); // not 1341100800, it's intentional. - } - - #[test] - fn test_datetime_add_sub_invariant() { - // issue #37 - let base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0); - let t = -946684799990000; - let time = base + Duration::microseconds(t); - assert_eq!(t, time.signed_duration_since(base).num_microseconds().unwrap()); - } - - #[test] - fn test_nanosecond_range() { - const A_BILLION: i64 = 1_000_000_000; - let maximum = "2262-04-11T23:47:16.854775804"; - let parsed: NaiveDateTime = maximum.parse().unwrap(); - let nanos = parsed.timestamp_nanos(); - assert_eq!( - parsed, - NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32) - ); - - let minimum = "1677-09-21T00:12:44.000000000"; - let parsed: NaiveDateTime = minimum.parse().unwrap(); - let nanos = parsed.timestamp_nanos(); - assert_eq!( - parsed, - NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32) - ); - } -} diff --git a/vendor/chrono/src/naive/datetime/mod.rs b/vendor/chrono/src/naive/datetime/mod.rs new file mode 100644 index 000000000..ec0d842c0 --- /dev/null +++ b/vendor/chrono/src/naive/datetime/mod.rs @@ -0,0 +1,1946 @@ +// This is a part of Chrono. +// See README.md and LICENSE.txt for details. + +//! ISO 8601 date and time without timezone. + +#[cfg(any(feature = "alloc", feature = "std", test))] +use core::borrow::Borrow; +use core::convert::TryFrom; +use core::fmt::Write; +use core::ops::{Add, AddAssign, Sub, SubAssign}; +use core::{fmt, str}; + +use num_integer::div_mod_floor; +use num_traits::ToPrimitive; +#[cfg(feature = "rkyv")] +use rkyv::{Archive, Deserialize, Serialize}; + +#[cfg(any(feature = "alloc", feature = "std", test))] +use crate::format::DelayedFormat; +use crate::format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; +use crate::format::{Fixed, Item, Numeric, Pad}; +use crate::naive::{Days, IsoWeek, NaiveDate, NaiveTime}; +use crate::oldtime::Duration as OldDuration; +use crate::{DateTime, Datelike, LocalResult, Months, TimeZone, Timelike, Weekday}; +use core::cmp::Ordering; + +#[cfg(feature = "rustc-serialize")] +pub(super) mod rustc_serialize; + +/// Tools to help serializing/deserializing `NaiveDateTime`s +#[cfg(feature = "serde")] +pub(crate) mod serde; + +#[cfg(test)] +mod tests; + +/// The tight upper bound guarantees that a duration with `|Duration| >= 2^MAX_SECS_BITS` +/// will always overflow the addition with any date and time type. +/// +/// So why is this needed? `Duration::seconds(rhs)` may overflow, and we don't have +/// an alternative returning `Option` or `Result`. Thus we need some early bound to avoid +/// touching that call when we are already sure that it WILL overflow... +const MAX_SECS_BITS: usize = 44; + +/// Number of nanoseconds in a millisecond +const NANOS_IN_MILLISECOND: u32 = 1_000_000; +/// Number of nanoseconds in a second +const NANOS_IN_SECOND: u32 = 1000 * NANOS_IN_MILLISECOND; + +/// The minimum possible `NaiveDateTime`. +#[deprecated(since = "0.4.20", note = "Use NaiveDateTime::MIN instead")] +pub const MIN_DATETIME: NaiveDateTime = NaiveDateTime::MIN; +/// The maximum possible `NaiveDateTime`. +#[deprecated(since = "0.4.20", note = "Use NaiveDateTime::MAX instead")] +pub const MAX_DATETIME: NaiveDateTime = NaiveDateTime::MAX; + +/// ISO 8601 combined date and time without timezone. +/// +/// # Example +/// +/// `NaiveDateTime` is commonly created from [`NaiveDate`](./struct.NaiveDate.html). +/// +/// ``` +/// use chrono::{NaiveDate, NaiveDateTime}; +/// +/// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(9, 10, 11).unwrap(); +/// # let _ = dt; +/// ``` +/// +/// You can use typical [date-like](../trait.Datelike.html) and +/// [time-like](../trait.Timelike.html) methods, +/// provided that relevant traits are in the scope. +/// +/// ``` +/// # use chrono::{NaiveDate, NaiveDateTime}; +/// # let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(9, 10, 11).unwrap(); +/// use chrono::{Datelike, Timelike, Weekday}; +/// +/// assert_eq!(dt.weekday(), Weekday::Fri); +/// assert_eq!(dt.num_seconds_from_midnight(), 33011); +/// ``` +#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)] +#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct NaiveDateTime { + date: NaiveDate, + time: NaiveTime, +} + +/// The unit of a timestamp expressed in fractions of a second. +/// Currently either milliseconds or microseconds. +/// +/// This is a private type, used in the implementation of +/// [NaiveDateTime::from_timestamp_millis] and [NaiveDateTime::from_timestamp_micros]. +#[derive(Clone, Copy, Debug)] +enum TimestampUnit { + Millis, + Micros, +} + +impl TimestampUnit { + fn per_second(self) -> u32 { + match self { + TimestampUnit::Millis => 1_000, + TimestampUnit::Micros => 1_000_000, + } + } + fn nanos_per(self) -> u32 { + match self { + TimestampUnit::Millis => 1_000_000, + TimestampUnit::Micros => 1_000, + } + } +} + +impl NaiveDateTime { + /// Makes a new `NaiveDateTime` from date and time components. + /// Equivalent to [`date.and_time(time)`](./struct.NaiveDate.html#method.and_time) + /// and many other helper constructors on `NaiveDate`. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime}; + /// + /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap(); + /// let t = NaiveTime::from_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// + /// let dt = NaiveDateTime::new(d, t); + /// assert_eq!(dt.date(), d); + /// assert_eq!(dt.time(), t); + /// ``` + #[inline] + pub const fn new(date: NaiveDate, time: NaiveTime) -> NaiveDateTime { + NaiveDateTime { date, time } + } + + /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, + /// from the number of non-leap seconds + /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") + /// and the number of nanoseconds since the last whole non-leap second. + /// + /// For a non-naive version of this function see + /// [`TimeZone::timestamp`](../offset/trait.TimeZone.html#method.timestamp). + /// + /// The nanosecond part can exceed 1,000,000,000 in order to represent the + /// [leap second](./struct.NaiveTime.html#leap-second-handling). (The true "UNIX + /// timestamp" cannot represent a leap second unambiguously.) + /// + /// Panics on the out-of-range number of seconds and/or invalid nanosecond. + #[deprecated(since = "0.4.23", note = "use `from_timestamp_opt()` instead")] + #[inline] + pub fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime { + let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs); + datetime.expect("invalid or out-of-range datetime") + } + + /// Creates a new [NaiveDateTime] from milliseconds since the UNIX epoch. + /// + /// The UNIX epoch starts on midnight, January 1, 1970, UTC. + /// + /// Returns `None` on an out-of-range number of milliseconds. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDateTime; + /// let timestamp_millis: i64 = 1662921288000; //Sunday, September 11, 2022 6:34:48 PM + /// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis); + /// assert!(naive_datetime.is_some()); + /// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis()); + /// + /// // Negative timestamps (before the UNIX epoch) are supported as well. + /// let timestamp_millis: i64 = -2208936075000; //Mon Jan 01 1900 14:38:45 GMT+0000 + /// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis); + /// assert!(naive_datetime.is_some()); + /// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis()); + /// ``` + #[inline] + pub fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> { + Self::from_timestamp_unit(millis, TimestampUnit::Millis) + } + + /// Creates a new [NaiveDateTime] from microseconds since the UNIX epoch. + /// + /// The UNIX epoch starts on midnight, January 1, 1970, UTC. + /// + /// Returns `None` on an out-of-range number of microseconds. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDateTime; + /// let timestamp_micros: i64 = 1662921288000000; //Sunday, September 11, 2022 6:34:48 PM + /// let naive_datetime = NaiveDateTime::from_timestamp_micros(timestamp_micros); + /// assert!(naive_datetime.is_some()); + /// assert_eq!(timestamp_micros, naive_datetime.unwrap().timestamp_micros()); + /// + /// // Negative timestamps (before the UNIX epoch) are supported as well. + /// let timestamp_micros: i64 = -2208936075000000; //Mon Jan 01 1900 14:38:45 GMT+0000 + /// let naive_datetime = NaiveDateTime::from_timestamp_micros(timestamp_micros); + /// assert!(naive_datetime.is_some()); + /// assert_eq!(timestamp_micros, naive_datetime.unwrap().timestamp_micros()); + /// ``` + #[inline] + pub fn from_timestamp_micros(micros: i64) -> Option<NaiveDateTime> { + Self::from_timestamp_unit(micros, TimestampUnit::Micros) + } + + /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, + /// from the number of non-leap seconds + /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") + /// and the number of nanoseconds since the last whole non-leap second. + /// + /// The nanosecond part can exceed 1,000,000,000 + /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling). + /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.) + /// + /// Returns `None` on the out-of-range number of seconds (more than 262 000 years away + /// from common era) and/or invalid nanosecond (2 seconds or more). + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDateTime, NaiveDate}; + /// use std::i64; + /// + /// let from_timestamp_opt = NaiveDateTime::from_timestamp_opt; + /// + /// assert!(from_timestamp_opt(0, 0).is_some()); + /// assert!(from_timestamp_opt(0, 999_999_999).is_some()); + /// assert!(from_timestamp_opt(0, 1_500_000_000).is_some()); // leap second + /// assert!(from_timestamp_opt(0, 2_000_000_000).is_none()); + /// assert!(from_timestamp_opt(i64::MAX, 0).is_none()); + /// ``` + #[inline] + pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> { + let (days, secs) = div_mod_floor(secs, 86_400); + let date = days + .to_i32() + .and_then(|days| days.checked_add(719_163)) + .and_then(NaiveDate::from_num_days_from_ce_opt); + let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs); + match (date, time) { + (Some(date), Some(time)) => Some(NaiveDateTime { date, time }), + (_, _) => None, + } + } + + /// Parses a string with the specified format string and returns a new `NaiveDateTime`. + /// See the [`format::strftime` module](../format/strftime/index.html) + /// on the supported escape sequences. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDateTime, NaiveDate}; + /// + /// let parse_from_str = NaiveDateTime::parse_from_str; + /// + /// assert_eq!(parse_from_str("2015-09-05 23:56:04", "%Y-%m-%d %H:%M:%S"), + /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap())); + /// assert_eq!(parse_from_str("5sep2015pm012345.6789", "%d%b%Y%p%I%M%S%.f"), + /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_micro_opt(13, 23, 45, 678_900).unwrap())); + /// ``` + /// + /// Offset is ignored for the purpose of parsing. + /// + /// ``` + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), + /// Ok(NaiveDate::from_ymd_opt(2014, 5, 17).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// ``` + /// + /// [Leap seconds](./struct.NaiveTime.html#leap-second-handling) are correctly handled by + /// treating any time of the form `hh:mm:60` as a leap second. + /// (This equally applies to the formatting, so the round trip is possible.) + /// + /// ``` + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("2015-07-01 08:59:60.123", "%Y-%m-%d %H:%M:%S%.f"), + /// Ok(NaiveDate::from_ymd_opt(2015, 7, 1).unwrap().and_hms_milli_opt(8, 59, 59, 1_123).unwrap())); + /// ``` + /// + /// Missing seconds are assumed to be zero, + /// but out-of-bound times or insufficient fields are errors otherwise. + /// + /// ``` + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("94/9/4 7:15", "%y/%m/%d %H:%M"), + /// Ok(NaiveDate::from_ymd_opt(1994, 9, 4).unwrap().and_hms_opt(7, 15, 0).unwrap())); + /// + /// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err()); + /// assert!(parse_from_str("94/9/4 12", "%y/%m/%d %H").is_err()); + /// assert!(parse_from_str("94/9/4 17:60", "%y/%m/%d %H:%M").is_err()); + /// assert!(parse_from_str("94/9/4 24:00:00", "%y/%m/%d %H:%M:%S").is_err()); + /// ``` + /// + /// All parsed fields should be consistent to each other, otherwise it's an error. + /// + /// ``` + /// # use chrono::NaiveDateTime; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// let fmt = "%Y-%m-%d %H:%M:%S = UNIX timestamp %s"; + /// assert!(parse_from_str("2001-09-09 01:46:39 = UNIX timestamp 999999999", fmt).is_ok()); + /// assert!(parse_from_str("1970-01-01 00:00:00 = UNIX timestamp 1", fmt).is_err()); + /// ``` + /// + /// Years before 1 BCE or after 9999 CE, require an initial sign + /// + ///``` + /// # use chrono::{NaiveDate, NaiveDateTime}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// let fmt = "%Y-%m-%d %H:%M:%S"; + /// assert!(parse_from_str("10000-09-09 01:46:39", fmt).is_err()); + /// assert!(parse_from_str("+10000-09-09 01:46:39", fmt).is_ok()); + ///``` + pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDateTime> { + let mut parsed = Parsed::new(); + parse(&mut parsed, s, StrftimeItems::new(fmt))?; + parsed.to_naive_datetime_with_offset(0) // no offset adjustment + } + + /// Retrieves a date component. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(9, 10, 11).unwrap(); + /// assert_eq!(dt.date(), NaiveDate::from_ymd_opt(2016, 7, 8).unwrap()); + /// ``` + #[inline] + pub const fn date(&self) -> NaiveDate { + self.date + } + + /// Retrieves a time component. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveTime}; + /// + /// let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(9, 10, 11).unwrap(); + /// assert_eq!(dt.time(), NaiveTime::from_hms_opt(9, 10, 11).unwrap()); + /// ``` + #[inline] + pub const fn time(&self) -> NaiveTime { + self.time + } + + /// Returns the number of non-leap seconds since the midnight on January 1, 1970. + /// + /// Note that this does *not* account for the timezone! + /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_milli_opt(0, 0, 1, 980).unwrap(); + /// assert_eq!(dt.timestamp(), 1); + /// + /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9).unwrap().and_hms_opt(1, 46, 40).unwrap(); + /// assert_eq!(dt.timestamp(), 1_000_000_000); + /// + /// let dt = NaiveDate::from_ymd_opt(1969, 12, 31).unwrap().and_hms_opt(23, 59, 59).unwrap(); + /// assert_eq!(dt.timestamp(), -1); + /// + /// let dt = NaiveDate::from_ymd_opt(-1, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap(); + /// assert_eq!(dt.timestamp(), -62198755200); + /// ``` + #[inline] + pub fn timestamp(&self) -> i64 { + const UNIX_EPOCH_DAY: i64 = 719_163; + let gregorian_day = i64::from(self.date.num_days_from_ce()); + let seconds_from_midnight = i64::from(self.time.num_seconds_from_midnight()); + (gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight + } + + /// Returns the number of non-leap *milliseconds* since midnight on January 1, 1970. + /// + /// Note that this does *not* account for the timezone! + /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. + /// + /// Note also that this does reduce the number of years that can be + /// represented from ~584 Billion to ~584 Million. (If this is a problem, + /// please file an issue to let me know what domain needs millisecond + /// precision over billions of years, I'm curious.) + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_milli_opt(0, 0, 1, 444).unwrap(); + /// assert_eq!(dt.timestamp_millis(), 1_444); + /// + /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9).unwrap().and_hms_milli_opt(1, 46, 40, 555).unwrap(); + /// assert_eq!(dt.timestamp_millis(), 1_000_000_000_555); + /// + /// let dt = NaiveDate::from_ymd_opt(1969, 12, 31).unwrap().and_hms_milli_opt(23, 59, 59, 100).unwrap(); + /// assert_eq!(dt.timestamp_millis(), -900); + /// ``` + #[inline] + pub fn timestamp_millis(&self) -> i64 { + let as_ms = self.timestamp() * 1000; + as_ms + i64::from(self.timestamp_subsec_millis()) + } + + /// Returns the number of non-leap *microseconds* since midnight on January 1, 1970. + /// + /// Note that this does *not* account for the timezone! + /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. + /// + /// Note also that this does reduce the number of years that can be + /// represented from ~584 Billion to ~584 Thousand. (If this is a problem, + /// please file an issue to let me know what domain needs microsecond + /// precision over millennia, I'm curious.) + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_micro_opt(0, 0, 1, 444).unwrap(); + /// assert_eq!(dt.timestamp_micros(), 1_000_444); + /// + /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9).unwrap().and_hms_micro_opt(1, 46, 40, 555).unwrap(); + /// assert_eq!(dt.timestamp_micros(), 1_000_000_000_000_555); + /// ``` + #[inline] + pub fn timestamp_micros(&self) -> i64 { + let as_us = self.timestamp() * 1_000_000; + as_us + i64::from(self.timestamp_subsec_micros()) + } + + /// Returns the number of non-leap *nanoseconds* since midnight on January 1, 1970. + /// + /// Note that this does *not* account for the timezone! + /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. + /// + /// # Panics + /// + /// Note also that this does reduce the number of years that can be + /// represented from ~584 Billion to ~584 years. The dates that can be + /// represented as nanoseconds are between 1677-09-21T00:12:44.0 and + /// 2262-04-11T23:47:16.854775804. + /// + /// (If this is a problem, please file an issue to let me know what domain + /// needs nanosecond precision over millennia, I'm curious.) + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime}; + /// + /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_nano_opt(0, 0, 1, 444).unwrap(); + /// assert_eq!(dt.timestamp_nanos(), 1_000_000_444); + /// + /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9).unwrap().and_hms_nano_opt(1, 46, 40, 555).unwrap(); + /// + /// const A_BILLION: i64 = 1_000_000_000; + /// let nanos = dt.timestamp_nanos(); + /// assert_eq!(nanos, 1_000_000_000_000_000_555); + /// assert_eq!( + /// dt, + /// NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32) + /// ); + /// ``` + #[inline] + pub fn timestamp_nanos(&self) -> i64 { + let as_ns = self.timestamp() * 1_000_000_000; + as_ns + i64::from(self.timestamp_subsec_nanos()) + } + + /// Returns the number of milliseconds since the last whole non-leap second. + /// + /// The return value ranges from 0 to 999, + /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_nano_opt(9, 10, 11, 123_456_789).unwrap(); + /// assert_eq!(dt.timestamp_subsec_millis(), 123); + /// + /// let dt = NaiveDate::from_ymd_opt(2015, 7, 1).unwrap().and_hms_nano_opt(8, 59, 59, 1_234_567_890).unwrap(); + /// assert_eq!(dt.timestamp_subsec_millis(), 1_234); + /// ``` + #[inline] + pub fn timestamp_subsec_millis(&self) -> u32 { + self.timestamp_subsec_nanos() / 1_000_000 + } + + /// Returns the number of microseconds since the last whole non-leap second. + /// + /// The return value ranges from 0 to 999,999, + /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999,999. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_nano_opt(9, 10, 11, 123_456_789).unwrap(); + /// assert_eq!(dt.timestamp_subsec_micros(), 123_456); + /// + /// let dt = NaiveDate::from_ymd_opt(2015, 7, 1).unwrap().and_hms_nano_opt(8, 59, 59, 1_234_567_890).unwrap(); + /// assert_eq!(dt.timestamp_subsec_micros(), 1_234_567); + /// ``` + #[inline] + pub fn timestamp_subsec_micros(&self) -> u32 { + self.timestamp_subsec_nanos() / 1_000 + } + + /// Returns the number of nanoseconds since the last whole non-leap second. + /// + /// The return value ranges from 0 to 999,999,999, + /// or for [leap seconds](./struct.NaiveTime.html#leap-second-handling), to 1,999,999,999. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_nano_opt(9, 10, 11, 123_456_789).unwrap(); + /// assert_eq!(dt.timestamp_subsec_nanos(), 123_456_789); + /// + /// let dt = NaiveDate::from_ymd_opt(2015, 7, 1).unwrap().and_hms_nano_opt(8, 59, 59, 1_234_567_890).unwrap(); + /// assert_eq!(dt.timestamp_subsec_nanos(), 1_234_567_890); + /// ``` + #[inline] + pub fn timestamp_subsec_nanos(&self) -> u32 { + self.time.nanosecond() + } + + /// Adds given `Duration` to the current date and time. + /// + /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), + /// the addition assumes that **there is no leap second ever**, + /// except when the `NaiveDateTime` itself represents a leap second + /// in which case the assumption becomes that **there is exactly a single leap second ever**. + /// + /// Returns `None` when it will result in overflow. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDate}; + /// + /// let from_ymd = NaiveDate::from_ymd; + /// + /// let d = from_ymd(2016, 7, 8); + /// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap(); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::zero()), + /// Some(hms(3, 5, 7))); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(1)), + /// Some(hms(3, 5, 8))); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(-1)), + /// Some(hms(3, 5, 6))); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(3600 + 60)), + /// Some(hms(4, 6, 7))); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::seconds(86_400)), + /// Some(from_ymd(2016, 7, 9).and_hms_opt(3, 5, 7).unwrap())); + /// + /// let hmsm = |h, m, s, milli| d.and_hms_milli_opt(h, m, s, milli).unwrap(); + /// assert_eq!(hmsm(3, 5, 7, 980).checked_add_signed(Duration::milliseconds(450)), + /// Some(hmsm(3, 5, 8, 430))); + /// ``` + /// + /// Overflow returns `None`. + /// + /// ``` + /// # use chrono::{Duration, NaiveDate}; + /// # let hms = |h, m, s| NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(h, m, s).unwrap(); + /// assert_eq!(hms(3, 5, 7).checked_add_signed(Duration::days(1_000_000_000)), None); + /// ``` + /// + /// Leap seconds are handled, + /// but the addition assumes that it is the only leap second happened. + /// + /// ``` + /// # use chrono::{Duration, NaiveDate}; + /// # let from_ymd = NaiveDate::from_ymd; + /// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap(); + /// let leap = hmsm(3, 5, 59, 1_300); + /// assert_eq!(leap.checked_add_signed(Duration::zero()), + /// Some(hmsm(3, 5, 59, 1_300))); + /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(-500)), + /// Some(hmsm(3, 5, 59, 800))); + /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(500)), + /// Some(hmsm(3, 5, 59, 1_800))); + /// assert_eq!(leap.checked_add_signed(Duration::milliseconds(800)), + /// Some(hmsm(3, 6, 0, 100))); + /// assert_eq!(leap.checked_add_signed(Duration::seconds(10)), + /// Some(hmsm(3, 6, 9, 300))); + /// assert_eq!(leap.checked_add_signed(Duration::seconds(-10)), + /// Some(hmsm(3, 5, 50, 300))); + /// assert_eq!(leap.checked_add_signed(Duration::days(1)), + /// Some(from_ymd(2016, 7, 9).and_hms_milli_opt(3, 5, 59, 300).unwrap())); + /// ``` + pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> { + let (time, rhs) = self.time.overflowing_add_signed(rhs); + + // early checking to avoid overflow in OldDuration::seconds + if rhs <= (-1 << MAX_SECS_BITS) || rhs >= (1 << MAX_SECS_BITS) { + return None; + } + + let date = self.date.checked_add_signed(OldDuration::seconds(rhs))?; + Some(NaiveDateTime { date, time }) + } + + /// Adds given `Months` to the current date and time. + /// + /// Returns `None` when it will result in overflow. + /// + /// Overflow returns `None`. + /// + /// # Example + /// + /// ``` + /// use std::str::FromStr; + /// use chrono::{Months, NaiveDate, NaiveDateTime}; + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + /// .checked_add_months(Months::new(1)), + /// Some(NaiveDate::from_ymd_opt(2014, 2, 1).unwrap().and_hms_opt(1, 0, 0).unwrap()) + /// ); + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + /// .checked_add_months(Months::new(core::i32::MAX as u32 + 1)), + /// None + /// ); + /// ``` + pub fn checked_add_months(self, rhs: Months) -> Option<NaiveDateTime> { + Some(Self { date: self.date.checked_add_months(rhs)?, time: self.time }) + } + + /// Subtracts given `Duration` from the current date and time. + /// + /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), + /// the subtraction assumes that **there is no leap second ever**, + /// except when the `NaiveDateTime` itself represents a leap second + /// in which case the assumption becomes that **there is exactly a single leap second ever**. + /// + /// Returns `None` when it will result in overflow. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDate}; + /// + /// let from_ymd = NaiveDate::from_ymd; + /// + /// let d = from_ymd(2016, 7, 8); + /// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap(); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::zero()), + /// Some(hms(3, 5, 7))); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(1)), + /// Some(hms(3, 5, 6))); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(-1)), + /// Some(hms(3, 5, 8))); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(3600 + 60)), + /// Some(hms(2, 4, 7))); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::seconds(86_400)), + /// Some(from_ymd(2016, 7, 7).and_hms_opt(3, 5, 7).unwrap())); + /// + /// let hmsm = |h, m, s, milli| d.and_hms_milli_opt(h, m, s, milli).unwrap(); + /// assert_eq!(hmsm(3, 5, 7, 450).checked_sub_signed(Duration::milliseconds(670)), + /// Some(hmsm(3, 5, 6, 780))); + /// ``` + /// + /// Overflow returns `None`. + /// + /// ``` + /// # use chrono::{Duration, NaiveDate}; + /// # let hms = |h, m, s| NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_opt(h, m, s).unwrap(); + /// assert_eq!(hms(3, 5, 7).checked_sub_signed(Duration::days(1_000_000_000)), None); + /// ``` + /// + /// Leap seconds are handled, + /// but the subtraction assumes that it is the only leap second happened. + /// + /// ``` + /// # use chrono::{Duration, NaiveDate}; + /// # let from_ymd = NaiveDate::from_ymd; + /// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap(); + /// let leap = hmsm(3, 5, 59, 1_300); + /// assert_eq!(leap.checked_sub_signed(Duration::zero()), + /// Some(hmsm(3, 5, 59, 1_300))); + /// assert_eq!(leap.checked_sub_signed(Duration::milliseconds(200)), + /// Some(hmsm(3, 5, 59, 1_100))); + /// assert_eq!(leap.checked_sub_signed(Duration::milliseconds(500)), + /// Some(hmsm(3, 5, 59, 800))); + /// assert_eq!(leap.checked_sub_signed(Duration::seconds(60)), + /// Some(hmsm(3, 5, 0, 300))); + /// assert_eq!(leap.checked_sub_signed(Duration::days(1)), + /// Some(from_ymd(2016, 7, 7).and_hms_milli_opt(3, 6, 0, 300).unwrap())); + /// ``` + pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> { + let (time, rhs) = self.time.overflowing_sub_signed(rhs); + + // early checking to avoid overflow in OldDuration::seconds + if rhs <= (-1 << MAX_SECS_BITS) || rhs >= (1 << MAX_SECS_BITS) { + return None; + } + + let date = self.date.checked_sub_signed(OldDuration::seconds(rhs))?; + Some(NaiveDateTime { date, time }) + } + + /// Subtracts given `Months` from the current date and time. + /// + /// Returns `None` when it will result in overflow. + /// + /// Overflow returns `None`. + /// + /// # Example + /// + /// ``` + /// use std::str::FromStr; + /// use chrono::{Months, NaiveDate, NaiveDateTime}; + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + /// .checked_sub_months(Months::new(1)), + /// Some(NaiveDate::from_ymd_opt(2013, 12, 1).unwrap().and_hms_opt(1, 0, 0).unwrap()) + /// ); + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + /// .checked_sub_months(Months::new(core::i32::MAX as u32 + 1)), + /// None + /// ); + /// ``` + pub fn checked_sub_months(self, rhs: Months) -> Option<NaiveDateTime> { + Some(Self { date: self.date.checked_sub_months(rhs)?, time: self.time }) + } + + /// Add a duration in [`Days`] to the date part of the `NaiveDateTime` + /// + /// Returns `None` if the resulting date would be out of range. + pub fn checked_add_days(self, days: Days) -> Option<Self> { + Some(Self { date: self.date.checked_add_days(days)?, ..self }) + } + + /// Subtract a duration in [`Days`] from the date part of the `NaiveDateTime` + /// + /// Returns `None` if the resulting date would be out of range. + pub fn checked_sub_days(self, days: Days) -> Option<Self> { + Some(Self { date: self.date.checked_sub_days(days)?, ..self }) + } + + /// Subtracts another `NaiveDateTime` from the current date and time. + /// This does not overflow or underflow at all. + /// + /// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), + /// the subtraction assumes that **there is no leap second ever**, + /// except when any of the `NaiveDateTime`s themselves represents a leap second + /// in which case the assumption becomes that + /// **there are exactly one (or two) leap second(s) ever**. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDate}; + /// + /// let from_ymd = NaiveDate::from_ymd; + /// + /// let d = from_ymd(2016, 7, 8); + /// assert_eq!(d.and_hms_opt(3, 5, 7).unwrap().signed_duration_since(d.and_hms_opt(2, 4, 6).unwrap()), + /// Duration::seconds(3600 + 60 + 1)); + /// + /// // July 8 is 190th day in the year 2016 + /// let d0 = from_ymd(2016, 1, 1); + /// assert_eq!(d.and_hms_milli_opt(0, 7, 6, 500).unwrap().signed_duration_since(d0.and_hms_opt(0, 0, 0).unwrap()), + /// Duration::seconds(189 * 86_400 + 7 * 60 + 6) + Duration::milliseconds(500)); + /// ``` + /// + /// Leap seconds are handled, but the subtraction assumes that + /// there were no other leap seconds happened. + /// + /// ``` + /// # use chrono::{Duration, NaiveDate}; + /// # let from_ymd = NaiveDate::from_ymd; + /// let leap = from_ymd(2015, 6, 30).and_hms_milli_opt(23, 59, 59, 1_500).unwrap(); + /// assert_eq!(leap.signed_duration_since(from_ymd(2015, 6, 30).and_hms_opt(23, 0, 0).unwrap()), + /// Duration::seconds(3600) + Duration::milliseconds(500)); + /// assert_eq!(from_ymd(2015, 7, 1).and_hms_opt(1, 0, 0).unwrap().signed_duration_since(leap), + /// Duration::seconds(3600) - Duration::milliseconds(500)); + /// ``` + pub fn signed_duration_since(self, rhs: NaiveDateTime) -> OldDuration { + self.date.signed_duration_since(rhs.date) + self.time.signed_duration_since(rhs.time) + } + + /// Formats the combined date and time with the specified formatting items. + /// Otherwise it is the same as the ordinary [`format`](#method.format) method. + /// + /// The `Iterator` of items should be `Clone`able, + /// since the resulting `DelayedFormat` value may be formatted multiple times. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// use chrono::format::strftime::StrftimeItems; + /// + /// let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S"); + /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); + /// assert_eq!(dt.format_with_items(fmt.clone()).to_string(), "2015-09-05 23:56:04"); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); + /// ``` + /// + /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// + /// ``` + /// # use chrono::NaiveDate; + /// # use chrono::format::strftime::StrftimeItems; + /// # let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S").clone(); + /// # let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); + /// assert_eq!(format!("{}", dt.format_with_items(fmt)), "2015-09-05 23:56:04"); + /// ``` + #[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 + I: Iterator<Item = B> + Clone, + B: Borrow<Item<'a>>, + { + DelayedFormat::new(Some(self.date), Some(self.time), items) + } + + /// Formats the combined date and time with the specified format string. + /// See the [`format::strftime` module](../format/strftime/index.html) + /// on the supported escape sequences. + /// + /// This returns a `DelayedFormat`, + /// which gets converted to a string only when actual formatting happens. + /// You may use the `to_string` method to get a `String`, + /// or just feed it into `print!` and other formatting macros. + /// (In this way it avoids the redundant memory allocation.) + /// + /// A wrong format string does *not* issue an error immediately. + /// Rather, converting or formatting the `DelayedFormat` fails. + /// You are recommended to immediately use `DelayedFormat` for this reason. + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); + /// assert_eq!(dt.format("around %l %p on %b %-d").to_string(), "around 11 PM on Sep 5"); + /// ``` + /// + /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// + /// ``` + /// # use chrono::NaiveDate; + /// # let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); + /// assert_eq!(format!("{}", dt.format("%Y-%m-%d %H:%M:%S")), "2015-09-05 23:56:04"); + /// assert_eq!(format!("{}", dt.format("around %l %p on %b %-d")), "around 11 PM on Sep 5"); + /// ``` + #[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)) + } + + /// Converts the `NaiveDateTime` into the timezone-aware `DateTime<Tz>` + /// with the provided timezone, if possible. + /// + /// This can fail in cases where the local time represented by the `NaiveDateTime` + /// is not a valid local timestamp in the target timezone due to an offset transition + /// for example if the target timezone had a change from +00:00 to +01:00 + /// occuring at 2015-09-05 22:59:59, then a local time of 2015-09-05 23:56:04 + /// could never occur. Similarly, if the offset transitioned in the opposite direction + /// then there would be two local times of 2015-09-05 23:56:04, one at +00:00 and one + /// at +01:00. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, Utc}; + /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap().and_local_timezone(Utc).unwrap(); + /// assert_eq!(dt.timezone(), Utc); + pub fn and_local_timezone<Tz: TimeZone>(&self, tz: Tz) -> LocalResult<DateTime<Tz>> { + tz.from_local_datetime(self) + } + + /// The minimum possible `NaiveDateTime`. + pub const MIN: Self = Self { date: NaiveDate::MIN, time: NaiveTime::MIN }; + /// The maximum possible `NaiveDateTime`. + pub const MAX: Self = Self { date: NaiveDate::MAX, time: NaiveTime::MAX }; + + /// Creates a new [NaiveDateTime] from milliseconds or microseconds since the UNIX epoch. + /// + /// This is a private function used by [from_timestamp_millis] and [from_timestamp_micros]. + #[inline] + fn from_timestamp_unit(value: i64, unit: TimestampUnit) -> Option<NaiveDateTime> { + let (secs, subsecs) = + (value / i64::from(unit.per_second()), value % i64::from(unit.per_second())); + + match subsecs.cmp(&0) { + Ordering::Less => { + // in the case where our subsec part is negative, then we are actually in the earlier second + // hence we subtract one from the seconds part, and we then add a whole second worth of nanos + // to our nanos part. Due to the use of u32 datatype, it is more convenient to subtract + // the absolute value of the subsec nanos from a whole second worth of nanos + let nsecs = u32::try_from(subsecs.abs()).ok()? * unit.nanos_per(); + NaiveDateTime::from_timestamp_opt( + secs.checked_sub(1)?, + NANOS_IN_SECOND.checked_sub(nsecs)?, + ) + } + Ordering::Equal => NaiveDateTime::from_timestamp_opt(secs, 0), + Ordering::Greater => { + // convert the subsec millis into nanosecond scale so they can be supplied + // as the nanoseconds parameter + let nsecs = u32::try_from(subsecs).ok()? * unit.nanos_per(); + NaiveDateTime::from_timestamp_opt(secs, nsecs) + } + } + } +} + +impl Datelike for NaiveDateTime { + /// Returns the year number in the [calendar date](./index.html#calendar-date). + /// + /// See also the [`NaiveDate::year`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.year(), 2015); + /// ``` + #[inline] + fn year(&self) -> i32 { + self.date.year() + } + + /// Returns the month number starting from 1. + /// + /// The return value ranges from 1 to 12. + /// + /// See also the [`NaiveDate::month`](./struct.NaiveDate.html#method.month) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.month(), 9); + /// ``` + #[inline] + fn month(&self) -> u32 { + self.date.month() + } + + /// Returns the month number starting from 0. + /// + /// The return value ranges from 0 to 11. + /// + /// See also the [`NaiveDate::month0`](./struct.NaiveDate.html#method.month0) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.month0(), 8); + /// ``` + #[inline] + fn month0(&self) -> u32 { + self.date.month0() + } + + /// Returns the day of month starting from 1. + /// + /// The return value ranges from 1 to 31. (The last day of month differs by months.) + /// + /// See also the [`NaiveDate::day`](./struct.NaiveDate.html#method.day) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.day(), 25); + /// ``` + #[inline] + fn day(&self) -> u32 { + self.date.day() + } + + /// Returns the day of month starting from 0. + /// + /// The return value ranges from 0 to 30. (The last day of month differs by months.) + /// + /// See also the [`NaiveDate::day0`](./struct.NaiveDate.html#method.day0) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.day0(), 24); + /// ``` + #[inline] + fn day0(&self) -> u32 { + self.date.day0() + } + + /// Returns the day of year starting from 1. + /// + /// The return value ranges from 1 to 366. (The last day of year differs by years.) + /// + /// See also the [`NaiveDate::ordinal`](./struct.NaiveDate.html#method.ordinal) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.ordinal(), 268); + /// ``` + #[inline] + fn ordinal(&self) -> u32 { + self.date.ordinal() + } + + /// Returns the day of year starting from 0. + /// + /// The return value ranges from 0 to 365. (The last day of year differs by years.) + /// + /// See also the [`NaiveDate::ordinal0`](./struct.NaiveDate.html#method.ordinal0) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.ordinal0(), 267); + /// ``` + #[inline] + fn ordinal0(&self) -> u32 { + self.date.ordinal0() + } + + /// Returns the day of week. + /// + /// See also the [`NaiveDate::weekday`](./struct.NaiveDate.html#method.weekday) method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Weekday}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.weekday(), Weekday::Fri); + /// ``` + #[inline] + fn weekday(&self) -> Weekday { + self.date.weekday() + } + + #[inline] + fn iso_week(&self) -> IsoWeek { + self.date.iso_week() + } + + /// Makes a new `NaiveDateTime` with the year number changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_year`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_year(2016), Some(NaiveDate::from_ymd_opt(2016, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_year(-308), Some(NaiveDate::from_ymd_opt(-308, 9, 25).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// ``` + #[inline] + fn with_year(&self, year: i32) -> Option<NaiveDateTime> { + self.date.with_year(year).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the month number (starting from 1) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_month`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_month(10), Some(NaiveDate::from_ymd_opt(2015, 10, 30).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_month(13), None); // no month 13 + /// assert_eq!(dt.with_month(2), None); // no February 30 + /// ``` + #[inline] + fn with_month(&self, month: u32) -> Option<NaiveDateTime> { + self.date.with_month(month).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the month number (starting from 0) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_month0`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_month0(9), Some(NaiveDate::from_ymd_opt(2015, 10, 30).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_month0(12), None); // no month 13 + /// assert_eq!(dt.with_month0(1), None); // no February 30 + /// ``` + #[inline] + fn with_month0(&self, month0: u32) -> Option<NaiveDateTime> { + self.date.with_month0(month0).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the day of month (starting from 1) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_day`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_day(30), Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_day(31), None); // no September 31 + /// ``` + #[inline] + fn with_day(&self, day: u32) -> Option<NaiveDateTime> { + self.date.with_day(day).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the day of month (starting from 0) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_day0`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_day0(29), Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_day0(30), None); // no September 31 + /// ``` + #[inline] + fn with_day0(&self, day0: u32) -> Option<NaiveDateTime> { + self.date.with_day0(day0).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the day of year (starting from 1) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_ordinal`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_ordinal(60), + /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_ordinal(366), None); // 2015 had only 365 days + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2016, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_ordinal(60), + /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_ordinal(366), + /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// ``` + #[inline] + fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDateTime> { + self.date.with_ordinal(ordinal).map(|d| NaiveDateTime { date: d, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the day of year (starting from 0) changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveDate::with_ordinal0`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Datelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_ordinal0(59), + /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_ordinal0(365), None); // 2015 had only 365 days + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2016, 9, 8).unwrap().and_hms_opt(12, 34, 56).unwrap(); + /// assert_eq!(dt.with_ordinal0(59), + /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// assert_eq!(dt.with_ordinal0(365), + /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap().and_hms_opt(12, 34, 56).unwrap())); + /// ``` + #[inline] + fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDateTime> { + self.date.with_ordinal0(ordinal0).map(|d| NaiveDateTime { date: d, ..*self }) + } +} + +impl Timelike for NaiveDateTime { + /// Returns the hour number from 0 to 23. + /// + /// See also the [`NaiveTime::hour`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.hour(), 12); + /// ``` + #[inline] + fn hour(&self) -> u32 { + self.time.hour() + } + + /// Returns the minute number from 0 to 59. + /// + /// See also the [`NaiveTime::minute`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.minute(), 34); + /// ``` + #[inline] + fn minute(&self) -> u32 { + self.time.minute() + } + + /// Returns the second number from 0 to 59. + /// + /// See also the [`NaiveTime::second`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.second(), 56); + /// ``` + #[inline] + fn second(&self) -> u32 { + self.time.second() + } + + /// Returns the number of nanoseconds since the whole non-leap second. + /// The range from 1,000,000,000 to 1,999,999,999 represents + /// the [leap second](./struct.NaiveTime.html#leap-second-handling). + /// + /// See also the [`NaiveTime::nanosecond`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.nanosecond(), 789_000_000); + /// ``` + #[inline] + fn nanosecond(&self) -> u32 { + self.time.nanosecond() + } + + /// Makes a new `NaiveDateTime` with the hour number changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the [`NaiveTime::with_hour`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.with_hour(7), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(7, 34, 56, 789).unwrap())); + /// assert_eq!(dt.with_hour(24), None); + /// ``` + #[inline] + fn with_hour(&self, hour: u32) -> Option<NaiveDateTime> { + self.time.with_hour(hour).map(|t| NaiveDateTime { time: t, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the minute number changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// + /// See also the + /// [`NaiveTime::with_minute`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.with_minute(45), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 45, 56, 789).unwrap())); + /// assert_eq!(dt.with_minute(60), None); + /// ``` + #[inline] + fn with_minute(&self, min: u32) -> Option<NaiveDateTime> { + self.time.with_minute(min).map(|t| NaiveDateTime { time: t, ..*self }) + } + + /// Makes a new `NaiveDateTime` with the second number changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. As + /// with the [`NaiveDateTime::second`] method, the input range is + /// restricted to 0 through 59. + /// + /// See also the [`NaiveTime::with_second`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.with_second(17), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 17, 789).unwrap())); + /// assert_eq!(dt.with_second(60), None); + /// ``` + #[inline] + fn with_second(&self, sec: u32) -> Option<NaiveDateTime> { + self.time.with_second(sec).map(|t| NaiveDateTime { time: t, ..*self }) + } + + /// Makes a new `NaiveDateTime` with nanoseconds since the whole non-leap second changed. + /// + /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// As with the [`NaiveDateTime::nanosecond`] method, + /// the input range can exceed 1,000,000,000 for leap seconds. + /// + /// See also the [`NaiveTime::with_nanosecond`] method. + /// + /// # Example + /// + /// ``` + /// use chrono::{NaiveDate, NaiveDateTime, Timelike}; + /// + /// let dt: NaiveDateTime = NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_milli_opt(12, 34, 56, 789).unwrap(); + /// assert_eq!(dt.with_nanosecond(333_333_333), + /// Some(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_nano_opt(12, 34, 56, 333_333_333).unwrap())); + /// assert_eq!(dt.with_nanosecond(1_333_333_333), // leap second + /// Some(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().and_hms_nano_opt(12, 34, 56, 1_333_333_333).unwrap())); + /// assert_eq!(dt.with_nanosecond(2_000_000_000), None); + /// ``` + #[inline] + fn with_nanosecond(&self, nano: u32) -> Option<NaiveDateTime> { + self.time.with_nanosecond(nano).map(|t| NaiveDateTime { time: t, ..*self }) + } +} + +/// An addition of `Duration` to `NaiveDateTime` yields another `NaiveDateTime`. +/// +/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), +/// the addition assumes that **there is no leap second ever**, +/// except when the `NaiveDateTime` itself represents a leap second +/// in which case the assumption becomes that **there is exactly a single leap second ever**. +/// +/// Panics on underflow or overflow. Use [`NaiveDateTime::checked_add_signed`] +/// to detect that. +/// +/// # Example +/// +/// ``` +/// use chrono::{Duration, NaiveDate}; +/// +/// let from_ymd = NaiveDate::from_ymd; +/// +/// let d = from_ymd(2016, 7, 8); +/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap(); +/// assert_eq!(hms(3, 5, 7) + Duration::zero(), hms(3, 5, 7)); +/// assert_eq!(hms(3, 5, 7) + Duration::seconds(1), hms(3, 5, 8)); +/// assert_eq!(hms(3, 5, 7) + Duration::seconds(-1), hms(3, 5, 6)); +/// assert_eq!(hms(3, 5, 7) + Duration::seconds(3600 + 60), hms(4, 6, 7)); +/// assert_eq!(hms(3, 5, 7) + Duration::seconds(86_400), +/// from_ymd(2016, 7, 9).and_hms_opt(3, 5, 7).unwrap()); +/// assert_eq!(hms(3, 5, 7) + Duration::days(365), +/// from_ymd(2017, 7, 8).and_hms_opt(3, 5, 7).unwrap()); +/// +/// let hmsm = |h, m, s, milli| d.and_hms_milli_opt(h, m, s, milli).unwrap(); +/// assert_eq!(hmsm(3, 5, 7, 980) + Duration::milliseconds(450), hmsm(3, 5, 8, 430)); +/// ``` +/// +/// Leap seconds are handled, +/// but the addition assumes that it is the only leap second happened. +/// +/// ``` +/// # use chrono::{Duration, NaiveDate}; +/// # let from_ymd = NaiveDate::from_ymd; +/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap(); +/// let leap = hmsm(3, 5, 59, 1_300); +/// assert_eq!(leap + Duration::zero(), hmsm(3, 5, 59, 1_300)); +/// assert_eq!(leap + Duration::milliseconds(-500), hmsm(3, 5, 59, 800)); +/// assert_eq!(leap + Duration::milliseconds(500), hmsm(3, 5, 59, 1_800)); +/// assert_eq!(leap + Duration::milliseconds(800), hmsm(3, 6, 0, 100)); +/// assert_eq!(leap + Duration::seconds(10), hmsm(3, 6, 9, 300)); +/// assert_eq!(leap + Duration::seconds(-10), hmsm(3, 5, 50, 300)); +/// assert_eq!(leap + Duration::days(1), +/// from_ymd(2016, 7, 9).and_hms_milli_opt(3, 5, 59, 300).unwrap()); +/// ``` +impl Add<OldDuration> for NaiveDateTime { + type Output = NaiveDateTime; + + #[inline] + fn add(self, rhs: OldDuration) -> NaiveDateTime { + self.checked_add_signed(rhs).expect("`NaiveDateTime + Duration` overflowed") + } +} + +impl AddAssign<OldDuration> for NaiveDateTime { + #[inline] + fn add_assign(&mut self, rhs: OldDuration) { + *self = self.add(rhs); + } +} + +impl Add<Months> for NaiveDateTime { + type Output = NaiveDateTime; + + /// An addition of months to `NaiveDateTime` clamped to valid days in resulting month. + /// + /// # Panics + /// + /// Panics if the resulting date would be out of range. + /// + /// # Example + /// + /// ``` + /// use chrono::{Duration, NaiveDateTime, Months, NaiveDate}; + /// use std::str::FromStr; + /// + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + Months::new(1), + /// NaiveDate::from_ymd_opt(2014, 2, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(0, 2, 0).unwrap() + Months::new(11), + /// NaiveDate::from_ymd_opt(2014, 12, 1).unwrap().and_hms_opt(0, 2, 0).unwrap() + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(0, 0, 3).unwrap() + Months::new(12), + /// NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().and_hms_opt(0, 0, 3).unwrap() + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(0, 0, 4).unwrap() + Months::new(13), + /// NaiveDate::from_ymd_opt(2015, 2, 1).unwrap().and_hms_opt(0, 0, 4).unwrap() + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2014, 1, 31).unwrap().and_hms_opt(0, 5, 0).unwrap() + Months::new(1), + /// NaiveDate::from_ymd_opt(2014, 2, 28).unwrap().and_hms_opt(0, 5, 0).unwrap() + /// ); + /// assert_eq!( + /// NaiveDate::from_ymd_opt(2020, 1, 31).unwrap().and_hms_opt(6, 0, 0).unwrap() + Months::new(1), + /// NaiveDate::from_ymd_opt(2020, 2, 29).unwrap().and_hms_opt(6, 0, 0).unwrap() + /// ); + /// ``` + fn add(self, rhs: Months) -> Self::Output { + Self { date: self.date.checked_add_months(rhs).unwrap(), time: self.time } + } +} + +/// A subtraction of `Duration` from `NaiveDateTime` yields another `NaiveDateTime`. +/// It is the same as the addition with a negated `Duration`. +/// +/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), +/// the addition assumes that **there is no leap second ever**, +/// except when the `NaiveDateTime` itself represents a leap second +/// in which case the assumption becomes that **there is exactly a single leap second ever**. +/// +/// Panics on underflow or overflow. Use [`NaiveDateTime::checked_sub_signed`] +/// to detect that. +/// +/// # Example +/// +/// ``` +/// use chrono::{Duration, NaiveDate}; +/// +/// let from_ymd = NaiveDate::from_ymd; +/// +/// let d = from_ymd(2016, 7, 8); +/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap(); +/// assert_eq!(hms(3, 5, 7) - Duration::zero(), hms(3, 5, 7)); +/// assert_eq!(hms(3, 5, 7) - Duration::seconds(1), hms(3, 5, 6)); +/// assert_eq!(hms(3, 5, 7) - Duration::seconds(-1), hms(3, 5, 8)); +/// assert_eq!(hms(3, 5, 7) - Duration::seconds(3600 + 60), hms(2, 4, 7)); +/// assert_eq!(hms(3, 5, 7) - Duration::seconds(86_400), +/// from_ymd(2016, 7, 7).and_hms_opt(3, 5, 7).unwrap()); +/// assert_eq!(hms(3, 5, 7) - Duration::days(365), +/// from_ymd(2015, 7, 9).and_hms_opt(3, 5, 7).unwrap()); +/// +/// let hmsm = |h, m, s, milli| d.and_hms_milli_opt(h, m, s, milli).unwrap(); +/// assert_eq!(hmsm(3, 5, 7, 450) - Duration::milliseconds(670), hmsm(3, 5, 6, 780)); +/// ``` +/// +/// Leap seconds are handled, +/// but the subtraction assumes that it is the only leap second happened. +/// +/// ``` +/// # use chrono::{Duration, NaiveDate}; +/// # let from_ymd = NaiveDate::from_ymd; +/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap(); +/// let leap = hmsm(3, 5, 59, 1_300); +/// assert_eq!(leap - Duration::zero(), hmsm(3, 5, 59, 1_300)); +/// assert_eq!(leap - Duration::milliseconds(200), hmsm(3, 5, 59, 1_100)); +/// assert_eq!(leap - Duration::milliseconds(500), hmsm(3, 5, 59, 800)); +/// assert_eq!(leap - Duration::seconds(60), hmsm(3, 5, 0, 300)); +/// assert_eq!(leap - Duration::days(1), +/// from_ymd(2016, 7, 7).and_hms_milli_opt(3, 6, 0, 300).unwrap()); +/// ``` +impl Sub<OldDuration> for NaiveDateTime { + type Output = NaiveDateTime; + + #[inline] + fn sub(self, rhs: OldDuration) -> NaiveDateTime { + self.checked_sub_signed(rhs).expect("`NaiveDateTime - Duration` overflowed") + } +} + +impl SubAssign<OldDuration> for NaiveDateTime { + #[inline] + fn sub_assign(&mut self, rhs: OldDuration) { + *self = self.sub(rhs); + } +} + +/// A subtraction of Months from `NaiveDateTime` clamped to valid days in resulting month. +/// +/// # Panics +/// +/// Panics if the resulting date would be out of range. +/// +/// # Example +/// +/// ``` +/// use chrono::{Duration, NaiveDateTime, Months, NaiveDate}; +/// use std::str::FromStr; +/// +/// assert_eq!( +/// NaiveDate::from_ymd_opt(2014, 01, 01).unwrap().and_hms_opt(01, 00, 00).unwrap() - Months::new(11), +/// NaiveDate::from_ymd_opt(2013, 02, 01).unwrap().and_hms_opt(01, 00, 00).unwrap() +/// ); +/// assert_eq!( +/// NaiveDate::from_ymd_opt(2014, 01, 01).unwrap().and_hms_opt(00, 02, 00).unwrap() - Months::new(12), +/// NaiveDate::from_ymd_opt(2013, 01, 01).unwrap().and_hms_opt(00, 02, 00).unwrap() +/// ); +/// assert_eq!( +/// NaiveDate::from_ymd_opt(2014, 01, 01).unwrap().and_hms_opt(00, 00, 03).unwrap() - Months::new(13), +/// NaiveDate::from_ymd_opt(2012, 12, 01).unwrap().and_hms_opt(00, 00, 03).unwrap() +/// ); +/// ``` +impl Sub<Months> for NaiveDateTime { + type Output = NaiveDateTime; + + fn sub(self, rhs: Months) -> Self::Output { + Self { date: self.date.checked_sub_months(rhs).unwrap(), time: self.time } + } +} + +/// Subtracts another `NaiveDateTime` from the current date and time. +/// This does not overflow or underflow at all. +/// +/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling), +/// the subtraction assumes that **there is no leap second ever**, +/// except when any of the `NaiveDateTime`s themselves represents a leap second +/// in which case the assumption becomes that +/// **there are exactly one (or two) leap second(s) ever**. +/// +/// The implementation is a wrapper around [`NaiveDateTime::signed_duration_since`]. +/// +/// # Example +/// +/// ``` +/// use chrono::{Duration, NaiveDate}; +/// +/// let from_ymd = NaiveDate::from_ymd; +/// +/// let d = from_ymd(2016, 7, 8); +/// assert_eq!(d.and_hms_opt(3, 5, 7).unwrap() - d.and_hms_opt(2, 4, 6).unwrap(), Duration::seconds(3600 + 60 + 1)); +/// +/// // July 8 is 190th day in the year 2016 +/// let d0 = from_ymd(2016, 1, 1); +/// assert_eq!(d.and_hms_milli_opt(0, 7, 6, 500).unwrap() - d0.and_hms_opt(0, 0, 0).unwrap(), +/// Duration::seconds(189 * 86_400 + 7 * 60 + 6) + Duration::milliseconds(500)); +/// ``` +/// +/// Leap seconds are handled, but the subtraction assumes that no other leap +/// seconds happened. +/// +/// ``` +/// # use chrono::{Duration, NaiveDate}; +/// # let from_ymd = NaiveDate::from_ymd; +/// let leap = from_ymd(2015, 6, 30).and_hms_milli_opt(23, 59, 59, 1_500).unwrap(); +/// assert_eq!(leap - from_ymd(2015, 6, 30).and_hms_opt(23, 0, 0).unwrap(), +/// Duration::seconds(3600) + Duration::milliseconds(500)); +/// assert_eq!(from_ymd(2015, 7, 1).and_hms_opt(1, 0, 0).unwrap() - leap, +/// Duration::seconds(3600) - Duration::milliseconds(500)); +/// ``` +impl Sub<NaiveDateTime> for NaiveDateTime { + type Output = OldDuration; + + #[inline] + fn sub(self, rhs: NaiveDateTime) -> OldDuration { + self.signed_duration_since(rhs) + } +} + +impl Add<Days> for NaiveDateTime { + type Output = NaiveDateTime; + + fn add(self, days: Days) -> Self::Output { + self.checked_add_days(days).unwrap() + } +} + +impl Sub<Days> for NaiveDateTime { + type Output = NaiveDateTime; + + fn sub(self, days: Days) -> Self::Output { + self.checked_sub_days(days).unwrap() + } +} + +/// The `Debug` output of the naive date and time `dt` is the same as +/// [`dt.format("%Y-%m-%dT%H:%M:%S%.f")`](crate::format::strftime). +/// +/// The string printed can be readily parsed via the `parse` method on `str`. +/// +/// It should be noted that, for leap seconds not on the minute boundary, +/// it may print a representation not distinguishable from non-leap seconds. +/// This doesn't matter in practice, since such leap seconds never happened. +/// (By the time of the first leap second on 1972-06-30, +/// every time zone offset around the world has standardized to the 5-minute alignment.) +/// +/// # Example +/// +/// ``` +/// use chrono::NaiveDate; +/// +/// let dt = NaiveDate::from_ymd_opt(2016, 11, 15).unwrap().and_hms_opt(7, 39, 24).unwrap(); +/// assert_eq!(format!("{:?}", dt), "2016-11-15T07:39:24"); +/// ``` +/// +/// Leap seconds may also be used. +/// +/// ``` +/// # use chrono::NaiveDate; +/// let dt = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_milli_opt(23, 59, 59, 1_500).unwrap(); +/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60.500"); +/// ``` +impl fmt::Debug for NaiveDateTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.date.fmt(f)?; + f.write_char('T')?; + self.time.fmt(f) + } +} + +/// The `Display` output of the naive date and time `dt` is the same as +/// [`dt.format("%Y-%m-%d %H:%M:%S%.f")`](crate::format::strftime). +/// +/// It should be noted that, for leap seconds not on the minute boundary, +/// it may print a representation not distinguishable from non-leap seconds. +/// This doesn't matter in practice, since such leap seconds never happened. +/// (By the time of the first leap second on 1972-06-30, +/// every time zone offset around the world has standardized to the 5-minute alignment.) +/// +/// # Example +/// +/// ``` +/// use chrono::NaiveDate; +/// +/// let dt = NaiveDate::from_ymd_opt(2016, 11, 15).unwrap().and_hms_opt(7, 39, 24).unwrap(); +/// assert_eq!(format!("{}", dt), "2016-11-15 07:39:24"); +/// ``` +/// +/// Leap seconds may also be used. +/// +/// ``` +/// # use chrono::NaiveDate; +/// let dt = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_milli_opt(23, 59, 59, 1_500).unwrap(); +/// assert_eq!(format!("{}", dt), "2015-06-30 23:59:60.500"); +/// ``` +impl fmt::Display for NaiveDateTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.date.fmt(f)?; + f.write_char(' ')?; + self.time.fmt(f) + } +} + +/// Parsing a `str` into a `NaiveDateTime` uses the same format, +/// [`%Y-%m-%dT%H:%M:%S%.f`](crate::format::strftime), as in `Debug`. +/// +/// # Example +/// +/// ``` +/// use chrono::{NaiveDateTime, NaiveDate}; +/// +/// let dt = NaiveDate::from_ymd_opt(2015, 9, 18).unwrap().and_hms_opt(23, 56, 4).unwrap(); +/// assert_eq!("2015-09-18T23:56:04".parse::<NaiveDateTime>(), Ok(dt)); +/// +/// let dt = NaiveDate::from_ymd_opt(12345, 6, 7).unwrap().and_hms_milli_opt(7, 59, 59, 1_500).unwrap(); // leap second +/// assert_eq!("+12345-6-7T7:59:60.5".parse::<NaiveDateTime>(), Ok(dt)); +/// +/// assert!("foo".parse::<NaiveDateTime>().is_err()); +/// ``` +impl str::FromStr for NaiveDateTime { + type Err = ParseError; + + fn from_str(s: &str) -> ParseResult<NaiveDateTime> { + const ITEMS: &[Item<'static>] = &[ + Item::Numeric(Numeric::Year, Pad::Zero), + Item::Space(""), + Item::Literal("-"), + Item::Numeric(Numeric::Month, Pad::Zero), + Item::Space(""), + Item::Literal("-"), + Item::Numeric(Numeric::Day, Pad::Zero), + Item::Space(""), + Item::Literal("T"), // XXX shouldn't this be case-insensitive? + Item::Numeric(Numeric::Hour, Pad::Zero), + Item::Space(""), + Item::Literal(":"), + Item::Numeric(Numeric::Minute, Pad::Zero), + Item::Space(""), + Item::Literal(":"), + Item::Numeric(Numeric::Second, Pad::Zero), + Item::Fixed(Fixed::Nanosecond), + Item::Space(""), + ]; + + let mut parsed = Parsed::new(); + parse(&mut parsed, s, ITEMS.iter())?; + parsed.to_naive_datetime_with_offset(0) + } +} + +/// The default value for a NaiveDateTime is one with epoch 0 +/// that is, 1st of January 1970 at 00:00:00. +/// +/// # Example +/// +/// ```rust +/// use chrono::NaiveDateTime; +/// +/// let default_date = NaiveDateTime::default(); +/// assert_eq!(default_date, NaiveDateTime::from_timestamp(0, 0)); +/// ``` +impl Default for NaiveDateTime { + fn default() -> Self { + NaiveDateTime::from_timestamp_opt(0, 0).unwrap() + } +} + +#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] +fn test_encodable_json<F, E>(to_string: F) +where + F: Fn(&NaiveDateTime) -> Result<String, E>, + E: ::std::fmt::Debug, +{ + assert_eq!( + to_string( + &NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_milli_opt(9, 10, 48, 90).unwrap() + ) + .ok(), + Some(r#""2016-07-08T09:10:48.090""#.into()) + ); + assert_eq!( + to_string(&NaiveDate::from_ymd_opt(2014, 7, 24).unwrap().and_hms_opt(12, 34, 6).unwrap()) + .ok(), + Some(r#""2014-07-24T12:34:06""#.into()) + ); + assert_eq!( + to_string( + &NaiveDate::from_ymd_opt(0, 1, 1).unwrap().and_hms_milli_opt(0, 0, 59, 1_000).unwrap() + ) + .ok(), + Some(r#""0000-01-01T00:00:60""#.into()) + ); + assert_eq!( + to_string( + &NaiveDate::from_ymd_opt(-1, 12, 31).unwrap().and_hms_nano_opt(23, 59, 59, 7).unwrap() + ) + .ok(), + Some(r#""-0001-12-31T23:59:59.000000007""#.into()) + ); + assert_eq!( + to_string(&NaiveDate::MIN.and_hms_opt(0, 0, 0).unwrap()).ok(), + Some(r#""-262144-01-01T00:00:00""#.into()) + ); + assert_eq!( + to_string(&NaiveDate::MAX.and_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()).ok(), + Some(r#""+262143-12-31T23:59:60.999999999""#.into()) + ); +} + +#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] +fn test_decodable_json<F, E>(from_str: F) +where + F: Fn(&str) -> Result<NaiveDateTime, E>, + E: ::std::fmt::Debug, +{ + assert_eq!( + from_str(r#""2016-07-08T09:10:48.090""#).ok(), + Some( + NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_milli_opt(9, 10, 48, 90).unwrap() + ) + ); + assert_eq!( + from_str(r#""2016-7-8T9:10:48.09""#).ok(), + Some( + NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_milli_opt(9, 10, 48, 90).unwrap() + ) + ); + assert_eq!( + from_str(r#""2014-07-24T12:34:06""#).ok(), + Some(NaiveDate::from_ymd_opt(2014, 7, 24).unwrap().and_hms_opt(12, 34, 6).unwrap()) + ); + assert_eq!( + from_str(r#""0000-01-01T00:00:60""#).ok(), + Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap().and_hms_milli_opt(0, 0, 59, 1_000).unwrap()) + ); + assert_eq!( + from_str(r#""0-1-1T0:0:60""#).ok(), + Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap().and_hms_milli_opt(0, 0, 59, 1_000).unwrap()) + ); + assert_eq!( + from_str(r#""-0001-12-31T23:59:59.000000007""#).ok(), + Some(NaiveDate::from_ymd_opt(-1, 12, 31).unwrap().and_hms_nano_opt(23, 59, 59, 7).unwrap()) + ); + assert_eq!( + from_str(r#""-262144-01-01T00:00:00""#).ok(), + Some(NaiveDate::MIN.and_hms_opt(0, 0, 0).unwrap()) + ); + assert_eq!( + from_str(r#""+262143-12-31T23:59:60.999999999""#).ok(), + Some(NaiveDate::MAX.and_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) + ); + assert_eq!( + from_str(r#""+262143-12-31T23:59:60.9999999999997""#).ok(), // excess digits are ignored + Some(NaiveDate::MAX.and_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) + ); + + // bad formats + assert!(from_str(r#""""#).is_err()); + assert!(from_str(r#""2016-07-08""#).is_err()); + assert!(from_str(r#""09:10:48.090""#).is_err()); + assert!(from_str(r#""20160708T091048.090""#).is_err()); + assert!(from_str(r#""2000-00-00T00:00:00""#).is_err()); + assert!(from_str(r#""2000-02-30T00:00:00""#).is_err()); + assert!(from_str(r#""2001-02-29T00:00:00""#).is_err()); + assert!(from_str(r#""2002-02-28T24:00:00""#).is_err()); + assert!(from_str(r#""2002-02-28T23:60:00""#).is_err()); + assert!(from_str(r#""2002-02-28T23:59:61""#).is_err()); + assert!(from_str(r#""2016-07-08T09:10:48,090""#).is_err()); + assert!(from_str(r#""2016-07-08 09:10:48.090""#).is_err()); + assert!(from_str(r#""2016-007-08T09:10:48.090""#).is_err()); + assert!(from_str(r#""yyyy-mm-ddThh:mm:ss.fffffffff""#).is_err()); + assert!(from_str(r#"20160708000000"#).is_err()); + assert!(from_str(r#"{}"#).is_err()); + // pre-0.3.0 rustc-serialize format is now invalid + assert!(from_str(r#"{"date":{"ymdf":20},"time":{"secs":0,"frac":0}}"#).is_err()); + assert!(from_str(r#"null"#).is_err()); +} + +#[cfg(all(test, feature = "rustc-serialize"))] +fn test_decodable_json_timestamp<F, E>(from_str: F) +where + F: Fn(&str) -> Result<rustc_serialize::TsSeconds, E>, + E: ::std::fmt::Debug, +{ + assert_eq!( + *from_str("0").unwrap(), + NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap(), + "should parse integers as timestamps" + ); + assert_eq!( + *from_str("-1").unwrap(), + NaiveDate::from_ymd_opt(1969, 12, 31).unwrap().and_hms_opt(23, 59, 59).unwrap(), + "should parse integers as timestamps" + ); +} diff --git a/vendor/chrono/src/naive/datetime/rustc_serialize.rs b/vendor/chrono/src/naive/datetime/rustc_serialize.rs new file mode 100644 index 000000000..6e33829e0 --- /dev/null +++ b/vendor/chrono/src/naive/datetime/rustc_serialize.rs @@ -0,0 +1,73 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))] + +use super::NaiveDateTime; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::ops::Deref; + +impl Encodable for NaiveDateTime { + fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + format!("{:?}", self).encode(s) + } +} + +impl Decodable for NaiveDateTime { + fn decode<D: Decoder>(d: &mut D) -> Result<NaiveDateTime, D::Error> { + d.read_str()?.parse().map_err(|_| d.error("invalid date time string")) + } +} + +/// A `DateTime` that can be deserialized from a seconds-based timestamp +#[derive(Debug)] +#[deprecated( + since = "1.4.2", + note = "RustcSerialize will be removed before chrono 1.0, use Serde instead" +)] +pub struct TsSeconds(NaiveDateTime); + +#[allow(deprecated)] +impl From<TsSeconds> for NaiveDateTime { + /// Pull the internal NaiveDateTime out + #[allow(deprecated)] + fn from(obj: TsSeconds) -> NaiveDateTime { + obj.0 + } +} + +#[allow(deprecated)] +impl Deref for TsSeconds { + type Target = NaiveDateTime; + + #[allow(deprecated)] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[allow(deprecated)] +impl Decodable for TsSeconds { + #[allow(deprecated)] + fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds, D::Error> { + Ok(TsSeconds( + NaiveDateTime::from_timestamp_opt(d.read_i64()?, 0) + .ok_or_else(|| d.error("invalid timestamp"))?, + )) + } +} + +#[cfg(test)] +use rustc_serialize::json; + +#[test] +fn test_encodable() { + super::test_encodable_json(json::encode); +} + +#[test] +fn test_decodable() { + super::test_decodable_json(json::decode); +} + +#[test] +fn test_decodable_timestamps() { + super::test_decodable_json_timestamp(json::decode); +} diff --git a/vendor/chrono/src/naive/datetime/serde.rs b/vendor/chrono/src/naive/datetime/serde.rs new file mode 100644 index 000000000..40695fa74 --- /dev/null +++ b/vendor/chrono/src/naive/datetime/serde.rs @@ -0,0 +1,1133 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "serde")))] + +use core::fmt; +use serde::{de, ser}; + +use super::NaiveDateTime; +use crate::offset::LocalResult; + +/// Serialize a `NaiveDateTime` as an RFC 3339 string +/// +/// See [the `serde` module](./serde/index.html) for alternate +/// serialization formats. +impl ser::Serialize for NaiveDateTime { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + struct FormatWrapped<'a, D: 'a> { + inner: &'a D, + } + + impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(f) + } + } + + serializer.collect_str(&FormatWrapped { inner: &self }) + } +} + +struct NaiveDateTimeVisitor; + +impl<'de> de::Visitor<'de> for NaiveDateTimeVisitor { + type Value = NaiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a formatted date and time string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + value.parse().map_err(E::custom) + } +} + +impl<'de> de::Deserialize<'de> for NaiveDateTime { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_str(NaiveDateTimeVisitor) + } +} + +/// Used to serialize/deserialize from nanosecond-precision timestamps +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_nanoseconds; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_nanoseconds")] +/// time: NaiveDateTime +/// } +/// +/// let time = NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_nano_opt(02, 04, 59, 918355733).unwrap(); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_nanoseconds { + use core::fmt; + use serde::{de, ser}; + + use super::ne_timestamp; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of nanoseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_nanoseconds::serialize as to_nano_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_nano_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s = S { + /// time: NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_nano_opt(02, 04, 59, 918355733).unwrap(), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serializer.serialize_i64(dt.timestamp_nanos()) + } + + /// Deserialize a `NaiveDateTime` from a nanoseconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::NaiveDateTime; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_nanoseconds::deserialize as from_nano_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_nano_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(NanoSecondsTimestampVisitor) + } + + pub(super) struct NanoSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for NanoSecondsTimestampVisitor { + type Value = NaiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp") + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt(value / 1_000_000_000, (value % 1_000_000_000) as u32) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + + fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt( + value as i64 / 1_000_000_000, + (value as i64 % 1_000_000_000) as u32, + ) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + } +} + +/// Ser/de to/from optional timestamps in nanoseconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::naive::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_nanoseconds_option; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_nanoseconds_option")] +/// time: Option<NaiveDateTime> +/// } +/// +/// let time = Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_nano_opt(02, 04, 59, 918355733).unwrap()); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_nanoseconds_option { + use core::fmt; + use serde::{de, ser}; + + use super::ts_nanoseconds::NanoSecondsTimestampVisitor; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of nanoseconds since the epoch or none + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_nanoseconds_option::serialize as to_nano_tsopt; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_nano_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s = S { + /// time: Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_nano_opt(02, 04, 59, 918355733).unwrap()), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match *opt { + Some(ref dt) => serializer.serialize_some(&dt.timestamp_nanos()), + None => serializer.serialize_none(), + } + } + + /// Deserialize a `NaiveDateTime` from a nanosecond timestamp or none + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_nanoseconds_option::deserialize as from_nano_tsopt; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_nano_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_option(OptionNanoSecondsTimestampVisitor) + } + + struct OptionNanoSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for OptionNanoSecondsTimestampVisitor { + type Value = Option<NaiveDateTime>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in nanoseconds or none") + } + + /// Deserialize a timestamp in nanoseconds since the epoch + fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(NanoSecondsTimestampVisitor).map(Some) + } + + /// Deserialize a timestamp in nanoseconds since the epoch + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + + /// Deserialize a timestamp in nanoseconds since the epoch + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + } +} + +/// Used to serialize/deserialize from microsecond-precision timestamps +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_microseconds; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_microseconds")] +/// time: NaiveDateTime +/// } +/// +/// let time = NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_micro_opt(02, 04, 59, 918355).unwrap(); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918355}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_microseconds { + use core::fmt; + use serde::{de, ser}; + + use super::ne_timestamp; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of microseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_microseconds::serialize as to_micro_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_micro_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s = S { + /// time: NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_micro_opt(02, 04, 59, 918355).unwrap(), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serializer.serialize_i64(dt.timestamp_micros()) + } + + /// Deserialize a `NaiveDateTime` from a microseconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::NaiveDateTime; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_microseconds::deserialize as from_micro_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_micro_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(MicroSecondsTimestampVisitor) + } + + pub(super) struct MicroSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for MicroSecondsTimestampVisitor { + type Value = NaiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp") + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt( + value / 1_000_000, + ((value % 1_000_000) * 1000) as u32, + ) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + + fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt( + (value / 1_000_000) as i64, + ((value % 1_000_000) * 1_000) as u32, + ) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + } +} + +/// Ser/de to/from optional timestamps in microseconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::naive::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_microseconds_option; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_microseconds_option")] +/// time: Option<NaiveDateTime> +/// } +/// +/// let time = Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_micro_opt(02, 04, 59, 918355).unwrap()); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918355}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_microseconds_option { + use core::fmt; + use serde::{de, ser}; + + use super::ts_microseconds::MicroSecondsTimestampVisitor; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of microseconds since the epoch or none + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_microseconds_option::serialize as to_micro_tsopt; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_micro_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s = S { + /// time: Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_micro_opt(02, 04, 59, 918355).unwrap()), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match *opt { + Some(ref dt) => serializer.serialize_some(&dt.timestamp_micros()), + None => serializer.serialize_none(), + } + } + + /// Deserialize a `NaiveDateTime` from a nanosecond timestamp or none + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_microseconds_option::deserialize as from_micro_tsopt; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_micro_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_option(OptionMicroSecondsTimestampVisitor) + } + + struct OptionMicroSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for OptionMicroSecondsTimestampVisitor { + type Value = Option<NaiveDateTime>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in microseconds or none") + } + + /// Deserialize a timestamp in microseconds since the epoch + fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(MicroSecondsTimestampVisitor).map(Some) + } + + /// Deserialize a timestamp in microseconds since the epoch + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + + /// Deserialize a timestamp in microseconds since the epoch + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + } +} + +/// Used to serialize/deserialize from millisecond-precision timestamps +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_milliseconds; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_milliseconds")] +/// time: NaiveDateTime +/// } +/// +/// let time = NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_milli_opt(02, 04, 59, 918).unwrap(); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_milliseconds { + use core::fmt; + use serde::{de, ser}; + + use super::ne_timestamp; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of milliseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_milliseconds::serialize as to_milli_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_milli_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s = S { + /// time: NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_milli_opt(02, 04, 59, 918).unwrap(), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serializer.serialize_i64(dt.timestamp_millis()) + } + + /// Deserialize a `NaiveDateTime` from a milliseconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::NaiveDateTime; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_milliseconds::deserialize as from_milli_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_milli_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(MilliSecondsTimestampVisitor) + } + + pub(super) struct MilliSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for MilliSecondsTimestampVisitor { + type Value = NaiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp") + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt(value / 1000, ((value % 1000) * 1_000_000) as u32) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + + fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt( + (value / 1000) as i64, + ((value % 1000) * 1_000_000) as u32, + ) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + } +} + +/// Ser/de to/from optional timestamps in milliseconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::naive::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_milliseconds_option; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_milliseconds_option")] +/// time: Option<NaiveDateTime> +/// } +/// +/// let time = Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_milli_opt(02, 04, 59, 918).unwrap()); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699918}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_milliseconds_option { + use core::fmt; + use serde::{de, ser}; + + use super::ts_milliseconds::MilliSecondsTimestampVisitor; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of milliseconds since the epoch or none + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_milliseconds_option::serialize as to_milli_tsopt; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_milli_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s = S { + /// time: Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_milli_opt(02, 04, 59, 918).unwrap()), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match *opt { + Some(ref dt) => serializer.serialize_some(&dt.timestamp_millis()), + None => serializer.serialize_none(), + } + } + + /// Deserialize a `NaiveDateTime` from a nanosecond timestamp or none + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_milliseconds_option::deserialize as from_milli_tsopt; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_milli_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_option(OptionMilliSecondsTimestampVisitor) + } + + struct OptionMilliSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for OptionMilliSecondsTimestampVisitor { + type Value = Option<NaiveDateTime>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in milliseconds or none") + } + + /// Deserialize a timestamp in milliseconds since the epoch + fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(MilliSecondsTimestampVisitor).map(Some) + } + + /// Deserialize a timestamp in milliseconds since the epoch + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + + /// Deserialize a timestamp in milliseconds since the epoch + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + } +} + +/// Used to serialize/deserialize from second-precision timestamps +/// +/// # Example: +/// +/// ```rust +/// # use chrono::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_seconds; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_seconds")] +/// time: NaiveDateTime +/// } +/// +/// let time = NaiveDate::from_ymd_opt(2015, 5, 15).unwrap().and_hms_opt(10, 0, 0).unwrap(); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1431684000}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_seconds { + use core::fmt; + use serde::{de, ser}; + + use super::ne_timestamp; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of seconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_seconds::serialize as to_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s = S { + /// time: NaiveDate::from_ymd_opt(2015, 5, 15).unwrap().and_hms_opt(10, 0, 0).unwrap(), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1431684000}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serializer.serialize_i64(dt.timestamp()) + } + + /// Deserialize a `NaiveDateTime` from a seconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::NaiveDateTime; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_seconds::deserialize as from_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_ts")] + /// time: NaiveDateTime + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(SecondsTimestampVisitor) + } + + pub(super) struct SecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for SecondsTimestampVisitor { + type Value = NaiveDateTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp") + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt(value, 0) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + + fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + NaiveDateTime::from_timestamp_opt(value as i64, 0) + .ok_or_else(|| E::custom(ne_timestamp(value))) + } + } +} + +/// Ser/de to/from optional timestamps in seconds +/// +/// Intended for use with `serde`'s `with` attribute. +/// +/// # Example: +/// +/// ```rust +/// # use chrono::naive::{NaiveDate, NaiveDateTime}; +/// # use serde_derive::{Deserialize, Serialize}; +/// use chrono::naive::serde::ts_seconds_option; +/// #[derive(Deserialize, Serialize)] +/// struct S { +/// #[serde(with = "ts_seconds_option")] +/// time: Option<NaiveDateTime> +/// } +/// +/// let time = Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_opt(02, 04, 59).unwrap()); +/// let my_s = S { +/// time: time.clone(), +/// }; +/// +/// let as_string = serde_json::to_string(&my_s)?; +/// assert_eq!(as_string, r#"{"time":1526522699}"#); +/// let my_s: S = serde_json::from_str(&as_string)?; +/// assert_eq!(my_s.time, time); +/// # Ok::<(), serde_json::Error>(()) +/// ``` +pub mod ts_seconds_option { + use core::fmt; + use serde::{de, ser}; + + use super::ts_seconds::SecondsTimestampVisitor; + use crate::NaiveDateTime; + + /// Serialize a datetime into an integer number of seconds since the epoch or none + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Serialize; + /// use chrono::naive::serde::ts_seconds_option::serialize as to_tsopt; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s = S { + /// time: Some(NaiveDate::from_ymd_opt(2018, 5, 17).unwrap().and_hms_opt(02, 04, 59).unwrap()), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699}"#); + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match *opt { + Some(ref dt) => serializer.serialize_some(&dt.timestamp()), + None => serializer.serialize_none(), + } + } + + /// Deserialize a `NaiveDateTime` from a second timestamp or none + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # use chrono::naive::{NaiveDate, NaiveDateTime}; + /// # use serde_derive::Deserialize; + /// use chrono::naive::serde::ts_seconds_option::deserialize as from_tsopt; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_tsopt")] + /// time: Option<NaiveDateTime> + /// } + /// + /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?; + /// # Ok::<(), serde_json::Error>(()) + /// ``` + pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_option(OptionSecondsTimestampVisitor) + } + + struct OptionSecondsTimestampVisitor; + + impl<'de> de::Visitor<'de> for OptionSecondsTimestampVisitor { + type Value = Option<NaiveDateTime>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a unix timestamp in seconds or none") + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + d.deserialize_i64(SecondsTimestampVisitor).map(Some) + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + + /// Deserialize a timestamp in seconds since the epoch + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(None) + } + } +} + +#[test] +fn test_serde_serialize() { + super::test_encodable_json(serde_json::to_string); +} + +#[test] +fn test_serde_deserialize() { + super::test_decodable_json(|input| serde_json::from_str(input)); +} + +// Bincode is relevant to test separately from JSON because +// it is not self-describing. +#[test] +fn test_serde_bincode() { + use crate::NaiveDate; + use bincode::{deserialize, serialize}; + + let dt = NaiveDate::from_ymd_opt(2016, 7, 8).unwrap().and_hms_milli_opt(9, 10, 48, 90).unwrap(); + let encoded = serialize(&dt).unwrap(); + let decoded: NaiveDateTime = deserialize(&encoded).unwrap(); + assert_eq!(dt, decoded); +} + +#[test] +fn test_serde_bincode_optional() { + use crate::prelude::*; + use crate::serde::ts_nanoseconds_option; + use bincode::{deserialize, serialize}; + use serde_derive::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] + struct Test { + one: Option<i64>, + #[serde(with = "ts_nanoseconds_option")] + two: Option<DateTime<Utc>>, + } + + let expected = + Test { one: Some(1), two: Some(Utc.with_ymd_and_hms(1970, 1, 1, 0, 1, 1).unwrap()) }; + let bytes: Vec<u8> = serialize(&expected).unwrap(); + let actual = deserialize::<Test>(&(bytes)).unwrap(); + + assert_eq!(expected, actual); +} + +// lik? function to convert a LocalResult into a serde-ish Result +pub(crate) fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> +where + E: de::Error, + V: fmt::Display, + T: fmt::Display, +{ + match me { + LocalResult::None => Err(E::custom(ne_timestamp(ts))), + LocalResult::Ambiguous(min, max) => { + Err(E::custom(SerdeError::Ambiguous { timestamp: ts, min, max })) + } + LocalResult::Single(val) => Ok(val), + } +} + +enum SerdeError<V: fmt::Display, D: fmt::Display> { + NonExistent { timestamp: V }, + Ambiguous { timestamp: V, min: D, max: D }, +} + +/// Construct a [`SerdeError::NonExistent`] +fn ne_timestamp<T: fmt::Display>(ts: T) -> SerdeError<T, u8> { + SerdeError::NonExistent::<T, u8> { timestamp: ts } +} + +impl<V: fmt::Display, D: fmt::Display> fmt::Debug for SerdeError<V, D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ChronoSerdeError({})", self) + } +} + +// impl<V: fmt::Display, D: fmt::Debug> core::error::Error for SerdeError<V, D> {} +impl<V: fmt::Display, D: fmt::Display> fmt::Display for SerdeError<V, D> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + SerdeError::NonExistent { timestamp } => { + write!(f, "value is not a legal timestamp: {}", timestamp) + } + SerdeError::Ambiguous { timestamp, min, max } => write!( + f, + "value is an ambiguous timestamp: {}, could be either of {}, {}", + timestamp, min, max + ), + } + } +} diff --git a/vendor/chrono/src/naive/datetime/tests.rs b/vendor/chrono/src/naive/datetime/tests.rs new file mode 100644 index 000000000..202bdb34d --- /dev/null +++ b/vendor/chrono/src/naive/datetime/tests.rs @@ -0,0 +1,343 @@ +use super::NaiveDateTime; +use crate::oldtime::Duration; +use crate::NaiveDate; +use crate::{Datelike, FixedOffset, Utc}; +use std::i64; + +#[test] +fn test_datetime_from_timestamp_millis() { + let valid_map = [ + (1662921288000, "2022-09-11 18:34:48.000000000"), + (1662921288123, "2022-09-11 18:34:48.123000000"), + (1662921287890, "2022-09-11 18:34:47.890000000"), + (-2208936075000, "1900-01-01 14:38:45.000000000"), + (0, "1970-01-01 00:00:00.000000000"), + (119731017000, "1973-10-17 18:36:57.000000000"), + (1234567890000, "2009-02-13 23:31:30.000000000"), + (2034061609000, "2034-06-16 09:06:49.000000000"), + ]; + + for (timestamp_millis, formatted) in valid_map.iter().copied() { + let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis); + assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis()); + assert_eq!(naive_datetime.unwrap().format("%F %T%.9f").to_string(), formatted); + } + + let invalid = [i64::MAX, i64::MIN]; + + for timestamp_millis in invalid.iter().copied() { + let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis); + assert!(naive_datetime.is_none()); + } + + // Test that the result of `from_timestamp_millis` compares equal to + // that of `from_timestamp_opt`. + let secs_test = [0, 1, 2, 1000, 1234, 12345678, -1, -2, -1000, -12345678]; + for secs in secs_test.iter().cloned() { + assert_eq!( + NaiveDateTime::from_timestamp_millis(secs * 1000), + NaiveDateTime::from_timestamp_opt(secs, 0) + ); + } +} + +#[test] +fn test_datetime_from_timestamp_micros() { + let valid_map = [ + (1662921288000000, "2022-09-11 18:34:48.000000000"), + (1662921288123456, "2022-09-11 18:34:48.123456000"), + (1662921287890000, "2022-09-11 18:34:47.890000000"), + (-2208936075000000, "1900-01-01 14:38:45.000000000"), + (0, "1970-01-01 00:00:00.000000000"), + (119731017000000, "1973-10-17 18:36:57.000000000"), + (1234567890000000, "2009-02-13 23:31:30.000000000"), + (2034061609000000, "2034-06-16 09:06:49.000000000"), + ]; + + for (timestamp_micros, formatted) in valid_map.iter().copied() { + let naive_datetime = NaiveDateTime::from_timestamp_micros(timestamp_micros); + assert_eq!(timestamp_micros, naive_datetime.unwrap().timestamp_micros()); + assert_eq!(naive_datetime.unwrap().format("%F %T%.9f").to_string(), formatted); + } + + let invalid = [i64::MAX, i64::MIN]; + + for timestamp_micros in invalid.iter().copied() { + let naive_datetime = NaiveDateTime::from_timestamp_micros(timestamp_micros); + assert!(naive_datetime.is_none()); + } + + // Test that the result of `from_timestamp_micros` compares equal to + // that of `from_timestamp_opt`. + let secs_test = [0, 1, 2, 1000, 1234, 12345678, -1, -2, -1000, -12345678]; + for secs in secs_test.iter().copied() { + assert_eq!( + NaiveDateTime::from_timestamp_micros(secs * 1_000_000), + NaiveDateTime::from_timestamp_opt(secs, 0) + ); + } +} + +#[test] +fn test_datetime_from_timestamp() { + let from_timestamp = |secs| NaiveDateTime::from_timestamp_opt(secs, 0); + let ymdhms = + |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + assert_eq!(from_timestamp(-1), Some(ymdhms(1969, 12, 31, 23, 59, 59))); + assert_eq!(from_timestamp(0), Some(ymdhms(1970, 1, 1, 0, 0, 0))); + assert_eq!(from_timestamp(1), Some(ymdhms(1970, 1, 1, 0, 0, 1))); + assert_eq!(from_timestamp(1_000_000_000), Some(ymdhms(2001, 9, 9, 1, 46, 40))); + assert_eq!(from_timestamp(0x7fffffff), Some(ymdhms(2038, 1, 19, 3, 14, 7))); + assert_eq!(from_timestamp(i64::MIN), None); + assert_eq!(from_timestamp(i64::MAX), None); +} + +#[test] +fn test_datetime_add() { + fn check( + (y, m, d, h, n, s): (i32, u32, u32, u32, u32, u32), + rhs: Duration, + result: Option<(i32, u32, u32, u32, u32, u32)>, + ) { + let lhs = NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + let sum = result.map(|(y, m, d, h, n, s)| { + NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap() + }); + assert_eq!(lhs.checked_add_signed(rhs), sum); + assert_eq!(lhs.checked_sub_signed(-rhs), sum); + } + + check((2014, 5, 6, 7, 8, 9), Duration::seconds(3600 + 60 + 1), Some((2014, 5, 6, 8, 9, 10))); + check((2014, 5, 6, 7, 8, 9), Duration::seconds(-(3600 + 60 + 1)), Some((2014, 5, 6, 6, 7, 8))); + check((2014, 5, 6, 7, 8, 9), Duration::seconds(86399), Some((2014, 5, 7, 7, 8, 8))); + check((2014, 5, 6, 7, 8, 9), Duration::seconds(86_400 * 10), Some((2014, 5, 16, 7, 8, 9))); + check((2014, 5, 6, 7, 8, 9), Duration::seconds(-86_400 * 10), Some((2014, 4, 26, 7, 8, 9))); + check((2014, 5, 6, 7, 8, 9), Duration::seconds(86_400 * 10), Some((2014, 5, 16, 7, 8, 9))); + + // overflow check + // assumes that we have correct values for MAX/MIN_DAYS_FROM_YEAR_0 from `naive::date`. + // (they are private constants, but the equivalence is tested in that module.) + let max_days_from_year_0 = + NaiveDate::MAX.signed_duration_since(NaiveDate::from_ymd_opt(0, 1, 1).unwrap()); + check((0, 1, 1, 0, 0, 0), max_days_from_year_0, Some((NaiveDate::MAX.year(), 12, 31, 0, 0, 0))); + check( + (0, 1, 1, 0, 0, 0), + max_days_from_year_0 + Duration::seconds(86399), + Some((NaiveDate::MAX.year(), 12, 31, 23, 59, 59)), + ); + check((0, 1, 1, 0, 0, 0), max_days_from_year_0 + Duration::seconds(86_400), None); + check((0, 1, 1, 0, 0, 0), Duration::max_value(), None); + + let min_days_from_year_0 = + NaiveDate::MIN.signed_duration_since(NaiveDate::from_ymd_opt(0, 1, 1).unwrap()); + check((0, 1, 1, 0, 0, 0), min_days_from_year_0, Some((NaiveDate::MIN.year(), 1, 1, 0, 0, 0))); + check((0, 1, 1, 0, 0, 0), min_days_from_year_0 - Duration::seconds(1), None); + check((0, 1, 1, 0, 0, 0), Duration::min_value(), None); +} + +#[test] +fn test_datetime_sub() { + let ymdhms = + |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + let since = NaiveDateTime::signed_duration_since; + assert_eq!(since(ymdhms(2014, 5, 6, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 9)), Duration::zero()); + assert_eq!( + since(ymdhms(2014, 5, 6, 7, 8, 10), ymdhms(2014, 5, 6, 7, 8, 9)), + Duration::seconds(1) + ); + assert_eq!( + since(ymdhms(2014, 5, 6, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 10)), + Duration::seconds(-1) + ); + assert_eq!( + since(ymdhms(2014, 5, 7, 7, 8, 9), ymdhms(2014, 5, 6, 7, 8, 10)), + Duration::seconds(86399) + ); + assert_eq!( + since(ymdhms(2001, 9, 9, 1, 46, 39), ymdhms(1970, 1, 1, 0, 0, 0)), + Duration::seconds(999_999_999) + ); +} + +#[test] +fn test_datetime_addassignment() { + let ymdhms = + |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date += Duration::minutes(10_000_000); + assert_eq!(date, ymdhms(2035, 10, 6, 20, 50, 10)); + date += Duration::days(10); + assert_eq!(date, ymdhms(2035, 10, 16, 20, 50, 10)); +} + +#[test] +fn test_datetime_subassignment() { + let ymdhms = + |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date -= Duration::minutes(10_000_000); + assert_eq!(date, ymdhms(1997, 9, 26, 23, 30, 10)); + date -= Duration::days(10); + assert_eq!(date, ymdhms(1997, 9, 16, 23, 30, 10)); +} + +#[test] +fn test_datetime_timestamp() { + let to_timestamp = |y, m, d, h, n, s| { + NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap().timestamp() + }; + assert_eq!(to_timestamp(1969, 12, 31, 23, 59, 59), -1); + assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 0), 0); + assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 1), 1); + assert_eq!(to_timestamp(2001, 9, 9, 1, 46, 40), 1_000_000_000); + assert_eq!(to_timestamp(2038, 1, 19, 3, 14, 7), 0x7fffffff); +} + +#[test] +fn test_datetime_from_str() { + // valid cases + let valid = [ + "2015-2-18T23:16:9.15", + "-77-02-18T23:16:09", + " +82701 - 05 - 6 T 15 : 9 : 60.898989898989 ", + ]; + for &s in &valid { + let d = match s.parse::<NaiveDateTime>() { + Ok(d) => d, + Err(e) => panic!("parsing `{}` has failed: {}", s, e), + }; + let s_ = format!("{:?}", d); + // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same + let d_ = match s_.parse::<NaiveDateTime>() { + Ok(d) => d, + Err(e) => { + panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}", s, d, e) + } + }; + assert!( + d == d_, + "`{}` is parsed into `{:?}`, but reparsed result \ + `{:?}` does not match", + s, + d, + d_ + ); + } + + // some invalid cases + // since `ParseErrorKind` is private, all we can do is to check if there was an error + assert!("".parse::<NaiveDateTime>().is_err()); + assert!("x".parse::<NaiveDateTime>().is_err()); + assert!("15".parse::<NaiveDateTime>().is_err()); + assert!("15:8:9".parse::<NaiveDateTime>().is_err()); + assert!("15-8-9".parse::<NaiveDateTime>().is_err()); + assert!("2015-15-15T15:15:15".parse::<NaiveDateTime>().is_err()); + assert!("2012-12-12T12:12:12x".parse::<NaiveDateTime>().is_err()); + assert!("2012-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); + assert!("+ 82701-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); + assert!("+802701-123-12T12:12:12".parse::<NaiveDateTime>().is_err()); // out-of-bound +} + +#[test] +fn test_datetime_parse_from_str() { + let ymdhms = + |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); + let ymdhmsn = |y, m, d, h, n, s, nano| { + NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_nano_opt(h, n, s, nano).unwrap() + }; + assert_eq!( + NaiveDateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), + Ok(ymdhms(2014, 5, 7, 12, 34, 56)) + ); // ignore offset + assert_eq!( + NaiveDateTime::parse_from_str("2015-W06-1 000000", "%G-W%V-%u%H%M%S"), + Ok(ymdhms(2015, 2, 2, 0, 0, 0)) + ); + assert_eq!( + NaiveDateTime::parse_from_str("Fri, 09 Aug 2013 23:54:35 GMT", "%a, %d %b %Y %H:%M:%S GMT"), + Ok(ymdhms(2013, 8, 9, 23, 54, 35)) + ); + assert!(NaiveDateTime::parse_from_str( + "Sat, 09 Aug 2013 23:54:35 GMT", + "%a, %d %b %Y %H:%M:%S GMT" + ) + .is_err()); + assert!(NaiveDateTime::parse_from_str("2014-5-7 12:3456", "%Y-%m-%d %H:%M:%S").is_err()); + assert!(NaiveDateTime::parse_from_str("12:34:56", "%H:%M:%S").is_err()); // insufficient + assert_eq!( + NaiveDateTime::parse_from_str("1441497364", "%s"), + Ok(ymdhms(2015, 9, 5, 23, 56, 4)) + ); + assert_eq!( + NaiveDateTime::parse_from_str("1283929614.1234", "%s.%f"), + Ok(ymdhmsn(2010, 9, 8, 7, 6, 54, 1234)) + ); + assert_eq!( + NaiveDateTime::parse_from_str("1441497364.649", "%s%.3f"), + Ok(ymdhmsn(2015, 9, 5, 23, 56, 4, 649000000)) + ); + assert_eq!( + NaiveDateTime::parse_from_str("1497854303.087654", "%s%.6f"), + Ok(ymdhmsn(2017, 6, 19, 6, 38, 23, 87654000)) + ); + assert_eq!( + NaiveDateTime::parse_from_str("1437742189.918273645", "%s%.9f"), + Ok(ymdhmsn(2015, 7, 24, 12, 49, 49, 918273645)) + ); +} + +#[test] +fn test_datetime_format() { + let dt = NaiveDate::from_ymd_opt(2010, 9, 8).unwrap().and_hms_milli_opt(7, 6, 54, 321).unwrap(); + assert_eq!(dt.format("%c").to_string(), "Wed Sep 8 07:06:54 2010"); + assert_eq!(dt.format("%s").to_string(), "1283929614"); + assert_eq!(dt.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); + + // a horror of leap second: coming near to you. + let dt = + NaiveDate::from_ymd_opt(2012, 6, 30).unwrap().and_hms_milli_opt(23, 59, 59, 1_000).unwrap(); + assert_eq!(dt.format("%c").to_string(), "Sat Jun 30 23:59:60 2012"); + assert_eq!(dt.format("%s").to_string(), "1341100799"); // not 1341100800, it's intentional. +} + +#[test] +fn test_datetime_add_sub_invariant() { + // issue #37 + let base = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap(); + let t = -946684799990000; + let time = base + Duration::microseconds(t); + assert_eq!(t, time.signed_duration_since(base).num_microseconds().unwrap()); +} + +#[test] +fn test_nanosecond_range() { + const A_BILLION: i64 = 1_000_000_000; + let maximum = "2262-04-11T23:47:16.854775804"; + let parsed: NaiveDateTime = maximum.parse().unwrap(); + let nanos = parsed.timestamp_nanos(); + assert_eq!( + parsed, + NaiveDateTime::from_timestamp_opt(nanos / A_BILLION, (nanos % A_BILLION) as u32).unwrap() + ); + + let minimum = "1677-09-21T00:12:44.000000000"; + let parsed: NaiveDateTime = minimum.parse().unwrap(); + let nanos = parsed.timestamp_nanos(); + assert_eq!( + parsed, + NaiveDateTime::from_timestamp_opt(nanos / A_BILLION, (nanos % A_BILLION) as u32).unwrap() + ); +} + +#[test] +fn test_and_timezone() { + let ndt = NaiveDate::from_ymd_opt(2022, 6, 15).unwrap().and_hms_opt(18, 59, 36).unwrap(); + let dt_utc = ndt.and_local_timezone(Utc).unwrap(); + assert_eq!(dt_utc.naive_local(), ndt); + assert_eq!(dt_utc.timezone(), Utc); + + let offset_tz = FixedOffset::west_opt(4 * 3600).unwrap(); + let dt_offset = ndt.and_local_timezone(offset_tz).unwrap(); + assert_eq!(dt_offset.naive_local(), ndt); + assert_eq!(dt_offset.timezone(), offset_tz); +} diff --git a/vendor/chrono/src/naive/internals.rs b/vendor/chrono/src/naive/internals.rs index 346063c37..05305b506 100644 --- a/vendor/chrono/src/naive/internals.rs +++ b/vendor/chrono/src/naive/internals.rs @@ -13,19 +13,18 @@ //! but the conversion keeps the valid value valid and the invalid value invalid //! so that the user-facing `NaiveDate` can validate the input as late as possible. -#![allow(dead_code)] // some internal methods have been left for consistency #![cfg_attr(feature = "__internal_bench", allow(missing_docs))] +use crate::Weekday; use core::{fmt, i32}; -use div::{div_rem, mod_floor}; +use num_integer::{div_rem, mod_floor}; use num_traits::FromPrimitive; -use Weekday; /// The internal date representation. This also includes the packed `Mdf` value. -pub type DateImpl = i32; +pub(super) type DateImpl = i32; -pub const MAX_YEAR: DateImpl = i32::MAX >> 13; -pub const MIN_YEAR: DateImpl = i32::MIN >> 13; +pub(super) const MAX_YEAR: DateImpl = i32::MAX >> 13; +pub(super) const MIN_YEAR: DateImpl = i32::MIN >> 13; /// The year flags (aka the dominical letter). /// @@ -35,23 +34,24 @@ pub const MIN_YEAR: DateImpl = i32::MIN >> 13; /// where `a` is `1` for the common year (simplifies the `Of` validation) /// and `bbb` is a non-zero `Weekday` (mapping `Mon` to 7) of the last day in the past year /// (simplifies the day of week calculation from the 1-based ordinal). -#[derive(PartialEq, Eq, Copy, Clone)] -pub struct YearFlags(pub u8); - -pub const A: YearFlags = YearFlags(0o15); -pub const AG: YearFlags = YearFlags(0o05); -pub const B: YearFlags = YearFlags(0o14); -pub const BA: YearFlags = YearFlags(0o04); -pub const C: YearFlags = YearFlags(0o13); -pub const CB: YearFlags = YearFlags(0o03); -pub const D: YearFlags = YearFlags(0o12); -pub const DC: YearFlags = YearFlags(0o02); -pub const E: YearFlags = YearFlags(0o11); -pub const ED: YearFlags = YearFlags(0o01); -pub const F: YearFlags = YearFlags(0o17); -pub const FE: YearFlags = YearFlags(0o07); -pub const G: YearFlags = YearFlags(0o16); -pub const GF: YearFlags = YearFlags(0o06); +#[allow(unreachable_pub)] // public as an alias for benchmarks only +#[derive(PartialEq, Eq, Copy, Clone, Hash)] +pub struct YearFlags(pub(super) u8); + +pub(super) const A: YearFlags = YearFlags(0o15); +pub(super) const AG: YearFlags = YearFlags(0o05); +pub(super) const B: YearFlags = YearFlags(0o14); +pub(super) const BA: YearFlags = YearFlags(0o04); +pub(super) const C: YearFlags = YearFlags(0o13); +pub(super) const CB: YearFlags = YearFlags(0o03); +pub(super) const D: YearFlags = YearFlags(0o12); +pub(super) const DC: YearFlags = YearFlags(0o02); +pub(super) const E: YearFlags = YearFlags(0o11); +pub(super) const ED: YearFlags = YearFlags(0o01); +pub(super) const F: YearFlags = YearFlags(0o17); +pub(super) const FE: YearFlags = YearFlags(0o07); +pub(super) const G: YearFlags = YearFlags(0o16); +pub(super) const GF: YearFlags = YearFlags(0o06); static YEAR_TO_FLAGS: [YearFlags; 400] = [ BA, G, F, E, DC, B, A, G, FE, D, C, B, AG, F, E, D, CB, A, G, F, ED, C, B, A, GF, E, D, C, BA, @@ -94,7 +94,7 @@ static YEAR_DELTAS: [u8; 401] = [ 96, 97, 97, 97, 97, // 400+1 ]; -pub fn cycle_to_yo(cycle: u32) -> (u32, u32) { +pub(super) fn cycle_to_yo(cycle: u32) -> (u32, u32) { let (mut year_mod_400, mut ordinal0) = div_rem(cycle, 365); let delta = u32::from(YEAR_DELTAS[year_mod_400 as usize]); if ordinal0 < delta { @@ -106,11 +106,13 @@ pub fn cycle_to_yo(cycle: u32) -> (u32, u32) { (year_mod_400, ordinal0 + 1) } -pub fn yo_to_cycle(year_mod_400: u32, ordinal: u32) -> u32 { +pub(super) fn yo_to_cycle(year_mod_400: u32, ordinal: u32) -> u32 { year_mod_400 * 365 + u32::from(YEAR_DELTAS[year_mod_400 as usize]) + ordinal - 1 } impl YearFlags { + #[allow(unreachable_pub)] // public as an alias for benchmarks only + #[doc(hidden)] // for benchmarks only #[inline] pub fn from_year(year: i32) -> YearFlags { let year = mod_floor(year, 400); @@ -118,18 +120,18 @@ impl YearFlags { } #[inline] - pub fn from_year_mod_400(year: i32) -> YearFlags { + pub(super) fn from_year_mod_400(year: i32) -> YearFlags { YEAR_TO_FLAGS[year as usize] } #[inline] - pub fn ndays(&self) -> u32 { + pub(super) fn ndays(&self) -> u32 { let YearFlags(flags) = *self; 366 - u32::from(flags >> 3) } #[inline] - pub fn isoweek_delta(&self) -> u32 { + pub(super) fn isoweek_delta(&self) -> u32 { let YearFlags(flags) = *self; let mut delta = u32::from(flags) & 0b0111; if delta < 3 { @@ -139,7 +141,7 @@ impl YearFlags { } #[inline] - pub fn nisoweeks(&self) -> u32 { + pub(super) const fn nisoweeks(&self) -> u32 { let YearFlags(flags) = *self; 52 + ((0b0000_0100_0000_0110 >> flags as usize) & 1) } @@ -170,10 +172,9 @@ impl fmt::Debug for YearFlags { } } -pub const MIN_OL: u32 = 1 << 1; -pub const MAX_OL: u32 = 366 << 1; // larger than the non-leap last day `(365 << 1) | 1` -pub const MIN_MDL: u32 = (1 << 6) | (1 << 1); -pub const MAX_MDL: u32 = (12 << 6) | (31 << 1) | 1; +pub(super) const MIN_OL: u32 = 1 << 1; +pub(super) const MAX_OL: u32 = 366 << 1; // larger than the non-leap last day `(365 << 1) | 1` +pub(super) const MAX_MDL: u32 = (12 << 6) | (31 << 1) | 1; const XX: i8 = -128; static MDL_TO_OL: [i8; MAX_MDL as usize + 1] = [ @@ -265,26 +266,19 @@ static OL_TO_MDL: [u8; MAX_OL as usize + 1] = [ /// The whole bits except for the least 3 bits are referred as `Ol` (ordinal and leap flag), /// which is an index to the `OL_TO_MDL` lookup table. #[derive(PartialEq, PartialOrd, Copy, Clone)] -pub struct Of(pub u32); +pub(super) struct Of(pub(crate) u32); impl Of { #[inline] - fn clamp_ordinal(ordinal: u32) -> u32 { - if ordinal > 366 { - 0 - } else { - ordinal + pub(super) fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Option<Of> { + match ordinal <= 366 { + true => Some(Of((ordinal << 4) | u32::from(flags))), + false => None, } } #[inline] - pub fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Of { - let ordinal = Of::clamp_ordinal(ordinal); - Of((ordinal << 4) | u32::from(flags)) - } - - #[inline] - pub fn from_mdf(Mdf(mdf): Mdf) -> Of { + pub(super) fn from_mdf(Mdf(mdf): Mdf) -> Of { let mdl = mdf >> 3; match MDL_TO_OL.get(mdl as usize) { Some(&v) => Of(mdf.wrapping_sub((i32::from(v) as u32 & 0x3ff) << 3)), @@ -293,64 +287,62 @@ impl Of { } #[inline] - pub fn valid(&self) -> bool { + pub(super) fn valid(&self) -> bool { let Of(of) = *self; let ol = of >> 3; - MIN_OL <= ol && ol <= MAX_OL + (MIN_OL..=MAX_OL).contains(&ol) } #[inline] - pub fn ordinal(&self) -> u32 { + pub(super) const fn ordinal(&self) -> u32 { let Of(of) = *self; of >> 4 } #[inline] - pub fn with_ordinal(&self, ordinal: u32) -> Of { - let ordinal = Of::clamp_ordinal(ordinal); - let Of(of) = *self; - Of((of & 0b1111) | (ordinal << 4)) - } + pub(super) fn with_ordinal(&self, ordinal: u32) -> Option<Of> { + if ordinal > 366 { + return None; + } - #[inline] - pub fn flags(&self) -> YearFlags { let Of(of) = *self; - YearFlags((of & 0b1111) as u8) + Some(Of((of & 0b1111) | (ordinal << 4))) } #[inline] - pub fn with_flags(&self, YearFlags(flags): YearFlags) -> Of { + pub(super) const fn flags(&self) -> YearFlags { let Of(of) = *self; - Of((of & !0b1111) | u32::from(flags)) + YearFlags((of & 0b1111) as u8) } #[inline] - pub fn weekday(&self) -> Weekday { + pub(super) fn weekday(&self) -> Weekday { let Of(of) = *self; Weekday::from_u32(((of >> 4) + (of & 0b111)) % 7).unwrap() } #[inline] - pub fn isoweekdate_raw(&self) -> (u32, Weekday) { + pub(super) fn isoweekdate_raw(&self) -> (u32, Weekday) { // week ordinal = ordinal + delta let Of(of) = *self; let weekord = (of >> 4).wrapping_add(self.flags().isoweek_delta()); (weekord / 7, Weekday::from_u32(weekord % 7).unwrap()) } + #[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))] #[inline] - pub fn to_mdf(&self) -> Mdf { + pub(super) fn to_mdf(&self) -> Mdf { Mdf::from_of(*self) } #[inline] - pub fn succ(&self) -> Of { + pub(super) const fn succ(&self) -> Of { let Of(of) = *self; Of(of + (1 << 4)) } #[inline] - pub fn pred(&self) -> Of { + pub(super) const fn pred(&self) -> Of { let Of(of) = *self; Of(of - (1 << 4)) } @@ -375,36 +367,19 @@ impl fmt::Debug for Of { /// (month, day of month and leap flag), /// which is an index to the `MDL_TO_OL` lookup table. #[derive(PartialEq, PartialOrd, Copy, Clone)] -pub struct Mdf(pub u32); +pub(super) struct Mdf(pub(super) u32); impl Mdf { #[inline] - fn clamp_month(month: u32) -> u32 { - if month > 12 { - 0 - } else { - month - } - } - - #[inline] - fn clamp_day(day: u32) -> u32 { - if day > 31 { - 0 - } else { - day + pub(super) fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Option<Mdf> { + match month <= 12 && day <= 31 { + true => Some(Mdf((month << 9) | (day << 4) | u32::from(flags))), + false => None, } } #[inline] - pub fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Mdf { - let month = Mdf::clamp_month(month); - let day = Mdf::clamp_day(day); - Mdf((month << 9) | (day << 4) | u32::from(flags)) - } - - #[inline] - pub fn from_of(Of(of): Of) -> Mdf { + pub(super) fn from_of(Of(of): Of) -> Mdf { let ol = of >> 3; match OL_TO_MDL.get(ol as usize) { Some(&v) => Mdf(of + (u32::from(v) << 3)), @@ -412,8 +387,8 @@ impl Mdf { } } - #[inline] - pub fn valid(&self) -> bool { + #[cfg(test)] + pub(super) fn valid(&self) -> bool { let Mdf(mdf) = *self; let mdl = mdf >> 3; match MDL_TO_OL.get(mdl as usize) { @@ -423,45 +398,46 @@ impl Mdf { } #[inline] - pub fn month(&self) -> u32 { + pub(super) const fn month(&self) -> u32 { let Mdf(mdf) = *self; mdf >> 9 } #[inline] - pub fn with_month(&self, month: u32) -> Mdf { - let month = Mdf::clamp_month(month); + pub(super) fn with_month(&self, month: u32) -> Option<Mdf> { + if month > 12 { + return None; + } + let Mdf(mdf) = *self; - Mdf((mdf & 0b1_1111_1111) | (month << 9)) + Some(Mdf((mdf & 0b1_1111_1111) | (month << 9))) } #[inline] - pub fn day(&self) -> u32 { + pub(super) const fn day(&self) -> u32 { let Mdf(mdf) = *self; (mdf >> 4) & 0b1_1111 } #[inline] - pub fn with_day(&self, day: u32) -> Mdf { - let day = Mdf::clamp_day(day); - let Mdf(mdf) = *self; - Mdf((mdf & !0b1_1111_0000) | (day << 4)) - } + pub(super) fn with_day(&self, day: u32) -> Option<Mdf> { + if day > 31 { + return None; + } - #[inline] - pub fn flags(&self) -> YearFlags { let Mdf(mdf) = *self; - YearFlags((mdf & 0b1111) as u8) + Some(Mdf((mdf & !0b1_1111_0000) | (day << 4))) } #[inline] - pub fn with_flags(&self, YearFlags(flags): YearFlags) -> Mdf { + pub(super) fn with_flags(&self, YearFlags(flags): YearFlags) -> Mdf { let Mdf(mdf) = *self; Mdf((mdf & !0b1111) | u32::from(flags)) } + #[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))] #[inline] - pub fn to_of(&self) -> Of { + pub(super) fn to_of(&self) -> Of { Of::from_mdf(*self) } } @@ -482,14 +458,12 @@ impl fmt::Debug for Mdf { #[cfg(test)] mod tests { - #[cfg(test)] - extern crate num_iter; + use num_iter::range_inclusive; + use std::u32; - use self::num_iter::range_inclusive; use super::{Mdf, Of}; use super::{YearFlags, A, AG, B, BA, C, CB, D, DC, E, ED, F, FE, G, GF}; - use std::u32; - use Weekday; + use crate::Weekday; const NONLEAP_FLAGS: [YearFlags; 7] = [A, B, C, D, E, F, G]; const LEAP_FLAGS: [YearFlags; 7] = [AG, BA, CB, DC, ED, FE, GF]; @@ -534,7 +508,12 @@ mod tests { fn test_of() { fn check(expected: bool, flags: YearFlags, ordinal1: u32, ordinal2: u32) { for ordinal in range_inclusive(ordinal1, ordinal2) { - let of = Of::new(ordinal, flags); + let of = match Of::new(ordinal, flags) { + Some(of) => of, + None if !expected => continue, + None => panic!("Of::new({}, {:?}) returned None", ordinal, flags), + }; + assert!( of.valid() == expected, "ordinal {} = {:?} should be {} for dominical year {:?}", @@ -566,7 +545,12 @@ mod tests { fn check(expected: bool, flags: YearFlags, month1: u32, day1: u32, month2: u32, day2: u32) { for month in range_inclusive(month1, month2) { for day in range_inclusive(day1, day2) { - let mdf = Mdf::new(month, day, flags); + let mdf = match Mdf::new(month, day, flags) { + Some(mdf) => mdf, + None if !expected => continue, + None => panic!("Mdf::new({}, {}, {:?}) returned None", month, day, flags), + }; + assert!( mdf.valid() == expected, "month {} day {} = {:?} should be {} for dominical year {:?}", @@ -651,7 +635,7 @@ mod tests { fn test_of_fields() { for &flags in FLAGS.iter() { for ordinal in range_inclusive(1u32, 366) { - let of = Of::new(ordinal, flags); + let of = Of::new(ordinal, flags).unwrap(); if of.valid() { assert_eq!(of.ordinal(), ordinal); } @@ -662,11 +646,16 @@ mod tests { #[test] fn test_of_with_fields() { fn check(flags: YearFlags, ordinal: u32) { - let of = Of::new(ordinal, flags); + let of = Of::new(ordinal, flags).unwrap(); for ordinal in range_inclusive(0u32, 1024) { - let of = of.with_ordinal(ordinal); - assert_eq!(of.valid(), Of::new(ordinal, flags).valid()); + let of = match of.with_ordinal(ordinal) { + Some(of) => of, + None if ordinal > 366 => continue, + None => panic!("failed to create Of with ordinal {}", ordinal), + }; + + assert_eq!(of.valid(), Of::new(ordinal, flags).unwrap().valid()); if of.valid() { assert_eq!(of.ordinal(), ordinal); } @@ -685,25 +674,25 @@ mod tests { #[test] fn test_of_weekday() { - assert_eq!(Of::new(1, A).weekday(), Weekday::Sun); - assert_eq!(Of::new(1, B).weekday(), Weekday::Sat); - assert_eq!(Of::new(1, C).weekday(), Weekday::Fri); - assert_eq!(Of::new(1, D).weekday(), Weekday::Thu); - assert_eq!(Of::new(1, E).weekday(), Weekday::Wed); - assert_eq!(Of::new(1, F).weekday(), Weekday::Tue); - assert_eq!(Of::new(1, G).weekday(), Weekday::Mon); - assert_eq!(Of::new(1, AG).weekday(), Weekday::Sun); - assert_eq!(Of::new(1, BA).weekday(), Weekday::Sat); - assert_eq!(Of::new(1, CB).weekday(), Weekday::Fri); - assert_eq!(Of::new(1, DC).weekday(), Weekday::Thu); - assert_eq!(Of::new(1, ED).weekday(), Weekday::Wed); - assert_eq!(Of::new(1, FE).weekday(), Weekday::Tue); - assert_eq!(Of::new(1, GF).weekday(), Weekday::Mon); + assert_eq!(Of::new(1, A).unwrap().weekday(), Weekday::Sun); + assert_eq!(Of::new(1, B).unwrap().weekday(), Weekday::Sat); + assert_eq!(Of::new(1, C).unwrap().weekday(), Weekday::Fri); + assert_eq!(Of::new(1, D).unwrap().weekday(), Weekday::Thu); + assert_eq!(Of::new(1, E).unwrap().weekday(), Weekday::Wed); + assert_eq!(Of::new(1, F).unwrap().weekday(), Weekday::Tue); + assert_eq!(Of::new(1, G).unwrap().weekday(), Weekday::Mon); + assert_eq!(Of::new(1, AG).unwrap().weekday(), Weekday::Sun); + assert_eq!(Of::new(1, BA).unwrap().weekday(), Weekday::Sat); + assert_eq!(Of::new(1, CB).unwrap().weekday(), Weekday::Fri); + assert_eq!(Of::new(1, DC).unwrap().weekday(), Weekday::Thu); + assert_eq!(Of::new(1, ED).unwrap().weekday(), Weekday::Wed); + assert_eq!(Of::new(1, FE).unwrap().weekday(), Weekday::Tue); + assert_eq!(Of::new(1, GF).unwrap().weekday(), Weekday::Mon); for &flags in FLAGS.iter() { - let mut prev = Of::new(1, flags).weekday(); + let mut prev = Of::new(1, flags).unwrap().weekday(); for ordinal in range_inclusive(2u32, flags.ndays()) { - let of = Of::new(ordinal, flags); + let of = Of::new(ordinal, flags).unwrap(); let expected = prev.succ(); assert_eq!(of.weekday(), expected); prev = expected; @@ -716,7 +705,11 @@ mod tests { for &flags in FLAGS.iter() { for month in range_inclusive(1u32, 12) { for day in range_inclusive(1u32, 31) { - let mdf = Mdf::new(month, day, flags); + let mdf = match Mdf::new(month, day, flags) { + Some(mdf) => mdf, + None => continue, + }; + if mdf.valid() { assert_eq!(mdf.month(), month); assert_eq!(mdf.day(), day); @@ -729,11 +722,15 @@ mod tests { #[test] fn test_mdf_with_fields() { fn check(flags: YearFlags, month: u32, day: u32) { - let mdf = Mdf::new(month, day, flags); + let mdf = Mdf::new(month, day, flags).unwrap(); for month in range_inclusive(0u32, 16) { - let mdf = mdf.with_month(month); - assert_eq!(mdf.valid(), Mdf::new(month, day, flags).valid()); + let mdf = match mdf.with_month(month) { + Some(mdf) => mdf, + None if month > 12 => continue, + None => panic!("failed to create Mdf with month {}", month), + }; + if mdf.valid() { assert_eq!(mdf.month(), month); assert_eq!(mdf.day(), day); @@ -741,8 +738,12 @@ mod tests { } for day in range_inclusive(0u32, 1024) { - let mdf = mdf.with_day(day); - assert_eq!(mdf.valid(), Mdf::new(month, day, flags).valid()); + let mdf = match mdf.with_day(day) { + Some(mdf) => mdf, + None if day > 31 => continue, + None => panic!("failed to create Mdf with month {}", month), + }; + if mdf.valid() { assert_eq!(mdf.month(), month); assert_eq!(mdf.day(), day); @@ -772,7 +773,7 @@ mod tests { fn test_of_isoweekdate_raw() { for &flags in FLAGS.iter() { // January 4 should be in the first week - let (week, _) = Of::new(4 /* January 4 */, flags).isoweekdate_raw(); + let (week, _) = Of::new(4 /* January 4 */, flags).unwrap().isoweekdate_raw(); assert_eq!(week, 1); } } diff --git a/vendor/chrono/src/naive/isoweek.rs b/vendor/chrono/src/naive/isoweek.rs index ece10f250..6a4fcfd11 100644 --- a/vendor/chrono/src/naive/isoweek.rs +++ b/vendor/chrono/src/naive/isoweek.rs @@ -7,13 +7,17 @@ use core::fmt; use super::internals::{DateImpl, Of, YearFlags}; +#[cfg(feature = "rkyv")] +use rkyv::{Archive, Deserialize, Serialize}; + /// ISO 8601 week. /// /// This type, combined with [`Weekday`](../enum.Weekday.html), -/// constitues the ISO 8601 [week date](./struct.NaiveDate.html#week-date). +/// constitutes the ISO 8601 [week date](./struct.NaiveDate.html#week-date). /// One can retrieve this type from the existing [`Datelike`](../trait.Datelike.html) types /// via the [`Datelike::iso_week`](../trait.Datelike.html#tymethod.iso_week) method. -#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Hash)] +#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))] pub struct IsoWeek { // note that this allows for larger year range than `NaiveDate`. // this is crucial because we have an edge case for the first and last week supported, @@ -27,7 +31,7 @@ pub struct IsoWeek { // because the year range for the week date and the calendar date do not match and // it is confusing to have a date that is out of range in one and not in another. // currently we sidestep this issue by making `IsoWeek` fully dependent of `Datelike`. -pub fn iso_week_from_yof(year: i32, of: Of) -> IsoWeek { +pub(super) fn iso_week_from_yof(year: i32, of: Of) -> IsoWeek { let (rawweek, _) = of.isoweekdate_raw(); let (year, week) = if rawweek < 1 { // previous year @@ -50,24 +54,24 @@ impl IsoWeek { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike, Weekday}; /// /// let d = NaiveDate::from_isoywd(2015, 1, Weekday::Mon); /// assert_eq!(d.iso_week().year(), 2015); - /// ~~~~ + /// ``` /// /// This year number might not match the calendar year number. /// Continuing the example... /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveDate, Datelike, Weekday}; /// # let d = NaiveDate::from_isoywd(2015, 1, Weekday::Mon); /// assert_eq!(d.year(), 2014); - /// assert_eq!(d, NaiveDate::from_ymd(2014, 12, 29)); - /// ~~~~ + /// assert_eq!(d, NaiveDate::from_ymd_opt(2014, 12, 29).unwrap()); + /// ``` #[inline] - pub fn year(&self) -> i32 { + pub const fn year(&self) -> i32 { self.ywf >> 10 } @@ -77,14 +81,14 @@ impl IsoWeek { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike, Weekday}; /// /// let d = NaiveDate::from_isoywd(2015, 15, Weekday::Mon); /// assert_eq!(d.iso_week().week(), 15); - /// ~~~~ + /// ``` #[inline] - pub fn week(&self) -> u32 { + pub const fn week(&self) -> u32 { ((self.ywf >> 4) & 0x3f) as u32 } @@ -94,14 +98,14 @@ impl IsoWeek { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveDate, Datelike, Weekday}; /// /// let d = NaiveDate::from_isoywd(2015, 15, Weekday::Mon); /// assert_eq!(d.iso_week().week0(), 14); - /// ~~~~ + /// ``` #[inline] - pub fn week0(&self) -> u32 { + pub const fn week0(&self) -> u32 { ((self.ywf >> 4) & 0x3f) as u32 - 1 } } @@ -112,26 +116,26 @@ impl IsoWeek { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::{NaiveDate, Datelike}; /// -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(2015, 9, 5).iso_week()), "2015-W36"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( 0, 1, 3).iso_week()), "0000-W01"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(9999, 12, 31).iso_week()), "9999-W52"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().iso_week()), "2015-W36"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( 0, 1, 3).unwrap().iso_week()), "0000-W01"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(9999, 12, 31).unwrap().iso_week()), "9999-W52"); +/// ``` /// /// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE. /// -/// ~~~~ +/// ``` /// # use chrono::{NaiveDate, Datelike}; -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( 0, 1, 2).iso_week()), "-0001-W52"); -/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(10000, 12, 31).iso_week()), "+10000-W52"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( 0, 1, 2).unwrap().iso_week()), "-0001-W52"); +/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(10000, 12, 31).unwrap().iso_week()), "+10000-W52"); +/// ``` impl fmt::Debug for IsoWeek { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let year = self.year(); let week = self.week(); - if 0 <= year && year <= 9999 { + if (0..=9999).contains(&year) { write!(f, "{:04}-W{:02}", year, week) } else { // ISO 8601 requires the explicit sign for out-of-range years @@ -142,22 +146,22 @@ impl fmt::Debug for IsoWeek { #[cfg(test)] mod tests { - use naive::{internals, MAX_DATE, MIN_DATE}; - use Datelike; + use crate::naive::{internals, NaiveDate}; + use crate::Datelike; #[test] fn test_iso_week_extremes() { - let minweek = MIN_DATE.iso_week(); - let maxweek = MAX_DATE.iso_week(); + let minweek = NaiveDate::MIN.iso_week(); + let maxweek = NaiveDate::MAX.iso_week(); assert_eq!(minweek.year(), internals::MIN_YEAR); assert_eq!(minweek.week(), 1); assert_eq!(minweek.week0(), 0); - assert_eq!(format!("{:?}", minweek), MIN_DATE.format("%G-W%V").to_string()); + assert_eq!(format!("{:?}", minweek), NaiveDate::MIN.format("%G-W%V").to_string()); assert_eq!(maxweek.year(), internals::MAX_YEAR + 1); assert_eq!(maxweek.week(), 1); assert_eq!(maxweek.week0(), 0); - assert_eq!(format!("{:?}", maxweek), MAX_DATE.format("%G-W%V").to_string()); + assert_eq!(format!("{:?}", maxweek), NaiveDate::MAX.format("%G-W%V").to_string()); } } diff --git a/vendor/chrono/src/naive/mod.rs b/vendor/chrono/src/naive/mod.rs new file mode 100644 index 000000000..c41acba8d --- /dev/null +++ b/vendor/chrono/src/naive/mod.rs @@ -0,0 +1,39 @@ +//! Date and time types unconcerned with timezones. +//! +//! They are primarily building blocks for other types +//! (e.g. [`TimeZone`](../offset/trait.TimeZone.html)), +//! but can be also used for the simpler date and time handling. + +mod date; +pub(crate) mod datetime; +mod internals; +mod isoweek; +mod time; + +#[allow(deprecated)] +pub use self::date::{Days, NaiveDate, NaiveWeek, MAX_DATE, MIN_DATE}; +#[cfg(feature = "rustc-serialize")] +#[allow(deprecated)] +pub use self::datetime::rustc_serialize::TsSeconds; +#[allow(deprecated)] +pub use self::datetime::{NaiveDateTime, MAX_DATETIME, MIN_DATETIME}; +pub use self::isoweek::IsoWeek; +pub use self::time::NaiveTime; + +#[cfg(feature = "__internal_bench")] +#[doc(hidden)] +pub use self::internals::YearFlags as __BenchYearFlags; + +/// Serialization/Deserialization of naive types in alternate formats +/// +/// The various modules in here are intended to be used with serde's [`with` +/// annotation][1] to serialize as something other than the default [RFC +/// 3339][2] format. +/// +/// [1]: https://serde.rs/attributes.html#field-attributes +/// [2]: https://tools.ietf.org/html/rfc3339 +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +pub mod serde { + pub use super::datetime::serde::*; +} diff --git a/vendor/chrono/src/naive/time.rs b/vendor/chrono/src/naive/time/mod.rs index 1ddc9fbed..1d36583aa 100644 --- a/vendor/chrono/src/naive/time.rs +++ b/vendor/chrono/src/naive/time/mod.rs @@ -6,18 +6,27 @@ #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; use core::ops::{Add, AddAssign, Sub, SubAssign}; -use core::{fmt, hash, str}; -use oldtime::Duration as OldDuration; +use core::{fmt, str}; + +use num_integer::div_mod_floor; +#[cfg(feature = "rkyv")] +use rkyv::{Archive, Deserialize, Serialize}; -use div::div_mod_floor; #[cfg(any(feature = "alloc", feature = "std", test))] -use format::DelayedFormat; -use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; -use format::{Fixed, Item, Numeric, Pad}; -use Timelike; +use crate::format::DelayedFormat; +use crate::format::{parse, write_hundreds, ParseError, ParseResult, Parsed, StrftimeItems}; +use crate::format::{Fixed, Item, Numeric, Pad}; +use crate::oldtime::Duration as OldDuration; +use crate::Timelike; -pub const MIN_TIME: NaiveTime = NaiveTime { secs: 0, frac: 0 }; -pub const MAX_TIME: NaiveTime = NaiveTime { secs: 23 * 3600 + 59 * 60 + 59, frac: 999_999_999 }; +#[cfg(feature = "rustc-serialize")] +mod rustc_serialize; + +#[cfg(feature = "serde")] +mod serde; + +#[cfg(test)] +mod tests; /// ISO 8601 time without timezone. /// Allows for the nanosecond precision and optional leap second representation. @@ -64,16 +73,16 @@ pub const MAX_TIME: NaiveTime = NaiveTime { secs: 23 * 3600 + 59 * 60 + 59, frac /// /// All methods accepting fractional seconds will accept such values. /// -/// ~~~~ +/// ``` /// use chrono::{NaiveDate, NaiveTime, Utc, TimeZone}; /// -/// let t = NaiveTime::from_hms_milli(8, 59, 59, 1_000); +/// let t = NaiveTime::from_hms_milli_opt(8, 59, 59, 1_000).unwrap(); /// -/// let dt1 = NaiveDate::from_ymd(2015, 7, 1).and_hms_micro(8, 59, 59, 1_000_000); +/// let dt1 = NaiveDate::from_ymd_opt(2015, 7, 1).unwrap().and_hms_micro_opt(8, 59, 59, 1_000_000).unwrap(); /// -/// let dt2 = Utc.ymd(2015, 6, 30).and_hms_nano(23, 59, 59, 1_000_000_000); +/// let dt2 = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_nano_opt(23, 59, 59, 1_000_000_000).unwrap().and_local_timezone(Utc).unwrap(); /// # let _ = (t, dt1, dt2); -/// ~~~~ +/// ``` /// /// Note that the leap second can happen anytime given an appropriate time zone; /// 2015-07-01 01:23:60 would be a proper leap second if UTC+01:24 had existed. @@ -151,12 +160,12 @@ pub const MAX_TIME: NaiveTime = NaiveTime { secs: 23 * 3600 + 59 * 60 + 59, frac /// The leap second in the human-readable representation /// will be represented as the second part being 60, as required by ISO 8601. /// -/// ~~~~ -/// use chrono::{Utc, TimeZone}; +/// ``` +/// use chrono::{Utc, TimeZone, NaiveDate}; /// -/// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_000); +/// let dt = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_milli_opt(23, 59, 59, 1_000).unwrap().and_local_timezone(Utc).unwrap(); /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60Z"); -/// ~~~~ +/// ``` /// /// There are hypothetical leap seconds not on the minute boundary /// nevertheless supported by Chrono. @@ -165,25 +174,37 @@ pub const MAX_TIME: NaiveTime = NaiveTime { secs: 23 * 3600 + 59 * 60 + 59, frac /// For such cases the human-readable representation is ambiguous /// and would be read back to the next non-leap second. /// -/// ~~~~ -/// use chrono::{DateTime, Utc, TimeZone}; +/// ``` +/// use chrono::{DateTime, Utc, TimeZone, NaiveDate}; /// -/// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 56, 4, 1_000); +/// let dt = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_milli_opt(23, 56, 4, 1_000).unwrap().and_local_timezone(Utc).unwrap(); /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z"); /// -/// let dt = Utc.ymd(2015, 6, 30).and_hms(23, 56, 5); +/// let dt = Utc.with_ymd_and_hms(2015, 6, 30, 23, 56, 5).unwrap(); /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z"); /// assert_eq!(DateTime::parse_from_rfc3339("2015-06-30T23:56:05Z").unwrap(), dt); -/// ~~~~ +/// ``` /// /// Since Chrono alone cannot determine any existence of leap seconds, /// **there is absolutely no guarantee that the leap second read has actually happened**. -#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] +#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)] +#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))] pub struct NaiveTime { secs: u32, frac: u32, } +#[cfg(feature = "arbitrary")] +impl arbitrary::Arbitrary<'_> for NaiveTime { + fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<NaiveTime> { + let secs = u.int_in_range(0..=86_399)?; + let nano = u.int_in_range(0..=1_999_999_999)?; + let time = NaiveTime::from_num_seconds_from_midnight_opt(secs, nano) + .expect("Could not generate a valid chrono::NaiveTime. It looks like implementation of Arbitrary for NaiveTime is erroneous."); + Ok(time) + } +} + impl NaiveTime { /// Makes a new `NaiveTime` from hour, minute and second. /// @@ -191,18 +212,7 @@ impl NaiveTime { /// use `NaiveTime::from_hms_*` methods with a subsecond parameter instead. /// /// Panics on invalid hour, minute and/or second. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveTime, Timelike}; - /// - /// let t = NaiveTime::from_hms(23, 56, 4); - /// assert_eq!(t.hour(), 23); - /// assert_eq!(t.minute(), 56); - /// assert_eq!(t.second(), 4); - /// assert_eq!(t.nanosecond(), 0); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_hms_opt()` instead")] #[inline] pub fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTime { NaiveTime::from_hms_opt(hour, min, sec).expect("invalid time") @@ -217,7 +227,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let from_hms_opt = NaiveTime::from_hms_opt; @@ -227,7 +237,7 @@ impl NaiveTime { /// assert!(from_hms_opt(24, 0, 0).is_none()); /// assert!(from_hms_opt(23, 60, 0).is_none()); /// assert!(from_hms_opt(23, 59, 60).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> { NaiveTime::from_hms_nano_opt(hour, min, sec, 0) @@ -239,18 +249,7 @@ impl NaiveTime { /// in order to represent the [leap second](#leap-second-handling). /// /// Panics on invalid hour, minute, second and/or millisecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveTime, Timelike}; - /// - /// let t = NaiveTime::from_hms_milli(23, 56, 4, 12); - /// assert_eq!(t.hour(), 23); - /// assert_eq!(t.minute(), 56); - /// assert_eq!(t.second(), 4); - /// assert_eq!(t.nanosecond(), 12_000_000); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_hms_milli_opt()` instead")] #[inline] pub fn from_hms_milli(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTime { NaiveTime::from_hms_milli_opt(hour, min, sec, milli).expect("invalid time") @@ -265,7 +264,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let from_hmsm_opt = NaiveTime::from_hms_milli_opt; @@ -277,7 +276,7 @@ impl NaiveTime { /// assert!(from_hmsm_opt(23, 60, 0, 0).is_none()); /// assert!(from_hmsm_opt(23, 59, 60, 0).is_none()); /// assert!(from_hmsm_opt(23, 59, 59, 2_000).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> { milli @@ -291,18 +290,7 @@ impl NaiveTime { /// in order to represent the [leap second](#leap-second-handling). /// /// Panics on invalid hour, minute, second and/or microsecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveTime, Timelike}; - /// - /// let t = NaiveTime::from_hms_micro(23, 56, 4, 12_345); - /// assert_eq!(t.hour(), 23); - /// assert_eq!(t.minute(), 56); - /// assert_eq!(t.second(), 4); - /// assert_eq!(t.nanosecond(), 12_345_000); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_hms_micro_opt()` instead")] #[inline] pub fn from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> NaiveTime { NaiveTime::from_hms_micro_opt(hour, min, sec, micro).expect("invalid time") @@ -317,7 +305,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let from_hmsu_opt = NaiveTime::from_hms_micro_opt; @@ -329,7 +317,7 @@ impl NaiveTime { /// assert!(from_hmsu_opt(23, 60, 0, 0).is_none()); /// assert!(from_hmsu_opt(23, 59, 60, 0).is_none()); /// assert!(from_hmsu_opt(23, 59, 59, 2_000_000).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> { micro.checked_mul(1_000).and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano)) @@ -341,18 +329,7 @@ impl NaiveTime { /// in order to represent the [leap second](#leap-second-handling). /// /// Panics on invalid hour, minute, second and/or nanosecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveTime, Timelike}; - /// - /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); - /// assert_eq!(t.hour(), 23); - /// assert_eq!(t.minute(), 56); - /// assert_eq!(t.second(), 4); - /// assert_eq!(t.nanosecond(), 12_345_678); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_hms_nano_opt()` instead")] #[inline] pub fn from_hms_nano(hour: u32, min: u32, sec: u32, nano: u32) -> NaiveTime { NaiveTime::from_hms_nano_opt(hour, min, sec, nano).expect("invalid time") @@ -367,7 +344,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let from_hmsn_opt = NaiveTime::from_hms_nano_opt; @@ -379,14 +356,14 @@ impl NaiveTime { /// assert!(from_hmsn_opt(23, 60, 0, 0).is_none()); /// assert!(from_hmsn_opt(23, 59, 60, 0).is_none()); /// assert!(from_hmsn_opt(23, 59, 59, 2_000_000_000).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> { if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; } let secs = hour * 3600 + min * 60 + sec; - Some(NaiveTime { secs: secs, frac: nano }) + Some(NaiveTime { secs, frac: nano }) } /// Makes a new `NaiveTime` from the number of seconds since midnight and nanosecond. @@ -395,18 +372,7 @@ impl NaiveTime { /// in order to represent the [leap second](#leap-second-handling). /// /// Panics on invalid number of seconds and/or nanosecond. - /// - /// # Example - /// - /// ~~~~ - /// use chrono::{NaiveTime, Timelike}; - /// - /// let t = NaiveTime::from_num_seconds_from_midnight(86164, 12_345_678); - /// assert_eq!(t.hour(), 23); - /// assert_eq!(t.minute(), 56); - /// assert_eq!(t.second(), 4); - /// assert_eq!(t.nanosecond(), 12_345_678); - /// ~~~~ + #[deprecated(since = "0.4.23", note = "use `from_num_seconds_from_midnight_opt()` instead")] #[inline] pub fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> NaiveTime { NaiveTime::from_num_seconds_from_midnight_opt(secs, nano).expect("invalid time") @@ -421,7 +387,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let from_nsecs_opt = NaiveTime::from_num_seconds_from_midnight_opt; @@ -431,13 +397,13 @@ impl NaiveTime { /// assert!(from_nsecs_opt(86399, 1_999_999_999).is_some()); // a leap second after 23:59:59 /// assert!(from_nsecs_opt(86_400, 0).is_none()); /// assert!(from_nsecs_opt(86399, 2_000_000_000).is_none()); - /// ~~~~ + /// ``` #[inline] pub fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime> { if secs >= 86_400 || nano >= 2_000_000_000 { return None; } - Some(NaiveTime { secs: secs, frac: nano }) + Some(NaiveTime { secs, frac: nano }) } /// Parses a string with the specified format string and returns a new `NaiveTime`. @@ -446,61 +412,61 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// /// let parse_from_str = NaiveTime::parse_from_str; /// /// assert_eq!(parse_from_str("23:56:04", "%H:%M:%S"), - /// Ok(NaiveTime::from_hms(23, 56, 4))); + /// Ok(NaiveTime::from_hms_opt(23, 56, 4).unwrap())); /// assert_eq!(parse_from_str("pm012345.6789", "%p%I%M%S%.f"), - /// Ok(NaiveTime::from_hms_micro(13, 23, 45, 678_900))); - /// ~~~~ + /// Ok(NaiveTime::from_hms_micro_opt(13, 23, 45, 678_900).unwrap())); + /// ``` /// /// Date and offset is ignored for the purpose of parsing. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; /// # let parse_from_str = NaiveTime::parse_from_str; /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), - /// Ok(NaiveTime::from_hms(12, 34, 56))); - /// ~~~~ + /// Ok(NaiveTime::from_hms_opt(12, 34, 56).unwrap())); + /// ``` /// /// [Leap seconds](#leap-second-handling) are correctly handled by /// treating any time of the form `hh:mm:60` as a leap second. /// (This equally applies to the formatting, so the round trip is possible.) /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; /// # let parse_from_str = NaiveTime::parse_from_str; /// assert_eq!(parse_from_str("08:59:60.123", "%H:%M:%S%.f"), - /// Ok(NaiveTime::from_hms_milli(8, 59, 59, 1_123))); - /// ~~~~ + /// Ok(NaiveTime::from_hms_milli_opt(8, 59, 59, 1_123).unwrap())); + /// ``` /// /// Missing seconds are assumed to be zero, /// but out-of-bound times or insufficient fields are errors otherwise. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; /// # let parse_from_str = NaiveTime::parse_from_str; /// assert_eq!(parse_from_str("7:15", "%H:%M"), - /// Ok(NaiveTime::from_hms(7, 15, 0))); + /// Ok(NaiveTime::from_hms_opt(7, 15, 0).unwrap())); /// /// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err()); /// assert!(parse_from_str("12", "%H").is_err()); /// assert!(parse_from_str("17:60", "%H:%M").is_err()); /// assert!(parse_from_str("24:00:00", "%H:%M:%S").is_err()); - /// ~~~~ + /// ``` /// /// All parsed fields should be consistent to each other, otherwise it's an error. /// Here `%H` is for 24-hour clocks, unlike `%I`, /// and thus can be independently determined without AM/PM. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; /// # let parse_from_str = NaiveTime::parse_from_str; /// assert!(parse_from_str("13:07 AM", "%H:%M %p").is_err()); - /// ~~~~ + /// ``` pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime> { let mut parsed = Parsed::new(); parse(&mut parsed, s, StrftimeItems::new(fmt))?; @@ -514,8 +480,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hms = NaiveTime::from_hms; @@ -526,9 +491,7 @@ impl NaiveTime { /// (from_hms(2, 4, 5), 86_400)); /// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(-7)), /// (from_hms(20, 4, 5), -86_400)); - /// # } - /// ~~~~ - #[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] + /// ``` pub fn overflowing_add_signed(&self, mut rhs: OldDuration) -> (NaiveTime, i64) { let mut secs = self.secs; let mut frac = self.frac; @@ -548,7 +511,7 @@ impl NaiveTime { } else { frac = (i64::from(frac) + rhs.num_nanoseconds().unwrap()) as u32; debug_assert!(frac < 2_000_000_000); - return (NaiveTime { secs: secs, frac: frac }, 0); + return (NaiveTime { secs, frac }, 0); } } debug_assert!(secs <= 86_400); @@ -577,8 +540,8 @@ impl NaiveTime { frac -= 1_000_000_000; secs += 1; } - debug_assert!(-86_400 <= secs && secs < 2 * 86_400); - debug_assert!(0 <= frac && frac < 1_000_000_000); + debug_assert!((-86_400..2 * 86_400).contains(&secs)); + debug_assert!((0..1_000_000_000).contains(&frac)); if secs < 0 { secs += 86_400; @@ -587,7 +550,7 @@ impl NaiveTime { secs -= 86_400; morerhssecs += 86_400; } - debug_assert!(0 <= secs && secs < 86_400); + debug_assert!((0..86_400).contains(&secs)); (NaiveTime { secs: secs as u32, frac: frac as u32 }, morerhssecs) } @@ -599,8 +562,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hms = NaiveTime::from_hms; @@ -611,8 +573,7 @@ impl NaiveTime { /// (from_hms(10, 4, 5), 86_400)); /// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(-22)), /// (from_hms(1, 4, 5), -86_400)); - /// # } - /// ~~~~ + /// ``` #[inline] pub fn overflowing_sub_signed(&self, rhs: OldDuration) -> (NaiveTime, i64) { let (time, rhs) = self.overflowing_add_signed(-rhs); @@ -631,8 +592,7 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hmsm = NaiveTime::from_hms_milli; @@ -654,14 +614,12 @@ impl NaiveTime { /// Duration::seconds(-3600)); /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(2, 4, 6, 800)), /// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100)); - /// # } - /// ~~~~ + /// ``` /// /// Leap seconds are handled, but the subtraction assumes that /// there were no other leap seconds happened. /// - /// ~~~~ - /// # extern crate chrono; fn main() { + /// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// # let since = NaiveTime::signed_duration_since; @@ -675,8 +633,7 @@ impl NaiveTime { /// Duration::seconds(1)); /// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(2, 59, 59, 1_000)), /// Duration::seconds(61)); - /// # } - /// ~~~~ + /// ``` pub fn signed_duration_since(self, rhs: NaiveTime) -> OldDuration { // | | :leap| | | | | | | :leap| | // | | : | | | | | | | : | | @@ -695,13 +652,7 @@ impl NaiveTime { // `secs` may contain a leap second yet to be counted let adjust = match self.secs.cmp(&rhs.secs) { - Ordering::Greater => { - if rhs.frac >= 1_000_000_000 { - 1 - } else { - 0 - } - } + Ordering::Greater => i64::from(rhs.frac >= 1_000_000_000), Ordering::Equal => 0, Ordering::Less => { if self.frac >= 1_000_000_000 { @@ -723,26 +674,27 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// use chrono::format::strftime::StrftimeItems; /// /// let fmt = StrftimeItems::new("%H:%M:%S"); - /// let t = NaiveTime::from_hms(23, 56, 4); + /// let t = NaiveTime::from_hms_opt(23, 56, 4).unwrap(); /// assert_eq!(t.format_with_items(fmt.clone()).to_string(), "23:56:04"); /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04"); - /// ~~~~ + /// ``` /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; /// # use chrono::format::strftime::StrftimeItems; /// # let fmt = StrftimeItems::new("%H:%M:%S").clone(); - /// # let t = NaiveTime::from_hms(23, 56, 4); + /// # let t = NaiveTime::from_hms_opt(23, 56, 4).unwrap(); /// assert_eq!(format!("{}", t.format_with_items(fmt)), "23:56:04"); - /// ~~~~ + /// ``` #[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 @@ -768,25 +720,26 @@ impl NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::NaiveTime; /// - /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); + /// let t = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04"); /// assert_eq!(t.format("%H:%M:%S%.6f").to_string(), "23:56:04.012345"); /// assert_eq!(t.format("%-I:%M %p").to_string(), "11:56 PM"); - /// ~~~~ + /// ``` /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// - /// ~~~~ + /// ``` /// # use chrono::NaiveTime; - /// # let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); + /// # let t = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!(format!("{}", t.format("%H:%M:%S")), "23:56:04"); /// assert_eq!(format!("{}", t.format("%H:%M:%S%.6f")), "23:56:04.012345"); /// assert_eq!(format!("{}", t.format("%-I:%M %p")), "11:56 PM"); - /// ~~~~ + /// ``` #[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)) @@ -798,6 +751,10 @@ impl NaiveTime { let (hour, min) = div_mod_floor(mins, 60); (hour, min, sec) } + + /// The earliest possible `NaiveTime` + pub const MIN: Self = Self { secs: 0, frac: 0 }; + pub(super) const MAX: Self = Self { secs: 23 * 3600 + 59 * 60 + 59, frac: 999_999_999 }; } impl Timelike for NaiveTime { @@ -805,12 +762,12 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// assert_eq!(NaiveTime::from_hms(0, 0, 0).hour(), 0); - /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).hour(), 23); - /// ~~~~ + /// assert_eq!(NaiveTime::from_hms_opt(0, 0, 0).unwrap().hour(), 0); + /// assert_eq!(NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap().hour(), 23); + /// ``` #[inline] fn hour(&self) -> u32 { self.hms().0 @@ -820,12 +777,12 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// assert_eq!(NaiveTime::from_hms(0, 0, 0).minute(), 0); - /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).minute(), 56); - /// ~~~~ + /// assert_eq!(NaiveTime::from_hms_opt(0, 0, 0).unwrap().minute(), 0); + /// assert_eq!(NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap().minute(), 56); + /// ``` #[inline] fn minute(&self) -> u32 { self.hms().1 @@ -835,23 +792,23 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// assert_eq!(NaiveTime::from_hms(0, 0, 0).second(), 0); - /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).second(), 4); - /// ~~~~ + /// assert_eq!(NaiveTime::from_hms_opt(0, 0, 0).unwrap().second(), 0); + /// assert_eq!(NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap().second(), 4); + /// ``` /// /// This method never returns 60 even when it is a leap second. /// ([Why?](#leap-second-handling)) /// Use the proper [formatting method](#method.format) to get a human-readable representation. /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveTime, Timelike}; - /// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000); + /// let leap = NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap(); /// assert_eq!(leap.second(), 59); /// assert_eq!(leap.format("%H:%M:%S").to_string(), "23:59:60"); - /// ~~~~ + /// ``` #[inline] fn second(&self) -> u32 { self.hms().2 @@ -863,23 +820,23 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// assert_eq!(NaiveTime::from_hms(0, 0, 0).nanosecond(), 0); - /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).nanosecond(), 12_345_678); - /// ~~~~ + /// assert_eq!(NaiveTime::from_hms_opt(0, 0, 0).unwrap().nanosecond(), 0); + /// assert_eq!(NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap().nanosecond(), 12_345_678); + /// ``` /// /// Leap seconds may have seemingly out-of-range return values. /// You can reduce the range with `time.nanosecond() % 1_000_000_000`, or /// use the proper [formatting method](#method.format) to get a human-readable representation. /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveTime, Timelike}; - /// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000); + /// let leap = NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap(); /// assert_eq!(leap.nanosecond(), 1_000_000_000); /// assert_eq!(leap.format("%H:%M:%S%.9f").to_string(), "23:59:60.000000000"); - /// ~~~~ + /// ``` #[inline] fn nanosecond(&self) -> u32 { self.frac @@ -891,20 +848,20 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); - /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678))); + /// let dt = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); + /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano_opt(7, 56, 4, 12_345_678).unwrap())); /// assert_eq!(dt.with_hour(24), None); - /// ~~~~ + /// ``` #[inline] fn with_hour(&self, hour: u32) -> Option<NaiveTime> { if hour >= 24 { return None; } let secs = hour * 3600 + self.secs % 3600; - Some(NaiveTime { secs: secs, ..*self }) + Some(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with the minute number changed. @@ -913,20 +870,20 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); - /// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano(23, 45, 4, 12_345_678))); + /// let dt = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); + /// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano_opt(23, 45, 4, 12_345_678).unwrap())); /// assert_eq!(dt.with_minute(60), None); - /// ~~~~ + /// ``` #[inline] fn with_minute(&self, min: u32) -> Option<NaiveTime> { if min >= 60 { return None; } let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60; - Some(NaiveTime { secs: secs, ..*self }) + Some(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with the second number changed. @@ -937,20 +894,20 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); - /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678))); + /// let dt = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); + /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano_opt(23, 56, 17, 12_345_678).unwrap())); /// assert_eq!(dt.with_second(60), None); - /// ~~~~ + /// ``` #[inline] fn with_second(&self, sec: u32) -> Option<NaiveTime> { if sec >= 60 { return None; } let secs = self.secs / 60 * 60 + sec; - Some(NaiveTime { secs: secs, ..*self }) + Some(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed. @@ -961,26 +918,26 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); + /// let dt = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!(dt.with_nanosecond(333_333_333), - /// Some(NaiveTime::from_hms_nano(23, 56, 4, 333_333_333))); + /// Some(NaiveTime::from_hms_nano_opt(23, 56, 4, 333_333_333).unwrap())); /// assert_eq!(dt.with_nanosecond(2_000_000_000), None); - /// ~~~~ + /// ``` /// /// Leap seconds can theoretically follow *any* whole second. /// The following would be a proper leap second at the time zone offset of UTC-00:03:57 /// (there are several historical examples comparable to this "non-sense" offset), /// and therefore is allowed. /// - /// ~~~~ + /// ``` /// # use chrono::{NaiveTime, Timelike}; - /// # let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); + /// # let dt = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!(dt.with_nanosecond(1_333_333_333), - /// Some(NaiveTime::from_hms_nano(23, 56, 4, 1_333_333_333))); - /// ~~~~ + /// Some(NaiveTime::from_hms_nano_opt(23, 56, 4, 1_333_333_333).unwrap())); + /// ``` #[inline] fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> { if nano >= 2_000_000_000 { @@ -993,33 +950,22 @@ impl Timelike for NaiveTime { /// /// # Example /// - /// ~~~~ + /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// assert_eq!(NaiveTime::from_hms(1, 2, 3).num_seconds_from_midnight(), + /// assert_eq!(NaiveTime::from_hms_opt(1, 2, 3).unwrap().num_seconds_from_midnight(), /// 3723); - /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).num_seconds_from_midnight(), + /// assert_eq!(NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap().num_seconds_from_midnight(), /// 86164); - /// assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).num_seconds_from_midnight(), + /// assert_eq!(NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap().num_seconds_from_midnight(), /// 86399); - /// ~~~~ + /// ``` #[inline] fn num_seconds_from_midnight(&self) -> u32 { self.secs // do not repeat the calculation! } } -/// `NaiveTime` can be used as a key to the hash maps (in principle). -/// -/// Practically this also takes account of fractional seconds, so it is not recommended. -/// (For the obvious reason this also distinguishes leap seconds from non-leap seconds.) -impl hash::Hash for NaiveTime { - fn hash<H: hash::Hasher>(&self, state: &mut H) { - self.secs.hash(state); - self.frac.hash(state); - } -} - /// An addition of `Duration` to `NaiveTime` wraps around and never overflows or underflows. /// In particular the addition ignores integral number of days. /// @@ -1030,8 +976,7 @@ impl hash::Hash for NaiveTime { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hmsm = NaiveTime::from_hms_milli; @@ -1044,25 +989,21 @@ impl hash::Hash for NaiveTime { /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::milliseconds(80), from_hmsm(3, 5, 7, 80)); /// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(280), from_hmsm(3, 5, 8, 230)); /// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(-980), from_hmsm(3, 5, 6, 970)); -/// # } -/// ~~~~ +/// ``` /// /// The addition wraps around. /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(22*60*60), from_hmsm(1, 5, 7, 0)); /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-8*60*60), from_hmsm(19, 5, 7, 0)); /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::days(800), from_hmsm(3, 5, 7, 0)); -/// # } -/// ~~~~ +/// ``` /// /// Leap seconds are handled, but the addition assumes that it is the only leap second happened. /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// let leap = from_hmsm(3, 5, 59, 1_300); @@ -1073,8 +1014,7 @@ impl hash::Hash for NaiveTime { /// assert_eq!(leap + Duration::seconds(10), from_hmsm(3, 6, 9, 300)); /// assert_eq!(leap + Duration::seconds(-10), from_hmsm(3, 5, 50, 300)); /// assert_eq!(leap + Duration::days(1), from_hmsm(3, 5, 59, 300)); -/// # } -/// ~~~~ +/// ``` impl Add<OldDuration> for NaiveTime { type Output = NaiveTime; @@ -1102,8 +1042,7 @@ impl AddAssign<OldDuration> for NaiveTime { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hmsm = NaiveTime::from_hms_milli; @@ -1114,24 +1053,20 @@ impl AddAssign<OldDuration> for NaiveTime { /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(2*60*60 + 6*60), from_hmsm(0, 59, 7, 0)); /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::milliseconds(80), from_hmsm(3, 5, 6, 920)); /// assert_eq!(from_hmsm(3, 5, 7, 950) - Duration::milliseconds(280), from_hmsm(3, 5, 7, 670)); -/// # } -/// ~~~~ +/// ``` /// /// The subtraction wraps around. /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(8*60*60), from_hmsm(19, 5, 7, 0)); /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::days(800), from_hmsm(3, 5, 7, 0)); -/// # } -/// ~~~~ +/// ``` /// /// Leap seconds are handled, but the subtraction assumes that it is the only leap second happened. /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// let leap = from_hmsm(3, 5, 59, 1_300); @@ -1140,8 +1075,7 @@ impl AddAssign<OldDuration> for NaiveTime { /// assert_eq!(leap - Duration::milliseconds(500), from_hmsm(3, 5, 59, 800)); /// assert_eq!(leap - Duration::seconds(60), from_hmsm(3, 5, 0, 300)); /// assert_eq!(leap - Duration::days(1), from_hmsm(3, 6, 0, 300)); -/// # } -/// ~~~~ +/// ``` impl Sub<OldDuration> for NaiveTime { type Output = NaiveTime; @@ -1173,8 +1107,7 @@ impl SubAssign<OldDuration> for NaiveTime { /// /// # Example /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// use chrono::{Duration, NaiveTime}; /// /// let from_hmsm = NaiveTime::from_hms_milli; @@ -1188,14 +1121,12 @@ impl SubAssign<OldDuration> for NaiveTime { /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(4, 5, 7, 900), Duration::seconds(-3600)); /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(2, 4, 6, 800), /// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100)); -/// # } -/// ~~~~ +/// ``` /// /// Leap seconds are handled, but the subtraction assumes that /// there were no other leap seconds happened. /// -/// ~~~~ -/// # extern crate chrono; fn main() { +/// ``` /// # use chrono::{Duration, NaiveTime}; /// # let from_hmsm = NaiveTime::from_hms_milli; /// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 59, 0), Duration::seconds(1)); @@ -1205,8 +1136,7 @@ impl SubAssign<OldDuration> for NaiveTime { /// assert_eq!(from_hmsm(3, 0, 0, 0) - from_hmsm(2, 59, 59, 1_000), Duration::seconds(1)); /// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(2, 59, 59, 1_000), /// Duration::seconds(61)); -/// # } -/// ~~~~ +/// ``` impl Sub<NaiveTime> for NaiveTime { type Output = OldDuration; @@ -1229,21 +1159,21 @@ impl Sub<NaiveTime> for NaiveTime { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveTime; /// -/// assert_eq!(format!("{:?}", NaiveTime::from_hms(23, 56, 4)), "23:56:04"); -/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012"); -/// assert_eq!(format!("{:?}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234"); -/// assert_eq!(format!("{:?}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_opt(23, 56, 4).unwrap()), "23:56:04"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli_opt(23, 56, 4, 12).unwrap()), "23:56:04.012"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_micro_opt(23, 56, 4, 1234).unwrap()), "23:56:04.001234"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_nano_opt(23, 56, 4, 123456).unwrap()), "23:56:04.000123456"); +/// ``` /// /// Leap seconds may also be used. /// -/// ~~~~ +/// ``` /// # use chrono::NaiveTime; -/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500"); -/// ~~~~ +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli_opt(6, 59, 59, 1_500).unwrap()), "06:59:60.500"); +/// ``` impl fmt::Debug for NaiveTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (hour, min, sec) = self.hms(); @@ -1253,7 +1183,13 @@ impl fmt::Debug for NaiveTime { (sec, self.frac) }; - write!(f, "{:02}:{:02}:{:02}", hour, min, sec)?; + use core::fmt::Write; + write_hundreds(f, hour as u8)?; + f.write_char(':')?; + write_hundreds(f, min as u8)?; + f.write_char(':')?; + write_hundreds(f, sec as u8)?; + if nano == 0 { Ok(()) } else if nano % 1_000_000 == 0 { @@ -1279,21 +1215,21 @@ impl fmt::Debug for NaiveTime { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveTime; /// -/// assert_eq!(format!("{}", NaiveTime::from_hms(23, 56, 4)), "23:56:04"); -/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012"); -/// assert_eq!(format!("{}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234"); -/// assert_eq!(format!("{}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456"); -/// ~~~~ +/// assert_eq!(format!("{}", NaiveTime::from_hms_opt(23, 56, 4).unwrap()), "23:56:04"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_milli_opt(23, 56, 4, 12).unwrap()), "23:56:04.012"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_micro_opt(23, 56, 4, 1234).unwrap()), "23:56:04.001234"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_nano_opt(23, 56, 4, 123456).unwrap()), "23:56:04.000123456"); +/// ``` /// /// Leap seconds may also be used. /// -/// ~~~~ +/// ``` /// # use chrono::NaiveTime; -/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500"); -/// ~~~~ +/// assert_eq!(format!("{}", NaiveTime::from_hms_milli_opt(6, 59, 59, 1_500).unwrap()), "06:59:60.500"); +/// ``` impl fmt::Display for NaiveTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) @@ -1305,25 +1241,25 @@ impl fmt::Display for NaiveTime { /// /// # Example /// -/// ~~~~ +/// ``` /// use chrono::NaiveTime; /// -/// let t = NaiveTime::from_hms(23, 56, 4); +/// let t = NaiveTime::from_hms_opt(23, 56, 4).unwrap(); /// assert_eq!("23:56:04".parse::<NaiveTime>(), Ok(t)); /// -/// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); +/// let t = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!("23:56:4.012345678".parse::<NaiveTime>(), Ok(t)); /// -/// let t = NaiveTime::from_hms_nano(23, 59, 59, 1_234_567_890); // leap second +/// let t = NaiveTime::from_hms_nano_opt(23, 59, 59, 1_234_567_890).unwrap(); // leap second /// assert_eq!("23:59:60.23456789".parse::<NaiveTime>(), Ok(t)); /// /// assert!("foo".parse::<NaiveTime>().is_err()); -/// ~~~~ +/// ``` impl str::FromStr for NaiveTime { type Err = ParseError; fn from_str(s: &str) -> ParseResult<NaiveTime> { - const ITEMS: &'static [Item<'static>] = &[ + const ITEMS: &[Item<'static>] = &[ Item::Numeric(Numeric::Hour, Pad::Zero), Item::Space(""), Item::Literal(":"), @@ -1341,33 +1277,58 @@ impl str::FromStr for NaiveTime { } } +/// The default value for a NaiveTime is midnight, 00:00:00 exactly. +/// +/// # Example +/// +/// ```rust +/// use chrono::NaiveTime; +/// +/// let default_time = NaiveTime::default(); +/// assert_eq!(default_time, NaiveTime::from_hms_opt(0, 0, 0).unwrap()); +/// ``` +impl Default for NaiveTime { + fn default() -> Self { + NaiveTime::from_hms_opt(0, 0, 0).unwrap() + } +} + #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] fn test_encodable_json<F, E>(to_string: F) where F: Fn(&NaiveTime) -> Result<String, E>, E: ::std::fmt::Debug, { - assert_eq!(to_string(&NaiveTime::from_hms(0, 0, 0)).ok(), Some(r#""00:00:00""#.into())); assert_eq!( - to_string(&NaiveTime::from_hms_milli(0, 0, 0, 950)).ok(), + to_string(&NaiveTime::from_hms_opt(0, 0, 0).unwrap()).ok(), + Some(r#""00:00:00""#.into()) + ); + assert_eq!( + to_string(&NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()).ok(), Some(r#""00:00:00.950""#.into()) ); assert_eq!( - to_string(&NaiveTime::from_hms_milli(0, 0, 59, 1_000)).ok(), + to_string(&NaiveTime::from_hms_milli_opt(0, 0, 59, 1_000).unwrap()).ok(), Some(r#""00:00:60""#.into()) ); - assert_eq!(to_string(&NaiveTime::from_hms(0, 1, 2)).ok(), Some(r#""00:01:02""#.into())); assert_eq!( - to_string(&NaiveTime::from_hms_nano(3, 5, 7, 98765432)).ok(), + to_string(&NaiveTime::from_hms_opt(0, 1, 2).unwrap()).ok(), + Some(r#""00:01:02""#.into()) + ); + assert_eq!( + to_string(&NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap()).ok(), Some(r#""03:05:07.098765432""#.into()) ); - assert_eq!(to_string(&NaiveTime::from_hms(7, 8, 9)).ok(), Some(r#""07:08:09""#.into())); assert_eq!( - to_string(&NaiveTime::from_hms_micro(12, 34, 56, 789)).ok(), + to_string(&NaiveTime::from_hms_opt(7, 8, 9).unwrap()).ok(), + Some(r#""07:08:09""#.into()) + ); + assert_eq!( + to_string(&NaiveTime::from_hms_micro_opt(12, 34, 56, 789).unwrap()).ok(), Some(r#""12:34:56.000789""#.into()) ); assert_eq!( - to_string(&NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)).ok(), + to_string(&NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()).ok(), Some(r#""23:59:60.999999999""#.into()) ); } @@ -1378,28 +1339,37 @@ where F: Fn(&str) -> Result<NaiveTime, E>, E: ::std::fmt::Debug, { - assert_eq!(from_str(r#""00:00:00""#).ok(), Some(NaiveTime::from_hms(0, 0, 0))); - assert_eq!(from_str(r#""0:0:0""#).ok(), Some(NaiveTime::from_hms(0, 0, 0))); - assert_eq!(from_str(r#""00:00:00.950""#).ok(), Some(NaiveTime::from_hms_milli(0, 0, 0, 950))); - assert_eq!(from_str(r#""0:0:0.95""#).ok(), Some(NaiveTime::from_hms_milli(0, 0, 0, 950))); - assert_eq!(from_str(r#""00:00:60""#).ok(), Some(NaiveTime::from_hms_milli(0, 0, 59, 1_000))); - assert_eq!(from_str(r#""00:01:02""#).ok(), Some(NaiveTime::from_hms(0, 1, 2))); + assert_eq!(from_str(r#""00:00:00""#).ok(), Some(NaiveTime::from_hms_opt(0, 0, 0).unwrap())); + assert_eq!(from_str(r#""0:0:0""#).ok(), Some(NaiveTime::from_hms_opt(0, 0, 0).unwrap())); + assert_eq!( + from_str(r#""00:00:00.950""#).ok(), + Some(NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()) + ); + assert_eq!( + from_str(r#""0:0:0.95""#).ok(), + Some(NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()) + ); + assert_eq!( + from_str(r#""00:00:60""#).ok(), + Some(NaiveTime::from_hms_milli_opt(0, 0, 59, 1_000).unwrap()) + ); + assert_eq!(from_str(r#""00:01:02""#).ok(), Some(NaiveTime::from_hms_opt(0, 1, 2).unwrap())); assert_eq!( from_str(r#""03:05:07.098765432""#).ok(), - Some(NaiveTime::from_hms_nano(3, 5, 7, 98765432)) + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap()) ); - assert_eq!(from_str(r#""07:08:09""#).ok(), Some(NaiveTime::from_hms(7, 8, 9))); + assert_eq!(from_str(r#""07:08:09""#).ok(), Some(NaiveTime::from_hms_opt(7, 8, 9).unwrap())); assert_eq!( from_str(r#""12:34:56.000789""#).ok(), - Some(NaiveTime::from_hms_micro(12, 34, 56, 789)) + Some(NaiveTime::from_hms_micro_opt(12, 34, 56, 789).unwrap()) ); assert_eq!( from_str(r#""23:59:60.999999999""#).ok(), - Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)) + Some(NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) ); assert_eq!( from_str(r#""23:59:60.9999999999997""#).ok(), // excess digits are ignored - Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)) + Some(NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) ); // bad formats @@ -1418,397 +1388,3 @@ where assert!(from_str(r#"{"secs":0,"frac":0}"#).is_err()); assert!(from_str(r#"null"#).is_err()); } - -#[cfg(feature = "rustc-serialize")] -mod rustc_serialize { - use super::NaiveTime; - use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; - - impl Encodable for NaiveTime { - fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { - format!("{:?}", self).encode(s) - } - } - - impl Decodable for NaiveTime { - fn decode<D: Decoder>(d: &mut D) -> Result<NaiveTime, D::Error> { - d.read_str()?.parse().map_err(|_| d.error("invalid time")) - } - } - - #[cfg(test)] - use rustc_serialize::json; - - #[test] - fn test_encodable() { - super::test_encodable_json(json::encode); - } - - #[test] - fn test_decodable() { - super::test_decodable_json(json::decode); - } -} - -#[cfg(feature = "serde")] -mod serde { - use super::NaiveTime; - use core::fmt; - use serdelib::{de, ser}; - - // TODO not very optimized for space (binary formats would want something better) - // TODO round-trip for general leap seconds (not just those with second = 60) - - impl ser::Serialize for NaiveTime { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: ser::Serializer, - { - serializer.collect_str(&self) - } - } - - struct NaiveTimeVisitor; - - impl<'de> de::Visitor<'de> for NaiveTimeVisitor { - type Value = NaiveTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a formatted time string") - } - - fn visit_str<E>(self, value: &str) -> Result<NaiveTime, E> - where - E: de::Error, - { - value.parse().map_err(E::custom) - } - } - - impl<'de> de::Deserialize<'de> for NaiveTime { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: de::Deserializer<'de>, - { - deserializer.deserialize_str(NaiveTimeVisitor) - } - } - - #[cfg(test)] - extern crate bincode; - #[cfg(test)] - extern crate serde_json; - - #[test] - fn test_serde_serialize() { - super::test_encodable_json(self::serde_json::to_string); - } - - #[test] - fn test_serde_deserialize() { - super::test_decodable_json(|input| self::serde_json::from_str(&input)); - } - - #[test] - fn test_serde_bincode() { - // Bincode is relevant to test separately from JSON because - // it is not self-describing. - use self::bincode::{deserialize, serialize, Infinite}; - - let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432); - let encoded = serialize(&t, Infinite).unwrap(); - let decoded: NaiveTime = deserialize(&encoded).unwrap(); - assert_eq!(t, decoded); - } -} - -#[cfg(test)] -mod tests { - use super::NaiveTime; - use oldtime::Duration; - use std::u32; - use Timelike; - - #[test] - fn test_time_from_hms_milli() { - assert_eq!( - NaiveTime::from_hms_milli_opt(3, 5, 7, 0), - Some(NaiveTime::from_hms_nano(3, 5, 7, 0)) - ); - assert_eq!( - NaiveTime::from_hms_milli_opt(3, 5, 7, 777), - Some(NaiveTime::from_hms_nano(3, 5, 7, 777_000_000)) - ); - assert_eq!( - NaiveTime::from_hms_milli_opt(3, 5, 7, 1_999), - Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_000_000)) - ); - assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 2_000), None); - assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 5_000), None); // overflow check - assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, u32::MAX), None); - } - - #[test] - fn test_time_from_hms_micro() { - assert_eq!( - NaiveTime::from_hms_micro_opt(3, 5, 7, 0), - Some(NaiveTime::from_hms_nano(3, 5, 7, 0)) - ); - assert_eq!( - NaiveTime::from_hms_micro_opt(3, 5, 7, 333), - Some(NaiveTime::from_hms_nano(3, 5, 7, 333_000)) - ); - assert_eq!( - NaiveTime::from_hms_micro_opt(3, 5, 7, 777_777), - Some(NaiveTime::from_hms_nano(3, 5, 7, 777_777_000)) - ); - assert_eq!( - NaiveTime::from_hms_micro_opt(3, 5, 7, 1_999_999), - Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_999_000)) - ); - assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 2_000_000), None); - assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 5_000_000), None); // overflow check - assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, u32::MAX), None); - } - - #[test] - fn test_time_hms() { - assert_eq!(NaiveTime::from_hms(3, 5, 7).hour(), 3); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(0), Some(NaiveTime::from_hms(0, 5, 7))); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(23), Some(NaiveTime::from_hms(23, 5, 7))); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(24), None); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(u32::MAX), None); - - assert_eq!(NaiveTime::from_hms(3, 5, 7).minute(), 5); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(0), Some(NaiveTime::from_hms(3, 0, 7))); - assert_eq!( - NaiveTime::from_hms(3, 5, 7).with_minute(59), - Some(NaiveTime::from_hms(3, 59, 7)) - ); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(60), None); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(u32::MAX), None); - - assert_eq!(NaiveTime::from_hms(3, 5, 7).second(), 7); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(0), Some(NaiveTime::from_hms(3, 5, 0))); - assert_eq!( - NaiveTime::from_hms(3, 5, 7).with_second(59), - Some(NaiveTime::from_hms(3, 5, 59)) - ); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(60), None); - assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(u32::MAX), None); - } - - #[test] - fn test_time_add() { - macro_rules! check { - ($lhs:expr, $rhs:expr, $sum:expr) => {{ - assert_eq!($lhs + $rhs, $sum); - //assert_eq!($rhs + $lhs, $sum); - }}; - } - - let hmsm = |h, m, s, mi| NaiveTime::from_hms_milli(h, m, s, mi); - - check!(hmsm(3, 5, 7, 900), Duration::zero(), hmsm(3, 5, 7, 900)); - check!(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-1800), hmsm(3, 5, 6, 500)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-800), hmsm(3, 5, 7, 500)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-100), hmsm(3, 5, 7, 1_200)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(100), hmsm(3, 5, 7, 1_400)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100)); - check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(1800), hmsm(3, 5, 9, 100)); - check!(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap - check!(hmsm(3, 5, 7, 900), Duration::seconds(-86399), hmsm(3, 5, 8, 900)); - check!(hmsm(3, 5, 7, 900), Duration::days(12345), hmsm(3, 5, 7, 900)); - check!(hmsm(3, 5, 7, 1_300), Duration::days(1), hmsm(3, 5, 7, 300)); - check!(hmsm(3, 5, 7, 1_300), Duration::days(-1), hmsm(3, 5, 8, 300)); - - // regression tests for #37 - check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-990), hmsm(23, 59, 59, 10)); - check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-9990), hmsm(23, 59, 50, 10)); - } - - #[test] - fn test_time_overflowing_add() { - let hmsm = NaiveTime::from_hms_milli; - - assert_eq!( - hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(11)), - (hmsm(14, 4, 5, 678), 0) - ); - assert_eq!( - hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(23)), - (hmsm(2, 4, 5, 678), 86_400) - ); - assert_eq!( - hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(-7)), - (hmsm(20, 4, 5, 678), -86_400) - ); - - // overflowing_add_signed with leap seconds may be counter-intuitive - assert_eq!( - hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(1)), - (hmsm(3, 4, 5, 678), 86_400) - ); - assert_eq!( - hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(-1)), - (hmsm(3, 4, 6, 678), -86_400) - ); - } - - #[test] - fn test_time_addassignment() { - let hms = NaiveTime::from_hms; - let mut time = hms(12, 12, 12); - time += Duration::hours(10); - assert_eq!(time, hms(22, 12, 12)); - time += Duration::hours(10); - assert_eq!(time, hms(8, 12, 12)); - } - - #[test] - fn test_time_subassignment() { - let hms = NaiveTime::from_hms; - let mut time = hms(12, 12, 12); - time -= Duration::hours(10); - assert_eq!(time, hms(2, 12, 12)); - time -= Duration::hours(10); - assert_eq!(time, hms(16, 12, 12)); - } - - #[test] - fn test_time_sub() { - macro_rules! check { - ($lhs:expr, $rhs:expr, $diff:expr) => {{ - // `time1 - time2 = duration` is equivalent to `time2 - time1 = -duration` - assert_eq!($lhs.signed_duration_since($rhs), $diff); - assert_eq!($rhs.signed_duration_since($lhs), -$diff); - }}; - } - - let hmsm = |h, m, s, mi| NaiveTime::from_hms_milli(h, m, s, mi); - - check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Duration::zero()); - check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300)); - check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1)); - check!( - hmsm(3, 5, 7, 200), - hmsm(2, 4, 6, 300), - Duration::seconds(3600 + 60) + Duration::milliseconds(900) - ); - - // treats the leap second as if it coincides with the prior non-leap second, - // as required by `time1 - time2 = duration` and `time2 - time1 = -duration` equivalence. - check!(hmsm(3, 5, 7, 200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(400)); - check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(1400)); - check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 800), Duration::milliseconds(1400)); - - // additional equality: `time1 + duration = time2` is equivalent to - // `time2 - time1 = duration` IF AND ONLY IF `time2` represents a non-leap second. - assert_eq!(hmsm(3, 5, 6, 800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200)); - assert_eq!(hmsm(3, 5, 6, 1_800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200)); - } - - #[test] - fn test_time_fmt() { - assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 999)), "23:59:59.999"); - assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_000)), "23:59:60"); - assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_001)), "23:59:60.001"); - assert_eq!(format!("{}", NaiveTime::from_hms_micro(0, 0, 0, 43210)), "00:00:00.043210"); - assert_eq!(format!("{}", NaiveTime::from_hms_nano(0, 0, 0, 6543210)), "00:00:00.006543210"); - - // the format specifier should have no effect on `NaiveTime` - assert_eq!(format!("{:30}", NaiveTime::from_hms_milli(3, 5, 7, 9)), "03:05:07.009"); - } - - #[test] - fn test_date_from_str() { - // valid cases - let valid = [ - "0:0:0", - "0:0:0.0000000", - "0:0:0.0000003", - " 4 : 3 : 2.1 ", - " 09:08:07 ", - " 9:8:07 ", - "23:59:60.373929310237", - ]; - for &s in &valid { - let d = match s.parse::<NaiveTime>() { - Ok(d) => d, - Err(e) => panic!("parsing `{}` has failed: {}", s, e), - }; - let s_ = format!("{:?}", d); - // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same - let d_ = match s_.parse::<NaiveTime>() { - Ok(d) => d, - Err(e) => { - panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}", s, d, e) - } - }; - assert!( - d == d_, - "`{}` is parsed into `{:?}`, but reparsed result \ - `{:?}` does not match", - s, - d, - d_ - ); - } - - // some invalid cases - // since `ParseErrorKind` is private, all we can do is to check if there was an error - assert!("".parse::<NaiveTime>().is_err()); - assert!("x".parse::<NaiveTime>().is_err()); - assert!("15".parse::<NaiveTime>().is_err()); - assert!("15:8".parse::<NaiveTime>().is_err()); - assert!("15:8:x".parse::<NaiveTime>().is_err()); - assert!("15:8:9x".parse::<NaiveTime>().is_err()); - assert!("23:59:61".parse::<NaiveTime>().is_err()); - assert!("12:34:56.x".parse::<NaiveTime>().is_err()); - assert!("12:34:56. 0".parse::<NaiveTime>().is_err()); - } - - #[test] - fn test_time_parse_from_str() { - let hms = |h, m, s| NaiveTime::from_hms(h, m, s); - assert_eq!( - NaiveTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), - Ok(hms(12, 34, 56)) - ); // ignore date and offset - assert_eq!(NaiveTime::parse_from_str("PM 12:59", "%P %H:%M"), Ok(hms(12, 59, 0))); - assert!(NaiveTime::parse_from_str("12:3456", "%H:%M:%S").is_err()); - } - - #[test] - fn test_time_format() { - let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432); - assert_eq!(t.format("%H,%k,%I,%l,%P,%p").to_string(), "03, 3,03, 3,am,AM"); - assert_eq!(t.format("%M").to_string(), "05"); - assert_eq!(t.format("%S,%f,%.f").to_string(), "07,098765432,.098765432"); - assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".098,.098765,.098765432"); - assert_eq!(t.format("%R").to_string(), "03:05"); - assert_eq!(t.format("%T,%X").to_string(), "03:05:07,03:05:07"); - assert_eq!(t.format("%r").to_string(), "03:05:07 AM"); - assert_eq!(t.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); - - let t = NaiveTime::from_hms_micro(3, 5, 7, 432100); - assert_eq!(t.format("%S,%f,%.f").to_string(), "07,432100000,.432100"); - assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".432,.432100,.432100000"); - - let t = NaiveTime::from_hms_milli(3, 5, 7, 210); - assert_eq!(t.format("%S,%f,%.f").to_string(), "07,210000000,.210"); - assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".210,.210000,.210000000"); - - let t = NaiveTime::from_hms(3, 5, 7); - assert_eq!(t.format("%S,%f,%.f").to_string(), "07,000000000,"); - assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".000,.000000,.000000000"); - - // corner cases - assert_eq!(NaiveTime::from_hms(13, 57, 9).format("%r").to_string(), "01:57:09 PM"); - assert_eq!( - NaiveTime::from_hms_milli(23, 59, 59, 1_000).format("%X").to_string(), - "23:59:60" - ); - } -} diff --git a/vendor/chrono/src/naive/time/rustc_serialize.rs b/vendor/chrono/src/naive/time/rustc_serialize.rs new file mode 100644 index 000000000..9eaf68219 --- /dev/null +++ b/vendor/chrono/src/naive/time/rustc_serialize.rs @@ -0,0 +1,29 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))] + +use super::NaiveTime; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; + +impl Encodable for NaiveTime { + fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + format!("{:?}", self).encode(s) + } +} + +impl Decodable for NaiveTime { + fn decode<D: Decoder>(d: &mut D) -> Result<NaiveTime, D::Error> { + d.read_str()?.parse().map_err(|_| d.error("invalid time")) + } +} + +#[cfg(test)] +use rustc_serialize::json; + +#[test] +fn test_encodable() { + super::test_encodable_json(json::encode); +} + +#[test] +fn test_decodable() { + super::test_decodable_json(json::decode); +} diff --git a/vendor/chrono/src/naive/time/serde.rs b/vendor/chrono/src/naive/time/serde.rs new file mode 100644 index 000000000..c7394fb57 --- /dev/null +++ b/vendor/chrono/src/naive/time/serde.rs @@ -0,0 +1,65 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "serde")))] + +use super::NaiveTime; +use core::fmt; +use serde::{de, ser}; + +// TODO not very optimized for space (binary formats would want something better) +// TODO round-trip for general leap seconds (not just those with second = 60) + +impl ser::Serialize for NaiveTime { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + serializer.collect_str(&self) + } +} + +struct NaiveTimeVisitor; + +impl<'de> de::Visitor<'de> for NaiveTimeVisitor { + type Value = NaiveTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a formatted time string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + value.parse().map_err(E::custom) + } +} + +impl<'de> de::Deserialize<'de> for NaiveTime { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_str(NaiveTimeVisitor) + } +} + +#[test] +fn test_serde_serialize() { + super::test_encodable_json(serde_json::to_string); +} + +#[test] +fn test_serde_deserialize() { + super::test_decodable_json(|input| serde_json::from_str(input)); +} + +#[test] +fn test_serde_bincode() { + // Bincode is relevant to test separately from JSON because + // it is not self-describing. + use bincode::{deserialize, serialize}; + + let t = NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap(); + let encoded = serialize(&t).unwrap(); + let decoded: NaiveTime = deserialize(&encoded).unwrap(); + assert_eq!(t, decoded); +} diff --git a/vendor/chrono/src/naive/time/tests.rs b/vendor/chrono/src/naive/time/tests.rs new file mode 100644 index 000000000..62c46a247 --- /dev/null +++ b/vendor/chrono/src/naive/time/tests.rs @@ -0,0 +1,317 @@ +use super::NaiveTime; +use crate::oldtime::Duration; +use crate::Timelike; +use std::u32; + +#[test] +fn test_time_from_hms_milli() { + assert_eq!( + NaiveTime::from_hms_milli_opt(3, 5, 7, 0), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 0).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_milli_opt(3, 5, 7, 777), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 777_000_000).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_milli_opt(3, 5, 7, 1_999), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 1_999_000_000).unwrap()) + ); + assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 2_000), None); + assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 5_000), None); // overflow check + assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, u32::MAX), None); +} + +#[test] +fn test_time_from_hms_micro() { + assert_eq!( + NaiveTime::from_hms_micro_opt(3, 5, 7, 0), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 0).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_micro_opt(3, 5, 7, 333), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 333_000).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_micro_opt(3, 5, 7, 777_777), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 777_777_000).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_micro_opt(3, 5, 7, 1_999_999), + Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 1_999_999_000).unwrap()) + ); + assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 2_000_000), None); + assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 5_000_000), None); // overflow check + assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, u32::MAX), None); +} + +#[test] +fn test_time_hms() { + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().hour(), 3); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_hour(0), + Some(NaiveTime::from_hms_opt(0, 5, 7).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_hour(23), + Some(NaiveTime::from_hms_opt(23, 5, 7).unwrap()) + ); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_hour(24), None); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_hour(u32::MAX), None); + + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().minute(), 5); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_minute(0), + Some(NaiveTime::from_hms_opt(3, 0, 7).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_minute(59), + Some(NaiveTime::from_hms_opt(3, 59, 7).unwrap()) + ); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_minute(60), None); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_minute(u32::MAX), None); + + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().second(), 7); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_second(0), + Some(NaiveTime::from_hms_opt(3, 5, 0).unwrap()) + ); + assert_eq!( + NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_second(59), + Some(NaiveTime::from_hms_opt(3, 5, 59).unwrap()) + ); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_second(60), None); + assert_eq!(NaiveTime::from_hms_opt(3, 5, 7).unwrap().with_second(u32::MAX), None); +} + +#[test] +fn test_time_add() { + macro_rules! check { + ($lhs:expr, $rhs:expr, $sum:expr) => {{ + assert_eq!($lhs + $rhs, $sum); + //assert_eq!($rhs + $lhs, $sum); + }}; + } + + let hmsm = |h, m, s, ms| NaiveTime::from_hms_milli_opt(h, m, s, ms).unwrap(); + + check!(hmsm(3, 5, 7, 900), Duration::zero(), hmsm(3, 5, 7, 900)); + check!(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-1800), hmsm(3, 5, 6, 500)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-800), hmsm(3, 5, 7, 500)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-100), hmsm(3, 5, 7, 1_200)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(100), hmsm(3, 5, 7, 1_400)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100)); + check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(1800), hmsm(3, 5, 9, 100)); + check!(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap + check!(hmsm(3, 5, 7, 900), Duration::seconds(-86399), hmsm(3, 5, 8, 900)); + check!(hmsm(3, 5, 7, 900), Duration::days(12345), hmsm(3, 5, 7, 900)); + check!(hmsm(3, 5, 7, 1_300), Duration::days(1), hmsm(3, 5, 7, 300)); + check!(hmsm(3, 5, 7, 1_300), Duration::days(-1), hmsm(3, 5, 8, 300)); + + // regression tests for #37 + check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-990), hmsm(23, 59, 59, 10)); + check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-9990), hmsm(23, 59, 50, 10)); +} + +#[test] +fn test_time_overflowing_add() { + let hmsm = |h, m, s, ms| NaiveTime::from_hms_milli_opt(h, m, s, ms).unwrap(); + + assert_eq!( + hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(11)), + (hmsm(14, 4, 5, 678), 0) + ); + assert_eq!( + hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(23)), + (hmsm(2, 4, 5, 678), 86_400) + ); + assert_eq!( + hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(-7)), + (hmsm(20, 4, 5, 678), -86_400) + ); + + // overflowing_add_signed with leap seconds may be counter-intuitive + assert_eq!( + hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(1)), + (hmsm(3, 4, 5, 678), 86_400) + ); + assert_eq!( + hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(-1)), + (hmsm(3, 4, 6, 678), -86_400) + ); +} + +#[test] +fn test_time_addassignment() { + let hms = |h, m, s| NaiveTime::from_hms_opt(h, m, s).unwrap(); + let mut time = hms(12, 12, 12); + time += Duration::hours(10); + assert_eq!(time, hms(22, 12, 12)); + time += Duration::hours(10); + assert_eq!(time, hms(8, 12, 12)); +} + +#[test] +fn test_time_subassignment() { + let hms = |h, m, s| NaiveTime::from_hms_opt(h, m, s).unwrap(); + let mut time = hms(12, 12, 12); + time -= Duration::hours(10); + assert_eq!(time, hms(2, 12, 12)); + time -= Duration::hours(10); + assert_eq!(time, hms(16, 12, 12)); +} + +#[test] +fn test_time_sub() { + macro_rules! check { + ($lhs:expr, $rhs:expr, $diff:expr) => {{ + // `time1 - time2 = duration` is equivalent to `time2 - time1 = -duration` + assert_eq!($lhs.signed_duration_since($rhs), $diff); + assert_eq!($rhs.signed_duration_since($lhs), -$diff); + }}; + } + + let hmsm = |h, m, s, ms| NaiveTime::from_hms_milli_opt(h, m, s, ms).unwrap(); + + check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Duration::zero()); + check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300)); + check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1)); + check!( + hmsm(3, 5, 7, 200), + hmsm(2, 4, 6, 300), + Duration::seconds(3600 + 60) + Duration::milliseconds(900) + ); + + // treats the leap second as if it coincides with the prior non-leap second, + // as required by `time1 - time2 = duration` and `time2 - time1 = -duration` equivalence. + check!(hmsm(3, 5, 7, 200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(400)); + check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(1400)); + check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 800), Duration::milliseconds(1400)); + + // additional equality: `time1 + duration = time2` is equivalent to + // `time2 - time1 = duration` IF AND ONLY IF `time2` represents a non-leap second. + assert_eq!(hmsm(3, 5, 6, 800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200)); + assert_eq!(hmsm(3, 5, 6, 1_800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200)); +} + +#[test] +fn test_time_fmt() { + assert_eq!( + format!("{}", NaiveTime::from_hms_milli_opt(23, 59, 59, 999).unwrap()), + "23:59:59.999" + ); + assert_eq!( + format!("{}", NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap()), + "23:59:60" + ); + assert_eq!( + format!("{}", NaiveTime::from_hms_milli_opt(23, 59, 59, 1_001).unwrap()), + "23:59:60.001" + ); + assert_eq!( + format!("{}", NaiveTime::from_hms_micro_opt(0, 0, 0, 43210).unwrap()), + "00:00:00.043210" + ); + assert_eq!( + format!("{}", NaiveTime::from_hms_nano_opt(0, 0, 0, 6543210).unwrap()), + "00:00:00.006543210" + ); + + // the format specifier should have no effect on `NaiveTime` + assert_eq!( + format!("{:30}", NaiveTime::from_hms_milli_opt(3, 5, 7, 9).unwrap()), + "03:05:07.009" + ); +} + +#[test] +fn test_date_from_str() { + // valid cases + let valid = [ + "0:0:0", + "0:0:0.0000000", + "0:0:0.0000003", + " 4 : 3 : 2.1 ", + " 09:08:07 ", + " 9:8:07 ", + "23:59:60.373929310237", + ]; + for &s in &valid { + let d = match s.parse::<NaiveTime>() { + Ok(d) => d, + Err(e) => panic!("parsing `{}` has failed: {}", s, e), + }; + let s_ = format!("{:?}", d); + // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same + let d_ = match s_.parse::<NaiveTime>() { + Ok(d) => d, + Err(e) => { + panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}", s, d, e) + } + }; + assert!( + d == d_, + "`{}` is parsed into `{:?}`, but reparsed result \ + `{:?}` does not match", + s, + d, + d_ + ); + } + + // some invalid cases + // since `ParseErrorKind` is private, all we can do is to check if there was an error + assert!("".parse::<NaiveTime>().is_err()); + assert!("x".parse::<NaiveTime>().is_err()); + assert!("15".parse::<NaiveTime>().is_err()); + assert!("15:8".parse::<NaiveTime>().is_err()); + assert!("15:8:x".parse::<NaiveTime>().is_err()); + assert!("15:8:9x".parse::<NaiveTime>().is_err()); + assert!("23:59:61".parse::<NaiveTime>().is_err()); + assert!("12:34:56.x".parse::<NaiveTime>().is_err()); + assert!("12:34:56. 0".parse::<NaiveTime>().is_err()); +} + +#[test] +fn test_time_parse_from_str() { + let hms = |h, m, s| NaiveTime::from_hms_opt(h, m, s).unwrap(); + assert_eq!( + NaiveTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), + Ok(hms(12, 34, 56)) + ); // ignore date and offset + assert_eq!(NaiveTime::parse_from_str("PM 12:59", "%P %H:%M"), Ok(hms(12, 59, 0))); + assert!(NaiveTime::parse_from_str("12:3456", "%H:%M:%S").is_err()); +} + +#[test] +fn test_time_format() { + let t = NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap(); + assert_eq!(t.format("%H,%k,%I,%l,%P,%p").to_string(), "03, 3,03, 3,am,AM"); + assert_eq!(t.format("%M").to_string(), "05"); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,098765432,.098765432"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".098,.098765,.098765432"); + assert_eq!(t.format("%R").to_string(), "03:05"); + assert_eq!(t.format("%T,%X").to_string(), "03:05:07,03:05:07"); + assert_eq!(t.format("%r").to_string(), "03:05:07 AM"); + assert_eq!(t.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); + + let t = NaiveTime::from_hms_micro_opt(3, 5, 7, 432100).unwrap(); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,432100000,.432100"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".432,.432100,.432100000"); + + let t = NaiveTime::from_hms_milli_opt(3, 5, 7, 210).unwrap(); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,210000000,.210"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".210,.210000,.210000000"); + + let t = NaiveTime::from_hms_opt(3, 5, 7).unwrap(); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,000000000,"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".000,.000000,.000000000"); + + // corner cases + assert_eq!(NaiveTime::from_hms_opt(13, 57, 9).unwrap().format("%r").to_string(), "01:57:09 PM"); + assert_eq!( + NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap().format("%X").to_string(), + "23:59:60" + ); +} |