1// This is a part of Chrono.
2// See README.md and LICENSE.txt for details.
3
4//! ISO 8601 calendar date without timezone.
5
6#[cfg(any(feature = "alloc", feature = "std", test))]
7use core::borrow::Borrow;
8use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
9use core::{fmt, str};
10
11#[cfg(feature = "rkyv")]
12use rkyv::{Archive, Deserialize, Serialize};
13
14/// L10n locales.
15#[cfg(feature = "unstable-locales")]
16use pure_rust_locales::Locale;
17
18#[cfg(any(feature = "alloc", feature = "std", test))]
19use crate::format::DelayedFormat;
20use crate::format::{
21 parse, parse_and_remainder, write_hundreds, Item, Numeric, Pad, ParseError, ParseResult,
22 Parsed, StrftimeItems,
23};
24use crate::month::Months;
25use crate::naive::{IsoWeek, NaiveDateTime, NaiveTime};
26use crate::oldtime::Duration as OldDuration;
27use crate::{Datelike, Duration, Weekday};
28
29use super::internals::{self, DateImpl, Mdf, Of, YearFlags};
30use super::isoweek;
31
32const MAX_YEAR: i32 = internals::MAX_YEAR;
33const MIN_YEAR: i32 = internals::MIN_YEAR;
34
35// MAX_YEAR-12-31 minus 0000-01-01
36// = ((MAX_YEAR+1)-01-01 minus 0001-01-01) + (0001-01-01 minus 0000-01-01) - 1 day
37// = ((MAX_YEAR+1)-01-01 minus 0001-01-01) + 365 days
38// = MAX_YEAR * 365 + (# of leap years from 0001 to MAX_YEAR) + 365 days
39#[cfg(test)] // only used for testing
40const MAX_DAYS_FROM_YEAR_0: i32 =
41 MAX_YEAR * 365 + MAX_YEAR / 4 - MAX_YEAR / 100 + MAX_YEAR / 400 + 365;
42
43// MIN_YEAR-01-01 minus 0000-01-01
44// = (MIN_YEAR+400n+1)-01-01 minus (400n+1)-01-01
45// = ((MIN_YEAR+400n+1)-01-01 minus 0001-01-01) - ((400n+1)-01-01 minus 0001-01-01)
46// = ((MIN_YEAR+400n+1)-01-01 minus 0001-01-01) - 146097n days
47//
48// n is set to 1000 for convenience.
49#[cfg(test)] // only used for testing
50const MIN_DAYS_FROM_YEAR_0: i32 = (MIN_YEAR + 400_000) * 365 + (MIN_YEAR + 400_000) / 4
51 - (MIN_YEAR + 400_000) / 100
52 + (MIN_YEAR + 400_000) / 400
53 - 146_097_000;
54
55#[cfg(test)] // only used for testing, but duplicated in naive::datetime
56const MAX_BITS: usize = 44;
57
58/// A week represented by a [`NaiveDate`] and a [`Weekday`] which is the first
59/// day of the week.
60#[derive(Debug)]
61pub struct NaiveWeek {
62 date: NaiveDate,
63 start: Weekday,
64}
65
66impl NaiveWeek {
67 /// Returns a date representing the first day of the week.
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use chrono::{NaiveDate, Weekday};
73 ///
74 /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap();
75 /// let week = date.week(Weekday::Mon);
76 /// assert!(week.first_day() <= date);
77 /// ```
78 #[inline]
79 #[must_use]
80 pub fn first_day(&self) -> NaiveDate {
81 let start = self.start.num_days_from_monday() as i32;
82 let ref_day = self.date.weekday().num_days_from_monday() as i32;
83 // Calculate the number of days to subtract from `self.date`.
84 // Do not construct an intermediate date beyond `self.date`, because that may be out of
85 // range if `date` is close to `NaiveDate::MAX`.
86 let days = start - ref_day - if start > ref_day { 7 } else { 0 };
87 self.date.diff_days(days as i64).unwrap()
88 }
89
90 /// Returns a date representing the last day of the week.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use chrono::{NaiveDate, Weekday};
96 ///
97 /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap();
98 /// let week = date.week(Weekday::Mon);
99 /// assert!(week.last_day() >= date);
100 /// ```
101 #[inline]
102 #[must_use]
103 pub fn last_day(&self) -> NaiveDate {
104 let end = self.start.pred().num_days_from_monday() as i32;
105 let ref_day = self.date.weekday().num_days_from_monday() as i32;
106 // Calculate the number of days to add to `self.date`.
107 // Do not construct an intermediate date before `self.date` (like with `first_day()`),
108 // because that may be out of range if `date` is close to `NaiveDate::MIN`.
109 let days = end - ref_day + if end < ref_day { 7 } else { 0 };
110 self.date.diff_days(days as i64).unwrap()
111 }
112
113 /// Returns a [`RangeInclusive<T>`] representing the whole week bounded by
114 /// [first_day](./struct.NaiveWeek.html#method.first_day) and
115 /// [last_day](./struct.NaiveWeek.html#method.last_day) functions.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use chrono::{NaiveDate, Weekday};
121 ///
122 /// let date = NaiveDate::from_ymd_opt(2022, 4, 18).unwrap();
123 /// let week = date.week(Weekday::Mon);
124 /// let days = week.days();
125 /// assert!(days.contains(&date));
126 /// ```
127 #[inline]
128 #[must_use]
129 pub fn days(&self) -> RangeInclusive<NaiveDate> {
130 self.first_day()..=self.last_day()
131 }
132}
133
134/// A duration in calendar days.
135///
136/// This is useful because when using `Duration` it is possible
137/// that adding `Duration::days(1)` doesn't increment the day value as expected due to it being a
138/// fixed number of seconds. This difference applies only when dealing with `DateTime<TimeZone>` data types
139/// and in other cases `Duration::days(n)` and `Days::new(n)` are equivalent.
140#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
141pub struct Days(pub(crate) u64);
142
143impl Days {
144 /// Construct a new `Days` from a number of days
145 pub const fn new(num: u64) -> Self {
146 Self(num)
147 }
148}
149
150/// ISO 8601 calendar date without timezone.
151/// Allows for every [proleptic Gregorian date] from Jan 1, 262145 BCE to Dec 31, 262143 CE.
152/// Also supports the conversion from ISO 8601 ordinal and week date.
153///
154/// # Calendar Date
155///
156/// The ISO 8601 **calendar date** follows the proleptic Gregorian calendar.
157/// It is like a normal civil calendar but note some slight differences:
158///
159/// * Dates before the Gregorian calendar's inception in 1582 are defined via the extrapolation.
160/// Be careful, as historical dates are often noted in the Julian calendar and others
161/// and the transition to Gregorian may differ across countries (as late as early 20C).
162///
163/// (Some example: Both Shakespeare from Britain and Cervantes from Spain seemingly died
164/// on the same calendar date---April 23, 1616---but in the different calendar.
165/// Britain used the Julian calendar at that time, so Shakespeare's death is later.)
166///
167/// * ISO 8601 calendars has the year 0, which is 1 BCE (a year before 1 CE).
168/// If you need a typical BCE/BC and CE/AD notation for year numbers,
169/// use the [`Datelike::year_ce`](../trait.Datelike.html#method.year_ce) method.
170///
171/// # Week Date
172///
173/// The ISO 8601 **week date** is a triple of year number, week number
174/// and [day of the week](../enum.Weekday.html) with the following rules:
175///
176/// * A week consists of Monday through Sunday, and is always numbered within some year.
177/// The week number ranges from 1 to 52 or 53 depending on the year.
178///
179/// * The week 1 of given year is defined as the first week containing January 4 of that year,
180/// or equivalently, the first week containing four or more days in that year.
181///
182/// * The year number in the week date may *not* correspond to the actual Gregorian year.
183/// For example, January 3, 2016 (Sunday) was on the last (53rd) week of 2015.
184///
185/// Chrono's date types default to the ISO 8601 [calendar date](#calendar-date),
186/// but [`Datelike::iso_week`](../trait.Datelike.html#tymethod.iso_week) and
187/// [`Datelike::weekday`](../trait.Datelike.html#tymethod.weekday) methods
188/// can be used to get the corresponding week date.
189///
190/// # Ordinal Date
191///
192/// The ISO 8601 **ordinal date** is a pair of year number and day of the year ("ordinal").
193/// The ordinal number ranges from 1 to 365 or 366 depending on the year.
194/// The year number is the same as that of the [calendar date](#calendar-date).
195///
196/// This is currently the internal format of Chrono's date types.
197///
198/// [proleptic Gregorian date]: crate::NaiveDate#calendar-date
199#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
200#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
201pub struct NaiveDate {
202 ymdf: DateImpl, // (year << 13) | of
203}
204
205/// The minimum possible `NaiveDate` (January 1, 262145 BCE).
206#[deprecated(since = "0.4.20", note = "Use NaiveDate::MIN instead")]
207pub const MIN_DATE: NaiveDate = NaiveDate::MIN;
208/// The maximum possible `NaiveDate` (December 31, 262143 CE).
209#[deprecated(since = "0.4.20", note = "Use NaiveDate::MAX instead")]
210pub const MAX_DATE: NaiveDate = NaiveDate::MAX;
211
212#[cfg(feature = "arbitrary")]
213impl arbitrary::Arbitrary<'_> for NaiveDate {
214 fn arbitrary(u: &mut arbitrary::Unstructured) -> arbitrary::Result<NaiveDate> {
215 let year = u.int_in_range(MIN_YEAR..=MAX_YEAR)?;
216 let max_days = YearFlags::from_year(year).ndays();
217 let ord = u.int_in_range(1..=max_days)?;
218 NaiveDate::from_yo_opt(year, ord).ok_or(arbitrary::Error::IncorrectFormat)
219 }
220}
221
222// as it is hard to verify year flags in `NaiveDate::MIN` and `NaiveDate::MAX`,
223// we use a separate run-time test.
224#[test]
225fn test_date_bounds() {
226 let calculated_min: NaiveDate = NaiveDate::from_ymd_opt(MIN_YEAR, month:1, day:1).unwrap();
227 let calculated_max: NaiveDate = NaiveDate::from_ymd_opt(MAX_YEAR, month:12, day:31).unwrap();
228 assert!(
229 NaiveDate::MIN == calculated_min,
230 "`NaiveDate::MIN` should have a year flag {:?}",
231 calculated_min.of().flags()
232 );
233 assert!(
234 NaiveDate::MAX == calculated_max,
235 "`NaiveDate::MAX` should have a year flag {:?}",
236 calculated_max.of().flags()
237 );
238
239 // let's also check that the entire range do not exceed 2^44 seconds
240 // (sometimes used for bounding `Duration` against overflow)
241 let maxsecs: i64 = NaiveDate::MAX.signed_duration_since(NaiveDate::MIN).num_seconds();
242 let maxsecs: i64 = maxsecs + 86401; // also take care of DateTime
243 assert!(
244 maxsecs < (1 << MAX_BITS),
245 "The entire `NaiveDate` range somehow exceeds 2^{} seconds",
246 MAX_BITS
247 );
248}
249
250impl NaiveDate {
251 pub(crate) fn weeks_from(&self, day: Weekday) -> i32 {
252 (self.ordinal() as i32 - self.weekday().num_days_from(day) as i32 + 6) / 7
253 }
254
255 /// Makes a new `NaiveDate` from year, ordinal and flags.
256 /// Does not check whether the flags are correct for the provided year.
257 const fn from_ordinal_and_flags(
258 year: i32,
259 ordinal: u32,
260 flags: YearFlags,
261 ) -> Option<NaiveDate> {
262 if year < MIN_YEAR || year > MAX_YEAR {
263 return None; // Out-of-range
264 }
265 // Enable debug check once the MSRV >= 1.57 (panicking in const feature)
266 // debug_assert!(YearFlags::from_year(year).0 == flags.0);
267 match Of::new(ordinal, flags) {
268 Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
269 None => None, // Invalid: Ordinal outside of the nr of days in a year with those flags.
270 }
271 }
272
273 /// Makes a new `NaiveDate` from year and packed month-day-flags.
274 /// Does not check whether the flags are correct for the provided year.
275 const fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
276 if year < MIN_YEAR || year > MAX_YEAR {
277 return None; // Out-of-range
278 }
279 match mdf.to_of() {
280 Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
281 None => None, // Non-existing date
282 }
283 }
284
285 /// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
286 /// (year, month and day).
287 ///
288 /// Panics on the out-of-range date, invalid month and/or day.
289 #[deprecated(since = "0.4.23", note = "use `from_ymd_opt()` instead")]
290 #[must_use]
291 pub fn from_ymd(year: i32, month: u32, day: u32) -> NaiveDate {
292 NaiveDate::from_ymd_opt(year, month, day).expect("invalid or out-of-range date")
293 }
294
295 /// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
296 /// (year, month and day).
297 ///
298 /// Returns `None` on the out-of-range date, invalid month and/or day.
299 ///
300 /// # Example
301 ///
302 /// ```
303 /// use chrono::NaiveDate;
304 ///
305 /// let from_ymd_opt = NaiveDate::from_ymd_opt;
306 ///
307 /// assert!(from_ymd_opt(2015, 3, 14).is_some());
308 /// assert!(from_ymd_opt(2015, 0, 14).is_none());
309 /// assert!(from_ymd_opt(2015, 2, 29).is_none());
310 /// assert!(from_ymd_opt(-4, 2, 29).is_some()); // 5 BCE is a leap year
311 /// assert!(from_ymd_opt(400000, 1, 1).is_none());
312 /// assert!(from_ymd_opt(-400000, 1, 1).is_none());
313 /// ```
314 #[must_use]
315 pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
316 let flags = YearFlags::from_year(year);
317 NaiveDate::from_mdf(year, Mdf::new(month, day, flags)?)
318 }
319
320 /// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date)
321 /// (year and day of the year).
322 ///
323 /// Panics on the out-of-range date and/or invalid day of year.
324 #[deprecated(since = "0.4.23", note = "use `from_yo_opt()` instead")]
325 #[must_use]
326 pub fn from_yo(year: i32, ordinal: u32) -> NaiveDate {
327 NaiveDate::from_yo_opt(year, ordinal).expect("invalid or out-of-range date")
328 }
329
330 /// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date)
331 /// (year and day of the year).
332 ///
333 /// Returns `None` on the out-of-range date and/or invalid day of year.
334 ///
335 /// # Example
336 ///
337 /// ```
338 /// use chrono::NaiveDate;
339 ///
340 /// let from_yo_opt = NaiveDate::from_yo_opt;
341 ///
342 /// assert!(from_yo_opt(2015, 100).is_some());
343 /// assert!(from_yo_opt(2015, 0).is_none());
344 /// assert!(from_yo_opt(2015, 365).is_some());
345 /// assert!(from_yo_opt(2015, 366).is_none());
346 /// assert!(from_yo_opt(-4, 366).is_some()); // 5 BCE is a leap year
347 /// assert!(from_yo_opt(400000, 1).is_none());
348 /// assert!(from_yo_opt(-400000, 1).is_none());
349 /// ```
350 #[must_use]
351 pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> {
352 let flags = YearFlags::from_year(year);
353 NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
354 }
355
356 /// Makes a new `NaiveDate` from the [ISO week date](#week-date)
357 /// (year, week number and day of the week).
358 /// The resulting `NaiveDate` may have a different year from the input year.
359 ///
360 /// Panics on the out-of-range date and/or invalid week number.
361 #[deprecated(since = "0.4.23", note = "use `from_isoywd_opt()` instead")]
362 #[must_use]
363 pub fn from_isoywd(year: i32, week: u32, weekday: Weekday) -> NaiveDate {
364 NaiveDate::from_isoywd_opt(year, week, weekday).expect("invalid or out-of-range date")
365 }
366
367 /// Makes a new `NaiveDate` from the [ISO week date](#week-date)
368 /// (year, week number and day of the week).
369 /// The resulting `NaiveDate` may have a different year from the input year.
370 ///
371 /// Returns `None` on the out-of-range date and/or invalid week number.
372 ///
373 /// # Example
374 ///
375 /// ```
376 /// use chrono::{NaiveDate, Weekday};
377 ///
378 /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
379 /// let from_isoywd_opt = NaiveDate::from_isoywd_opt;
380 ///
381 /// assert_eq!(from_isoywd_opt(2015, 0, Weekday::Sun), None);
382 /// assert_eq!(from_isoywd_opt(2015, 10, Weekday::Sun), Some(from_ymd(2015, 3, 8)));
383 /// assert_eq!(from_isoywd_opt(2015, 30, Weekday::Mon), Some(from_ymd(2015, 7, 20)));
384 /// assert_eq!(from_isoywd_opt(2015, 60, Weekday::Mon), None);
385 ///
386 /// assert_eq!(from_isoywd_opt(400000, 10, Weekday::Fri), None);
387 /// assert_eq!(from_isoywd_opt(-400000, 10, Weekday::Sat), None);
388 /// ```
389 ///
390 /// The year number of ISO week date may differ from that of the calendar date.
391 ///
392 /// ```
393 /// # use chrono::{NaiveDate, Weekday};
394 /// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
395 /// # let from_isoywd_opt = NaiveDate::from_isoywd_opt;
396 /// // Mo Tu We Th Fr Sa Su
397 /// // 2014-W52 22 23 24 25 26 27 28 has 4+ days of new year,
398 /// // 2015-W01 29 30 31 1 2 3 4 <- so this is the first week
399 /// assert_eq!(from_isoywd_opt(2014, 52, Weekday::Sun), Some(from_ymd(2014, 12, 28)));
400 /// assert_eq!(from_isoywd_opt(2014, 53, Weekday::Mon), None);
401 /// assert_eq!(from_isoywd_opt(2015, 1, Weekday::Mon), Some(from_ymd(2014, 12, 29)));
402 ///
403 /// // 2015-W52 21 22 23 24 25 26 27 has 4+ days of old year,
404 /// // 2015-W53 28 29 30 31 1 2 3 <- so this is the last week
405 /// // 2016-W01 4 5 6 7 8 9 10
406 /// assert_eq!(from_isoywd_opt(2015, 52, Weekday::Sun), Some(from_ymd(2015, 12, 27)));
407 /// assert_eq!(from_isoywd_opt(2015, 53, Weekday::Sun), Some(from_ymd(2016, 1, 3)));
408 /// assert_eq!(from_isoywd_opt(2015, 54, Weekday::Mon), None);
409 /// assert_eq!(from_isoywd_opt(2016, 1, Weekday::Mon), Some(from_ymd(2016, 1, 4)));
410 /// ```
411 #[must_use]
412 pub fn from_isoywd_opt(year: i32, week: u32, weekday: Weekday) -> Option<NaiveDate> {
413 let flags = YearFlags::from_year(year);
414 let nweeks = flags.nisoweeks();
415 if 1 <= week && week <= nweeks {
416 // ordinal = week ordinal - delta
417 let weekord = week * 7 + weekday as u32;
418 let delta = flags.isoweek_delta();
419 if weekord <= delta {
420 // ordinal < 1, previous year
421 let prevflags = YearFlags::from_year(year - 1);
422 NaiveDate::from_ordinal_and_flags(
423 year - 1,
424 weekord + prevflags.ndays() - delta,
425 prevflags,
426 )
427 } else {
428 let ordinal = weekord - delta;
429 let ndays = flags.ndays();
430 if ordinal <= ndays {
431 // this year
432 NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
433 } else {
434 // ordinal > ndays, next year
435 let nextflags = YearFlags::from_year(year + 1);
436 NaiveDate::from_ordinal_and_flags(year + 1, ordinal - ndays, nextflags)
437 }
438 }
439 } else {
440 None
441 }
442 }
443
444 /// Makes a new `NaiveDate` from a day's number in the proleptic Gregorian calendar, with
445 /// January 1, 1 being day 1.
446 ///
447 /// Panics if the date is out of range.
448 #[deprecated(since = "0.4.23", note = "use `from_num_days_from_ce_opt()` instead")]
449 #[inline]
450 #[must_use]
451 pub fn from_num_days_from_ce(days: i32) -> NaiveDate {
452 NaiveDate::from_num_days_from_ce_opt(days).expect("out-of-range date")
453 }
454
455 /// Makes a new `NaiveDate` from a day's number in the proleptic Gregorian calendar, with
456 /// January 1, 1 being day 1.
457 ///
458 /// Returns `None` if the date is out of range.
459 ///
460 /// # Example
461 ///
462 /// ```
463 /// use chrono::NaiveDate;
464 ///
465 /// let from_ndays_opt = NaiveDate::from_num_days_from_ce_opt;
466 /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
467 ///
468 /// assert_eq!(from_ndays_opt(730_000), Some(from_ymd(1999, 9, 3)));
469 /// assert_eq!(from_ndays_opt(1), Some(from_ymd(1, 1, 1)));
470 /// assert_eq!(from_ndays_opt(0), Some(from_ymd(0, 12, 31)));
471 /// assert_eq!(from_ndays_opt(-1), Some(from_ymd(0, 12, 30)));
472 /// assert_eq!(from_ndays_opt(100_000_000), None);
473 /// assert_eq!(from_ndays_opt(-100_000_000), None);
474 /// ```
475 #[must_use]
476 pub fn from_num_days_from_ce_opt(days: i32) -> Option<NaiveDate> {
477 let days = days.checked_add(365)?; // make December 31, 1 BCE equal to day 0
478 let (year_div_400, cycle) = div_mod_floor(days, 146_097);
479 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
480 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
481 NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
482 }
483
484 /// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
485 /// since the beginning of the given month. For instance, if you want the 2nd Friday of March
486 /// 2017, you would use `NaiveDate::from_weekday_of_month(2017, 3, Weekday::Fri, 2)`.
487 ///
488 /// # Panics
489 ///
490 /// The resulting `NaiveDate` is guaranteed to be in `month`. If `n` is larger than the number
491 /// of `weekday` in `month` (eg. the 6th Friday of March 2017) then this function will panic.
492 ///
493 /// `n` is 1-indexed. Passing `n=0` will cause a panic.
494 #[deprecated(since = "0.4.23", note = "use `from_weekday_of_month_opt()` instead")]
495 #[must_use]
496 pub fn from_weekday_of_month(year: i32, month: u32, weekday: Weekday, n: u8) -> NaiveDate {
497 NaiveDate::from_weekday_of_month_opt(year, month, weekday, n).expect("out-of-range date")
498 }
499
500 /// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
501 /// since the beginning of the given month. For instance, if you want the 2nd Friday of March
502 /// 2017, you would use `NaiveDate::from_weekday_of_month(2017, 3, Weekday::Fri, 2)`. `n` is 1-indexed.
503 ///
504 /// ```
505 /// use chrono::{NaiveDate, Weekday};
506 /// assert_eq!(NaiveDate::from_weekday_of_month_opt(2017, 3, Weekday::Fri, 2),
507 /// NaiveDate::from_ymd_opt(2017, 3, 10))
508 /// ```
509 ///
510 /// Returns `None` if `n` out-of-range; ie. if `n` is larger than the number of `weekday` in
511 /// `month` (eg. the 6th Friday of March 2017), or if `n == 0`.
512 #[must_use]
513 pub fn from_weekday_of_month_opt(
514 year: i32,
515 month: u32,
516 weekday: Weekday,
517 n: u8,
518 ) -> Option<NaiveDate> {
519 if n == 0 {
520 return None;
521 }
522 let first = NaiveDate::from_ymd_opt(year, month, 1)?.weekday();
523 let first_to_dow = (7 + weekday.number_from_monday() - first.number_from_monday()) % 7;
524 let day = (u32::from(n) - 1) * 7 + first_to_dow + 1;
525 NaiveDate::from_ymd_opt(year, month, day)
526 }
527
528 /// Parses a string with the specified format string and returns a new `NaiveDate`.
529 /// See the [`format::strftime` module](../format/strftime/index.html)
530 /// on the supported escape sequences.
531 ///
532 /// # Example
533 ///
534 /// ```
535 /// use chrono::NaiveDate;
536 ///
537 /// let parse_from_str = NaiveDate::parse_from_str;
538 ///
539 /// assert_eq!(parse_from_str("2015-09-05", "%Y-%m-%d"),
540 /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()));
541 /// assert_eq!(parse_from_str("5sep2015", "%d%b%Y"),
542 /// Ok(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()));
543 /// ```
544 ///
545 /// Time and offset is ignored for the purpose of parsing.
546 ///
547 /// ```
548 /// # use chrono::NaiveDate;
549 /// # let parse_from_str = NaiveDate::parse_from_str;
550 /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
551 /// Ok(NaiveDate::from_ymd_opt(2014, 5, 17).unwrap()));
552 /// ```
553 ///
554 /// Out-of-bound dates or insufficient fields are errors.
555 ///
556 /// ```
557 /// # use chrono::NaiveDate;
558 /// # let parse_from_str = NaiveDate::parse_from_str;
559 /// assert!(parse_from_str("2015/9", "%Y/%m").is_err());
560 /// assert!(parse_from_str("2015/9/31", "%Y/%m/%d").is_err());
561 /// ```
562 ///
563 /// All parsed fields should be consistent to each other, otherwise it's an error.
564 ///
565 /// ```
566 /// # use chrono::NaiveDate;
567 /// # let parse_from_str = NaiveDate::parse_from_str;
568 /// assert!(parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err());
569 /// ```
570 pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDate> {
571 let mut parsed = Parsed::new();
572 parse(&mut parsed, s, StrftimeItems::new(fmt))?;
573 parsed.to_naive_date()
574 }
575
576 /// Parses a string from a user-specified format into a new `NaiveDate` value, and a slice with
577 /// the remaining portion of the string.
578 /// See the [`format::strftime` module](../format/strftime/index.html)
579 /// on the supported escape sequences.
580 ///
581 /// Similar to [`parse_from_str`](#method.parse_from_str).
582 ///
583 /// # Example
584 ///
585 /// ```rust
586 /// # use chrono::{NaiveDate};
587 /// let (date, remainder) = NaiveDate::parse_and_remainder(
588 /// "2015-02-18 trailing text", "%Y-%m-%d").unwrap();
589 /// assert_eq!(date, NaiveDate::from_ymd_opt(2015, 2, 18).unwrap());
590 /// assert_eq!(remainder, " trailing text");
591 /// ```
592 pub fn parse_and_remainder<'a>(s: &'a str, fmt: &str) -> ParseResult<(NaiveDate, &'a str)> {
593 let mut parsed = Parsed::new();
594 let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
595 parsed.to_naive_date().map(|d| (d, remainder))
596 }
597
598 /// Add a duration in [`Months`] to the date
599 ///
600 /// If the day would be out of range for the resulting month, use the last day for that month.
601 ///
602 /// Returns `None` if the resulting date would be out of range.
603 ///
604 /// ```
605 /// # use chrono::{NaiveDate, Months};
606 /// assert_eq!(
607 /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_add_months(Months::new(6)),
608 /// Some(NaiveDate::from_ymd_opt(2022, 8, 20).unwrap())
609 /// );
610 /// assert_eq!(
611 /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_months(Months::new(2)),
612 /// Some(NaiveDate::from_ymd_opt(2022, 9, 30).unwrap())
613 /// );
614 /// ```
615 #[must_use]
616 pub fn checked_add_months(self, months: Months) -> Option<Self> {
617 if months.0 == 0 {
618 return Some(self);
619 }
620
621 match months.0 <= core::i32::MAX as u32 {
622 true => self.diff_months(months.0 as i32),
623 false => None,
624 }
625 }
626
627 /// Subtract a duration in [`Months`] from the date
628 ///
629 /// If the day would be out of range for the resulting month, use the last day for that month.
630 ///
631 /// Returns `None` if the resulting date would be out of range.
632 ///
633 /// ```
634 /// # use chrono::{NaiveDate, Months};
635 /// assert_eq!(
636 /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_months(Months::new(6)),
637 /// Some(NaiveDate::from_ymd_opt(2021, 8, 20).unwrap())
638 /// );
639 ///
640 /// assert_eq!(
641 /// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap()
642 /// .checked_sub_months(Months::new(core::i32::MAX as u32 + 1)),
643 /// None
644 /// );
645 /// ```
646 #[must_use]
647 pub fn checked_sub_months(self, months: Months) -> Option<Self> {
648 if months.0 == 0 {
649 return Some(self);
650 }
651
652 // Copy `i32::MAX` here so we don't have to do a complicated cast
653 match months.0 <= 2_147_483_647 {
654 true => self.diff_months(-(months.0 as i32)),
655 false => None,
656 }
657 }
658
659 fn diff_months(self, months: i32) -> Option<Self> {
660 let (years, left) = ((months / 12), (months % 12));
661
662 // Determine new year (without taking months into account for now
663
664 let year = if (years > 0 && years > (MAX_YEAR - self.year()))
665 || (years < 0 && years < (MIN_YEAR - self.year()))
666 {
667 return None;
668 } else {
669 self.year() + years
670 };
671
672 // Determine new month
673
674 let month = self.month() as i32 + left;
675 let (year, month) = if month <= 0 {
676 if year == MIN_YEAR {
677 return None;
678 }
679
680 (year - 1, month + 12)
681 } else if month > 12 {
682 if year == MAX_YEAR {
683 return None;
684 }
685
686 (year + 1, month - 12)
687 } else {
688 (year, month)
689 };
690
691 // Clamp original day in case new month is shorter
692
693 let flags = YearFlags::from_year(year);
694 let feb_days = if flags.ndays() == 366 { 29 } else { 28 };
695 let days = [31, feb_days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
696 let day = Ord::min(self.day(), days[(month - 1) as usize]);
697
698 NaiveDate::from_mdf(year, Mdf::new(month as u32, day, flags)?)
699 }
700
701 /// Add a duration in [`Days`] to the date
702 ///
703 /// Returns `None` if the resulting date would be out of range.
704 ///
705 /// ```
706 /// # use chrono::{NaiveDate, Days};
707 /// assert_eq!(
708 /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_add_days(Days::new(9)),
709 /// Some(NaiveDate::from_ymd_opt(2022, 3, 1).unwrap())
710 /// );
711 /// assert_eq!(
712 /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_days(Days::new(2)),
713 /// Some(NaiveDate::from_ymd_opt(2022, 8, 2).unwrap())
714 /// );
715 /// assert_eq!(
716 /// NaiveDate::from_ymd_opt(2022, 7, 31).unwrap().checked_add_days(Days::new(1000000000000)),
717 /// None
718 /// );
719 /// ```
720 #[must_use]
721 pub fn checked_add_days(self, days: Days) -> Option<Self> {
722 if days.0 == 0 {
723 return Some(self);
724 }
725
726 i64::try_from(days.0).ok().and_then(|d| self.diff_days(d))
727 }
728
729 /// Subtract a duration in [`Days`] from the date
730 ///
731 /// Returns `None` if the resulting date would be out of range.
732 ///
733 /// ```
734 /// # use chrono::{NaiveDate, Days};
735 /// assert_eq!(
736 /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_days(Days::new(6)),
737 /// Some(NaiveDate::from_ymd_opt(2022, 2, 14).unwrap())
738 /// );
739 /// assert_eq!(
740 /// NaiveDate::from_ymd_opt(2022, 2, 20).unwrap().checked_sub_days(Days::new(1000000000000)),
741 /// None
742 /// );
743 /// ```
744 #[must_use]
745 pub fn checked_sub_days(self, days: Days) -> Option<Self> {
746 if days.0 == 0 {
747 return Some(self);
748 }
749
750 i64::try_from(days.0).ok().and_then(|d| self.diff_days(-d))
751 }
752
753 fn diff_days(self, days: i64) -> Option<Self> {
754 let secs = days.checked_mul(86400)?; // 86400 seconds in one day
755 if secs >= core::i64::MAX / 1000 || secs <= core::i64::MIN / 1000 {
756 return None; // See the `time` 0.1 crate. Outside these bounds, `Duration::seconds` will panic
757 }
758 self.checked_add_signed(Duration::seconds(secs))
759 }
760
761 /// Makes a new `NaiveDateTime` from the current date and given `NaiveTime`.
762 ///
763 /// # Example
764 ///
765 /// ```
766 /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime};
767 ///
768 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
769 /// let t = NaiveTime::from_hms_milli_opt(12, 34, 56, 789).unwrap();
770 ///
771 /// let dt: NaiveDateTime = d.and_time(t);
772 /// assert_eq!(dt.date(), d);
773 /// assert_eq!(dt.time(), t);
774 /// ```
775 #[inline]
776 #[must_use]
777 pub const fn and_time(&self, time: NaiveTime) -> NaiveDateTime {
778 NaiveDateTime::new(*self, time)
779 }
780
781 /// Makes a new `NaiveDateTime` from the current date, hour, minute and second.
782 ///
783 /// No [leap second](./struct.NaiveTime.html#leap-second-handling) is allowed here;
784 /// use `NaiveDate::and_hms_*` methods with a subsecond parameter instead.
785 ///
786 /// Panics on invalid hour, minute and/or second.
787 #[deprecated(since = "0.4.23", note = "use `and_hms_opt()` instead")]
788 #[inline]
789 #[must_use]
790 pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> NaiveDateTime {
791 self.and_hms_opt(hour, min, sec).expect("invalid time")
792 }
793
794 /// Makes a new `NaiveDateTime` from the current date, hour, minute and second.
795 ///
796 /// No [leap second](./struct.NaiveTime.html#leap-second-handling) is allowed here;
797 /// use `NaiveDate::and_hms_*_opt` methods with a subsecond parameter instead.
798 ///
799 /// Returns `None` on invalid hour, minute and/or second.
800 ///
801 /// # Example
802 ///
803 /// ```
804 /// use chrono::NaiveDate;
805 ///
806 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
807 /// assert!(d.and_hms_opt(12, 34, 56).is_some());
808 /// assert!(d.and_hms_opt(12, 34, 60).is_none()); // use `and_hms_milli_opt` instead
809 /// assert!(d.and_hms_opt(12, 60, 56).is_none());
810 /// assert!(d.and_hms_opt(24, 34, 56).is_none());
811 /// ```
812 #[inline]
813 #[must_use]
814 pub fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> {
815 NaiveTime::from_hms_opt(hour, min, sec).map(|time| self.and_time(time))
816 }
817
818 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and millisecond.
819 ///
820 /// The millisecond part can exceed 1,000
821 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
822 ///
823 /// Panics on invalid hour, minute, second and/or millisecond.
824 #[deprecated(since = "0.4.23", note = "use `and_hms_milli_opt()` instead")]
825 #[inline]
826 #[must_use]
827 pub fn and_hms_milli(&self, hour: u32, min: u32, sec: u32, milli: u32) -> NaiveDateTime {
828 self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
829 }
830
831 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and millisecond.
832 ///
833 /// The millisecond part can exceed 1,000
834 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
835 ///
836 /// Returns `None` on invalid hour, minute, second and/or millisecond.
837 ///
838 /// # Example
839 ///
840 /// ```
841 /// use chrono::NaiveDate;
842 ///
843 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
844 /// assert!(d.and_hms_milli_opt(12, 34, 56, 789).is_some());
845 /// assert!(d.and_hms_milli_opt(12, 34, 59, 1_789).is_some()); // leap second
846 /// assert!(d.and_hms_milli_opt(12, 34, 59, 2_789).is_none());
847 /// assert!(d.and_hms_milli_opt(12, 34, 60, 789).is_none());
848 /// assert!(d.and_hms_milli_opt(12, 60, 56, 789).is_none());
849 /// assert!(d.and_hms_milli_opt(24, 34, 56, 789).is_none());
850 /// ```
851 #[inline]
852 #[must_use]
853 pub fn and_hms_milli_opt(
854 &self,
855 hour: u32,
856 min: u32,
857 sec: u32,
858 milli: u32,
859 ) -> Option<NaiveDateTime> {
860 NaiveTime::from_hms_milli_opt(hour, min, sec, milli).map(|time| self.and_time(time))
861 }
862
863 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and microsecond.
864 ///
865 /// The microsecond part can exceed 1,000,000
866 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
867 ///
868 /// Panics on invalid hour, minute, second and/or microsecond.
869 ///
870 /// # Example
871 ///
872 /// ```
873 /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday};
874 ///
875 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
876 ///
877 /// let dt: NaiveDateTime = d.and_hms_micro_opt(12, 34, 56, 789_012).unwrap();
878 /// assert_eq!(dt.year(), 2015);
879 /// assert_eq!(dt.weekday(), Weekday::Wed);
880 /// assert_eq!(dt.second(), 56);
881 /// assert_eq!(dt.nanosecond(), 789_012_000);
882 /// ```
883 #[deprecated(since = "0.4.23", note = "use `and_hms_micro_opt()` instead")]
884 #[inline]
885 #[must_use]
886 pub fn and_hms_micro(&self, hour: u32, min: u32, sec: u32, micro: u32) -> NaiveDateTime {
887 self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
888 }
889
890 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and microsecond.
891 ///
892 /// The microsecond part can exceed 1,000,000
893 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
894 ///
895 /// Returns `None` on invalid hour, minute, second and/or microsecond.
896 ///
897 /// # Example
898 ///
899 /// ```
900 /// use chrono::NaiveDate;
901 ///
902 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
903 /// assert!(d.and_hms_micro_opt(12, 34, 56, 789_012).is_some());
904 /// assert!(d.and_hms_micro_opt(12, 34, 59, 1_789_012).is_some()); // leap second
905 /// assert!(d.and_hms_micro_opt(12, 34, 59, 2_789_012).is_none());
906 /// assert!(d.and_hms_micro_opt(12, 34, 60, 789_012).is_none());
907 /// assert!(d.and_hms_micro_opt(12, 60, 56, 789_012).is_none());
908 /// assert!(d.and_hms_micro_opt(24, 34, 56, 789_012).is_none());
909 /// ```
910 #[inline]
911 #[must_use]
912 pub fn and_hms_micro_opt(
913 &self,
914 hour: u32,
915 min: u32,
916 sec: u32,
917 micro: u32,
918 ) -> Option<NaiveDateTime> {
919 NaiveTime::from_hms_micro_opt(hour, min, sec, micro).map(|time| self.and_time(time))
920 }
921
922 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and nanosecond.
923 ///
924 /// The nanosecond part can exceed 1,000,000,000
925 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
926 ///
927 /// Panics on invalid hour, minute, second and/or nanosecond.
928 #[deprecated(since = "0.4.23", note = "use `and_hms_nano_opt()` instead")]
929 #[inline]
930 #[must_use]
931 pub fn and_hms_nano(&self, hour: u32, min: u32, sec: u32, nano: u32) -> NaiveDateTime {
932 self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
933 }
934
935 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and nanosecond.
936 ///
937 /// The nanosecond part can exceed 1,000,000,000
938 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
939 ///
940 /// Returns `None` on invalid hour, minute, second and/or nanosecond.
941 ///
942 /// # Example
943 ///
944 /// ```
945 /// use chrono::NaiveDate;
946 ///
947 /// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
948 /// assert!(d.and_hms_nano_opt(12, 34, 56, 789_012_345).is_some());
949 /// assert!(d.and_hms_nano_opt(12, 34, 59, 1_789_012_345).is_some()); // leap second
950 /// assert!(d.and_hms_nano_opt(12, 34, 59, 2_789_012_345).is_none());
951 /// assert!(d.and_hms_nano_opt(12, 34, 60, 789_012_345).is_none());
952 /// assert!(d.and_hms_nano_opt(12, 60, 56, 789_012_345).is_none());
953 /// assert!(d.and_hms_nano_opt(24, 34, 56, 789_012_345).is_none());
954 /// ```
955 #[inline]
956 #[must_use]
957 pub fn and_hms_nano_opt(
958 &self,
959 hour: u32,
960 min: u32,
961 sec: u32,
962 nano: u32,
963 ) -> Option<NaiveDateTime> {
964 NaiveTime::from_hms_nano_opt(hour, min, sec, nano).map(|time| self.and_time(time))
965 }
966
967 /// Returns the packed month-day-flags.
968 #[inline]
969 fn mdf(&self) -> Mdf {
970 self.of().to_mdf()
971 }
972
973 /// Returns the packed ordinal-flags.
974 #[inline]
975 const fn of(&self) -> Of {
976 Of::from_date_impl(self.ymdf)
977 }
978
979 /// Makes a new `NaiveDate` with the packed month-day-flags changed.
980 ///
981 /// Returns `None` when the resulting `NaiveDate` would be invalid.
982 #[inline]
983 fn with_mdf(&self, mdf: Mdf) -> Option<NaiveDate> {
984 Some(self.with_of(mdf.to_of()?))
985 }
986
987 /// Makes a new `NaiveDate` with the packed ordinal-flags changed.
988 ///
989 /// Returns `None` when the resulting `NaiveDate` would be invalid.
990 /// Does not check if the year flags match the year.
991 #[inline]
992 const fn with_of(&self, of: Of) -> NaiveDate {
993 NaiveDate { ymdf: (self.ymdf & !0b1_1111_1111_1111) | of.inner() as DateImpl }
994 }
995
996 /// Makes a new `NaiveDate` for the next calendar date.
997 ///
998 /// Panics when `self` is the last representable date.
999 #[deprecated(since = "0.4.23", note = "use `succ_opt()` instead")]
1000 #[inline]
1001 #[must_use]
1002 pub fn succ(&self) -> NaiveDate {
1003 self.succ_opt().expect("out of bound")
1004 }
1005
1006 /// Makes a new `NaiveDate` for the next calendar date.
1007 ///
1008 /// Returns `None` when `self` is the last representable date.
1009 ///
1010 /// # Example
1011 ///
1012 /// ```
1013 /// use chrono::NaiveDate;
1014 ///
1015 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 6, 3).unwrap().succ_opt(),
1016 /// Some(NaiveDate::from_ymd_opt(2015, 6, 4).unwrap()));
1017 /// assert_eq!(NaiveDate::MAX.succ_opt(), None);
1018 /// ```
1019 #[inline]
1020 #[must_use]
1021 pub fn succ_opt(&self) -> Option<NaiveDate> {
1022 match self.of().succ() {
1023 Some(of) => Some(self.with_of(of)),
1024 None => NaiveDate::from_ymd_opt(self.year() + 1, 1, 1),
1025 }
1026 }
1027
1028 /// Makes a new `NaiveDate` for the previous calendar date.
1029 ///
1030 /// Panics when `self` is the first representable date.
1031 #[deprecated(since = "0.4.23", note = "use `pred_opt()` instead")]
1032 #[inline]
1033 #[must_use]
1034 pub fn pred(&self) -> NaiveDate {
1035 self.pred_opt().expect("out of bound")
1036 }
1037
1038 /// Makes a new `NaiveDate` for the previous calendar date.
1039 ///
1040 /// Returns `None` when `self` is the first representable date.
1041 ///
1042 /// # Example
1043 ///
1044 /// ```
1045 /// use chrono::NaiveDate;
1046 ///
1047 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 6, 3).unwrap().pred_opt(),
1048 /// Some(NaiveDate::from_ymd_opt(2015, 6, 2).unwrap()));
1049 /// assert_eq!(NaiveDate::MIN.pred_opt(), None);
1050 /// ```
1051 #[inline]
1052 #[must_use]
1053 pub fn pred_opt(&self) -> Option<NaiveDate> {
1054 match self.of().pred() {
1055 Some(of) => Some(self.with_of(of)),
1056 None => NaiveDate::from_ymd_opt(self.year() - 1, 12, 31),
1057 }
1058 }
1059
1060 /// Adds the `days` part of given `Duration` to the current date.
1061 ///
1062 /// Returns `None` when it will result in overflow.
1063 ///
1064 /// # Example
1065 ///
1066 /// ```
1067 /// use chrono::{Duration, NaiveDate};
1068 ///
1069 /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1070 /// assert_eq!(d.checked_add_signed(Duration::days(40)),
1071 /// Some(NaiveDate::from_ymd_opt(2015, 10, 15).unwrap()));
1072 /// assert_eq!(d.checked_add_signed(Duration::days(-40)),
1073 /// Some(NaiveDate::from_ymd_opt(2015, 7, 27).unwrap()));
1074 /// assert_eq!(d.checked_add_signed(Duration::days(1_000_000_000)), None);
1075 /// assert_eq!(d.checked_add_signed(Duration::days(-1_000_000_000)), None);
1076 /// assert_eq!(NaiveDate::MAX.checked_add_signed(Duration::days(1)), None);
1077 /// ```
1078 #[must_use]
1079 pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
1080 let year = self.year();
1081 let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
1082 let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
1083 let cycle = (cycle as i32).checked_add(i32::try_from(rhs.num_days()).ok()?)?;
1084 let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
1085 year_div_400 += cycle_div_400y;
1086
1087 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
1088 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
1089 NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
1090 }
1091
1092 /// Subtracts the `days` part of given `Duration` from the current date.
1093 ///
1094 /// Returns `None` when it will result in overflow.
1095 ///
1096 /// # Example
1097 ///
1098 /// ```
1099 /// use chrono::{Duration, NaiveDate};
1100 ///
1101 /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1102 /// assert_eq!(d.checked_sub_signed(Duration::days(40)),
1103 /// Some(NaiveDate::from_ymd_opt(2015, 7, 27).unwrap()));
1104 /// assert_eq!(d.checked_sub_signed(Duration::days(-40)),
1105 /// Some(NaiveDate::from_ymd_opt(2015, 10, 15).unwrap()));
1106 /// assert_eq!(d.checked_sub_signed(Duration::days(1_000_000_000)), None);
1107 /// assert_eq!(d.checked_sub_signed(Duration::days(-1_000_000_000)), None);
1108 /// assert_eq!(NaiveDate::MIN.checked_sub_signed(Duration::days(1)), None);
1109 /// ```
1110 #[must_use]
1111 pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
1112 let year = self.year();
1113 let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
1114 let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
1115 let cycle = (cycle as i32).checked_sub(i32::try_from(rhs.num_days()).ok()?)?;
1116 let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
1117 year_div_400 += cycle_div_400y;
1118
1119 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
1120 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
1121 NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
1122 }
1123
1124 /// Subtracts another `NaiveDate` from the current date.
1125 /// Returns a `Duration` of integral numbers.
1126 ///
1127 /// This does not overflow or underflow at all,
1128 /// as all possible output fits in the range of `Duration`.
1129 ///
1130 /// # Example
1131 ///
1132 /// ```
1133 /// use chrono::{Duration, NaiveDate};
1134 ///
1135 /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1136 /// let since = NaiveDate::signed_duration_since;
1137 ///
1138 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2014, 1, 1)), Duration::zero());
1139 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 12, 31)), Duration::days(1));
1140 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2014, 1, 2)), Duration::days(-1));
1141 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 9, 23)), Duration::days(100));
1142 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 1, 1)), Duration::days(365));
1143 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2010, 1, 1)), Duration::days(365*4 + 1));
1144 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(1614, 1, 1)), Duration::days(365*400 + 97));
1145 /// ```
1146 #[must_use]
1147 pub fn signed_duration_since(self, rhs: NaiveDate) -> OldDuration {
1148 let year1 = self.year();
1149 let year2 = rhs.year();
1150 let (year1_div_400, year1_mod_400) = div_mod_floor(year1, 400);
1151 let (year2_div_400, year2_mod_400) = div_mod_floor(year2, 400);
1152 let cycle1 = i64::from(internals::yo_to_cycle(year1_mod_400 as u32, self.of().ordinal()));
1153 let cycle2 = i64::from(internals::yo_to_cycle(year2_mod_400 as u32, rhs.of().ordinal()));
1154 OldDuration::days(
1155 (i64::from(year1_div_400) - i64::from(year2_div_400)) * 146_097 + (cycle1 - cycle2),
1156 )
1157 }
1158
1159 /// Returns the number of whole years from the given `base` until `self`.
1160 #[must_use]
1161 pub fn years_since(&self, base: Self) -> Option<u32> {
1162 let mut years = self.year() - base.year();
1163 if (self.month(), self.day()) < (base.month(), base.day()) {
1164 years -= 1;
1165 }
1166
1167 match years >= 0 {
1168 true => Some(years as u32),
1169 false => None,
1170 }
1171 }
1172
1173 /// Formats the date with the specified formatting items.
1174 /// Otherwise it is the same as the ordinary `format` method.
1175 ///
1176 /// The `Iterator` of items should be `Clone`able,
1177 /// since the resulting `DelayedFormat` value may be formatted multiple times.
1178 ///
1179 /// # Example
1180 ///
1181 /// ```
1182 /// use chrono::NaiveDate;
1183 /// use chrono::format::strftime::StrftimeItems;
1184 ///
1185 /// let fmt = StrftimeItems::new("%Y-%m-%d");
1186 /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1187 /// assert_eq!(d.format_with_items(fmt.clone()).to_string(), "2015-09-05");
1188 /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05");
1189 /// ```
1190 ///
1191 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
1192 ///
1193 /// ```
1194 /// # use chrono::NaiveDate;
1195 /// # use chrono::format::strftime::StrftimeItems;
1196 /// # let fmt = StrftimeItems::new("%Y-%m-%d").clone();
1197 /// # let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1198 /// assert_eq!(format!("{}", d.format_with_items(fmt)), "2015-09-05");
1199 /// ```
1200 #[cfg(any(feature = "alloc", feature = "std", test))]
1201 #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
1202 #[inline]
1203 #[must_use]
1204 pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
1205 where
1206 I: Iterator<Item = B> + Clone,
1207 B: Borrow<Item<'a>>,
1208 {
1209 DelayedFormat::new(Some(*self), None, items)
1210 }
1211
1212 /// Formats the date with the specified format string.
1213 /// See the [`format::strftime` module](../format/strftime/index.html)
1214 /// on the supported escape sequences.
1215 ///
1216 /// This returns a `DelayedFormat`,
1217 /// which gets converted to a string only when actual formatting happens.
1218 /// You may use the `to_string` method to get a `String`,
1219 /// or just feed it into `print!` and other formatting macros.
1220 /// (In this way it avoids the redundant memory allocation.)
1221 ///
1222 /// A wrong format string does *not* issue an error immediately.
1223 /// Rather, converting or formatting the `DelayedFormat` fails.
1224 /// You are recommended to immediately use `DelayedFormat` for this reason.
1225 ///
1226 /// # Example
1227 ///
1228 /// ```
1229 /// use chrono::NaiveDate;
1230 ///
1231 /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1232 /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05");
1233 /// assert_eq!(d.format("%A, %-d %B, %C%y").to_string(), "Saturday, 5 September, 2015");
1234 /// ```
1235 ///
1236 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
1237 ///
1238 /// ```
1239 /// # use chrono::NaiveDate;
1240 /// # let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap();
1241 /// assert_eq!(format!("{}", d.format("%Y-%m-%d")), "2015-09-05");
1242 /// assert_eq!(format!("{}", d.format("%A, %-d %B, %C%y")), "Saturday, 5 September, 2015");
1243 /// ```
1244 #[cfg(any(feature = "alloc", feature = "std", test))]
1245 #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
1246 #[inline]
1247 #[must_use]
1248 pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
1249 self.format_with_items(StrftimeItems::new(fmt))
1250 }
1251
1252 /// Formats the date with the specified formatting items and locale.
1253 #[cfg(feature = "unstable-locales")]
1254 #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
1255 #[inline]
1256 #[must_use]
1257 pub fn format_localized_with_items<'a, I, B>(
1258 &self,
1259 items: I,
1260 locale: Locale,
1261 ) -> DelayedFormat<I>
1262 where
1263 I: Iterator<Item = B> + Clone,
1264 B: Borrow<Item<'a>>,
1265 {
1266 DelayedFormat::new_with_locale(Some(*self), None, items, locale)
1267 }
1268
1269 /// Formats the date with the specified format string and locale.
1270 ///
1271 /// See the [`crate::format::strftime`] module on the supported escape
1272 /// sequences.
1273 #[cfg(feature = "unstable-locales")]
1274 #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
1275 #[inline]
1276 #[must_use]
1277 pub fn format_localized<'a>(
1278 &self,
1279 fmt: &'a str,
1280 locale: Locale,
1281 ) -> DelayedFormat<StrftimeItems<'a>> {
1282 self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale)
1283 }
1284
1285 /// Returns an iterator that steps by days across all representable dates.
1286 ///
1287 /// # Example
1288 ///
1289 /// ```
1290 /// # use chrono::NaiveDate;
1291 ///
1292 /// let expected = [
1293 /// NaiveDate::from_ymd_opt(2016, 2, 27).unwrap(),
1294 /// NaiveDate::from_ymd_opt(2016, 2, 28).unwrap(),
1295 /// NaiveDate::from_ymd_opt(2016, 2, 29).unwrap(),
1296 /// NaiveDate::from_ymd_opt(2016, 3, 1).unwrap(),
1297 /// ];
1298 ///
1299 /// let mut count = 0;
1300 /// for (idx, d) in NaiveDate::from_ymd_opt(2016, 2, 27).unwrap().iter_days().take(4).enumerate() {
1301 /// assert_eq!(d, expected[idx]);
1302 /// count += 1;
1303 /// }
1304 /// assert_eq!(count, 4);
1305 ///
1306 /// for d in NaiveDate::from_ymd_opt(2016, 3, 1).unwrap().iter_days().rev().take(4) {
1307 /// count -= 1;
1308 /// assert_eq!(d, expected[count]);
1309 /// }
1310 /// ```
1311 #[inline]
1312 pub const fn iter_days(&self) -> NaiveDateDaysIterator {
1313 NaiveDateDaysIterator { value: *self }
1314 }
1315
1316 /// Returns an iterator that steps by weeks across all representable dates.
1317 ///
1318 /// # Example
1319 ///
1320 /// ```
1321 /// # use chrono::NaiveDate;
1322 ///
1323 /// let expected = [
1324 /// NaiveDate::from_ymd_opt(2016, 2, 27).unwrap(),
1325 /// NaiveDate::from_ymd_opt(2016, 3, 5).unwrap(),
1326 /// NaiveDate::from_ymd_opt(2016, 3, 12).unwrap(),
1327 /// NaiveDate::from_ymd_opt(2016, 3, 19).unwrap(),
1328 /// ];
1329 ///
1330 /// let mut count = 0;
1331 /// for (idx, d) in NaiveDate::from_ymd_opt(2016, 2, 27).unwrap().iter_weeks().take(4).enumerate() {
1332 /// assert_eq!(d, expected[idx]);
1333 /// count += 1;
1334 /// }
1335 /// assert_eq!(count, 4);
1336 ///
1337 /// for d in NaiveDate::from_ymd_opt(2016, 3, 19).unwrap().iter_weeks().rev().take(4) {
1338 /// count -= 1;
1339 /// assert_eq!(d, expected[count]);
1340 /// }
1341 /// ```
1342 #[inline]
1343 pub const fn iter_weeks(&self) -> NaiveDateWeeksIterator {
1344 NaiveDateWeeksIterator { value: *self }
1345 }
1346
1347 /// Returns the [`NaiveWeek`] that the date belongs to, starting with the [`Weekday`]
1348 /// specified.
1349 #[inline]
1350 pub const fn week(&self, start: Weekday) -> NaiveWeek {
1351 NaiveWeek { date: *self, start }
1352 }
1353
1354 /// The minimum possible `NaiveDate` (January 1, 262145 BCE).
1355 pub const MIN: NaiveDate = NaiveDate { ymdf: (MIN_YEAR << 13) | (1 << 4) | 0o07 /*FE*/ };
1356 /// The maximum possible `NaiveDate` (December 31, 262143 CE).
1357 pub const MAX: NaiveDate = NaiveDate { ymdf: (MAX_YEAR << 13) | (365 << 4) | 0o17 /*F*/ };
1358}
1359
1360impl Datelike for NaiveDate {
1361 /// Returns the year number in the [calendar date](#calendar-date).
1362 ///
1363 /// # Example
1364 ///
1365 /// ```
1366 /// use chrono::{NaiveDate, Datelike};
1367 ///
1368 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().year(), 2015);
1369 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().year(), -308); // 309 BCE
1370 /// ```
1371 #[inline]
1372 fn year(&self) -> i32 {
1373 self.ymdf >> 13
1374 }
1375
1376 /// Returns the month number starting from 1.
1377 ///
1378 /// The return value ranges from 1 to 12.
1379 ///
1380 /// # Example
1381 ///
1382 /// ```
1383 /// use chrono::{NaiveDate, Datelike};
1384 ///
1385 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().month(), 9);
1386 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().month(), 3);
1387 /// ```
1388 #[inline]
1389 fn month(&self) -> u32 {
1390 self.mdf().month()
1391 }
1392
1393 /// Returns the month number starting from 0.
1394 ///
1395 /// The return value ranges from 0 to 11.
1396 ///
1397 /// # Example
1398 ///
1399 /// ```
1400 /// use chrono::{NaiveDate, Datelike};
1401 ///
1402 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().month0(), 8);
1403 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().month0(), 2);
1404 /// ```
1405 #[inline]
1406 fn month0(&self) -> u32 {
1407 self.mdf().month() - 1
1408 }
1409
1410 /// Returns the day of month starting from 1.
1411 ///
1412 /// The return value ranges from 1 to 31. (The last day of month differs by months.)
1413 ///
1414 /// # Example
1415 ///
1416 /// ```
1417 /// use chrono::{NaiveDate, Datelike};
1418 ///
1419 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().day(), 8);
1420 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().day(), 14);
1421 /// ```
1422 ///
1423 /// Combined with [`NaiveDate::pred`](#method.pred),
1424 /// one can determine the number of days in a particular month.
1425 /// (Note that this panics when `year` is out of range.)
1426 ///
1427 /// ```
1428 /// use chrono::{NaiveDate, Datelike};
1429 ///
1430 /// fn ndays_in_month(year: i32, month: u32) -> u32 {
1431 /// // the first day of the next month...
1432 /// let (y, m) = if month == 12 { (year + 1, 1) } else { (year, month + 1) };
1433 /// let d = NaiveDate::from_ymd_opt(y, m, 1).unwrap();
1434 ///
1435 /// // ...is preceded by the last day of the original month
1436 /// d.pred_opt().unwrap().day()
1437 /// }
1438 ///
1439 /// assert_eq!(ndays_in_month(2015, 8), 31);
1440 /// assert_eq!(ndays_in_month(2015, 9), 30);
1441 /// assert_eq!(ndays_in_month(2015, 12), 31);
1442 /// assert_eq!(ndays_in_month(2016, 2), 29);
1443 /// assert_eq!(ndays_in_month(2017, 2), 28);
1444 /// ```
1445 #[inline]
1446 fn day(&self) -> u32 {
1447 self.mdf().day()
1448 }
1449
1450 /// Returns the day of month starting from 0.
1451 ///
1452 /// The return value ranges from 0 to 30. (The last day of month differs by months.)
1453 ///
1454 /// # Example
1455 ///
1456 /// ```
1457 /// use chrono::{NaiveDate, Datelike};
1458 ///
1459 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().day0(), 7);
1460 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().day0(), 13);
1461 /// ```
1462 #[inline]
1463 fn day0(&self) -> u32 {
1464 self.mdf().day() - 1
1465 }
1466
1467 /// Returns the day of year starting from 1.
1468 ///
1469 /// The return value ranges from 1 to 366. (The last day of year differs by years.)
1470 ///
1471 /// # Example
1472 ///
1473 /// ```
1474 /// use chrono::{NaiveDate, Datelike};
1475 ///
1476 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().ordinal(), 251);
1477 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().ordinal(), 74);
1478 /// ```
1479 ///
1480 /// Combined with [`NaiveDate::pred`](#method.pred),
1481 /// one can determine the number of days in a particular year.
1482 /// (Note that this panics when `year` is out of range.)
1483 ///
1484 /// ```
1485 /// use chrono::{NaiveDate, Datelike};
1486 ///
1487 /// fn ndays_in_year(year: i32) -> u32 {
1488 /// // the first day of the next year...
1489 /// let d = NaiveDate::from_ymd_opt(year + 1, 1, 1).unwrap();
1490 ///
1491 /// // ...is preceded by the last day of the original year
1492 /// d.pred_opt().unwrap().ordinal()
1493 /// }
1494 ///
1495 /// assert_eq!(ndays_in_year(2015), 365);
1496 /// assert_eq!(ndays_in_year(2016), 366);
1497 /// assert_eq!(ndays_in_year(2017), 365);
1498 /// assert_eq!(ndays_in_year(2000), 366);
1499 /// assert_eq!(ndays_in_year(2100), 365);
1500 /// ```
1501 #[inline]
1502 fn ordinal(&self) -> u32 {
1503 self.of().ordinal()
1504 }
1505
1506 /// Returns the day of year starting from 0.
1507 ///
1508 /// The return value ranges from 0 to 365. (The last day of year differs by years.)
1509 ///
1510 /// # Example
1511 ///
1512 /// ```
1513 /// use chrono::{NaiveDate, Datelike};
1514 ///
1515 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().ordinal0(), 250);
1516 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().ordinal0(), 73);
1517 /// ```
1518 #[inline]
1519 fn ordinal0(&self) -> u32 {
1520 self.of().ordinal() - 1
1521 }
1522
1523 /// Returns the day of week.
1524 ///
1525 /// # Example
1526 ///
1527 /// ```
1528 /// use chrono::{NaiveDate, Datelike, Weekday};
1529 ///
1530 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().weekday(), Weekday::Tue);
1531 /// assert_eq!(NaiveDate::from_ymd_opt(-308, 3, 14).unwrap().weekday(), Weekday::Fri);
1532 /// ```
1533 #[inline]
1534 fn weekday(&self) -> Weekday {
1535 self.of().weekday()
1536 }
1537
1538 #[inline]
1539 fn iso_week(&self) -> IsoWeek {
1540 isoweek::iso_week_from_yof(self.year(), self.of())
1541 }
1542
1543 /// Makes a new `NaiveDate` with the year number changed.
1544 ///
1545 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1546 ///
1547 /// # Example
1548 ///
1549 /// ```
1550 /// use chrono::{NaiveDate, Datelike};
1551 ///
1552 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_year(2016),
1553 /// Some(NaiveDate::from_ymd_opt(2016, 9, 8).unwrap()));
1554 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_year(-308),
1555 /// Some(NaiveDate::from_ymd_opt(-308, 9, 8).unwrap()));
1556 /// ```
1557 ///
1558 /// A leap day (February 29) is a good example that this method can return `None`.
1559 ///
1560 /// ```
1561 /// # use chrono::{NaiveDate, Datelike};
1562 /// assert!(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().with_year(2015).is_none());
1563 /// assert!(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap().with_year(2020).is_some());
1564 /// ```
1565 #[inline]
1566 fn with_year(&self, year: i32) -> Option<NaiveDate> {
1567 // we need to operate with `mdf` since we should keep the month and day number as is
1568 let mdf = self.mdf();
1569
1570 // adjust the flags as needed
1571 let flags = YearFlags::from_year(year);
1572 let mdf = mdf.with_flags(flags);
1573
1574 NaiveDate::from_mdf(year, mdf)
1575 }
1576
1577 /// Makes a new `NaiveDate` with the month number (starting from 1) changed.
1578 ///
1579 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1580 ///
1581 /// # Example
1582 ///
1583 /// ```
1584 /// use chrono::{NaiveDate, Datelike};
1585 ///
1586 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month(10),
1587 /// Some(NaiveDate::from_ymd_opt(2015, 10, 8).unwrap()));
1588 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month(13), None); // no month 13
1589 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().with_month(2), None); // no February 30
1590 /// ```
1591 #[inline]
1592 fn with_month(&self, month: u32) -> Option<NaiveDate> {
1593 self.with_mdf(self.mdf().with_month(month)?)
1594 }
1595
1596 /// Makes a new `NaiveDate` with the month number (starting from 0) changed.
1597 ///
1598 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1599 ///
1600 /// # Example
1601 ///
1602 /// ```
1603 /// use chrono::{NaiveDate, Datelike};
1604 ///
1605 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month0(9),
1606 /// Some(NaiveDate::from_ymd_opt(2015, 10, 8).unwrap()));
1607 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_month0(12), None); // no month 13
1608 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap().with_month0(1), None); // no February 30
1609 /// ```
1610 #[inline]
1611 fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
1612 let month = month0.checked_add(1)?;
1613 self.with_mdf(self.mdf().with_month(month)?)
1614 }
1615
1616 /// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
1617 ///
1618 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1619 ///
1620 /// # Example
1621 ///
1622 /// ```
1623 /// use chrono::{NaiveDate, Datelike};
1624 ///
1625 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day(30),
1626 /// Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap()));
1627 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day(31),
1628 /// None); // no September 31
1629 /// ```
1630 #[inline]
1631 fn with_day(&self, day: u32) -> Option<NaiveDate> {
1632 self.with_mdf(self.mdf().with_day(day)?)
1633 }
1634
1635 /// Makes a new `NaiveDate` with the day of month (starting from 0) changed.
1636 ///
1637 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1638 ///
1639 /// # Example
1640 ///
1641 /// ```
1642 /// use chrono::{NaiveDate, Datelike};
1643 ///
1644 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day0(29),
1645 /// Some(NaiveDate::from_ymd_opt(2015, 9, 30).unwrap()));
1646 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 9, 8).unwrap().with_day0(30),
1647 /// None); // no September 31
1648 /// ```
1649 #[inline]
1650 fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
1651 let day = day0.checked_add(1)?;
1652 self.with_mdf(self.mdf().with_day(day)?)
1653 }
1654
1655 /// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
1656 ///
1657 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1658 ///
1659 /// # Example
1660 ///
1661 /// ```
1662 /// use chrono::{NaiveDate, Datelike};
1663 ///
1664 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal(60),
1665 /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap()));
1666 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal(366),
1667 /// None); // 2015 had only 365 days
1668 ///
1669 /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal(60),
1670 /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap()));
1671 /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal(366),
1672 /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap()));
1673 /// ```
1674 #[inline]
1675 fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
1676 self.of().with_ordinal(ordinal).map(|of| self.with_of(of))
1677 }
1678
1679 /// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
1680 ///
1681 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1682 ///
1683 /// # Example
1684 ///
1685 /// ```
1686 /// use chrono::{NaiveDate, Datelike};
1687 ///
1688 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal0(59),
1689 /// Some(NaiveDate::from_ymd_opt(2015, 3, 1).unwrap()));
1690 /// assert_eq!(NaiveDate::from_ymd_opt(2015, 1, 1).unwrap().with_ordinal0(365),
1691 /// None); // 2015 had only 365 days
1692 ///
1693 /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal0(59),
1694 /// Some(NaiveDate::from_ymd_opt(2016, 2, 29).unwrap()));
1695 /// assert_eq!(NaiveDate::from_ymd_opt(2016, 1, 1).unwrap().with_ordinal0(365),
1696 /// Some(NaiveDate::from_ymd_opt(2016, 12, 31).unwrap()));
1697 /// ```
1698 #[inline]
1699 fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
1700 let ordinal = ordinal0.checked_add(1)?;
1701 self.with_ordinal(ordinal)
1702 }
1703}
1704
1705/// An addition of `Duration` to `NaiveDate` discards the fractional days,
1706/// rounding to the closest integral number of days towards `Duration::zero()`.
1707///
1708/// Panics on underflow or overflow. Use [`NaiveDate::checked_add_signed`] to detect that.
1709///
1710/// # Example
1711///
1712/// ```
1713/// use chrono::{Duration, NaiveDate};
1714///
1715/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1716///
1717/// assert_eq!(from_ymd(2014, 1, 1) + Duration::zero(), from_ymd(2014, 1, 1));
1718/// assert_eq!(from_ymd(2014, 1, 1) + Duration::seconds(86399), from_ymd(2014, 1, 1));
1719/// assert_eq!(from_ymd(2014, 1, 1) + Duration::seconds(-86399), from_ymd(2014, 1, 1));
1720/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(1), from_ymd(2014, 1, 2));
1721/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(-1), from_ymd(2013, 12, 31));
1722/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(364), from_ymd(2014, 12, 31));
1723/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*4 + 1), from_ymd(2018, 1, 1));
1724/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*400 + 97), from_ymd(2414, 1, 1));
1725/// ```
1726///
1727/// [`NaiveDate::checked_add_signed`]: crate::NaiveDate::checked_add_signed
1728impl Add<OldDuration> for NaiveDate {
1729 type Output = NaiveDate;
1730
1731 #[inline]
1732 fn add(self, rhs: OldDuration) -> NaiveDate {
1733 self.checked_add_signed(rhs).expect(msg:"`NaiveDate + Duration` overflowed")
1734 }
1735}
1736
1737impl AddAssign<OldDuration> for NaiveDate {
1738 #[inline]
1739 fn add_assign(&mut self, rhs: OldDuration) {
1740 *self = self.add(rhs);
1741 }
1742}
1743
1744impl Add<Months> for NaiveDate {
1745 type Output = NaiveDate;
1746
1747 /// An addition of months to `NaiveDate` clamped to valid days in resulting month.
1748 ///
1749 /// # Panics
1750 ///
1751 /// Panics if the resulting date would be out of range.
1752 ///
1753 /// # Example
1754 ///
1755 /// ```
1756 /// use chrono::{NaiveDate, Months};
1757 ///
1758 /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1759 ///
1760 /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(1), from_ymd(2014, 2, 1));
1761 /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(11), from_ymd(2014, 12, 1));
1762 /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(12), from_ymd(2015, 1, 1));
1763 /// assert_eq!(from_ymd(2014, 1, 1) + Months::new(13), from_ymd(2015, 2, 1));
1764 /// assert_eq!(from_ymd(2014, 1, 31) + Months::new(1), from_ymd(2014, 2, 28));
1765 /// assert_eq!(from_ymd(2020, 1, 31) + Months::new(1), from_ymd(2020, 2, 29));
1766 /// ```
1767 fn add(self, months: Months) -> Self::Output {
1768 self.checked_add_months(months).unwrap()
1769 }
1770}
1771
1772impl Sub<Months> for NaiveDate {
1773 type Output = NaiveDate;
1774
1775 /// A subtraction of Months from `NaiveDate` clamped to valid days in resulting month.
1776 ///
1777 /// # Panics
1778 ///
1779 /// Panics if the resulting date would be out of range.
1780 ///
1781 /// # Example
1782 ///
1783 /// ```
1784 /// use chrono::{NaiveDate, Months};
1785 ///
1786 /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1787 ///
1788 /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(11), from_ymd(2013, 2, 1));
1789 /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(12), from_ymd(2013, 1, 1));
1790 /// assert_eq!(from_ymd(2014, 1, 1) - Months::new(13), from_ymd(2012, 12, 1));
1791 /// ```
1792 fn sub(self, months: Months) -> Self::Output {
1793 self.checked_sub_months(months).unwrap()
1794 }
1795}
1796
1797impl Add<Days> for NaiveDate {
1798 type Output = NaiveDate;
1799
1800 fn add(self, days: Days) -> Self::Output {
1801 self.checked_add_days(days).unwrap()
1802 }
1803}
1804
1805impl Sub<Days> for NaiveDate {
1806 type Output = NaiveDate;
1807
1808 fn sub(self, days: Days) -> Self::Output {
1809 self.checked_sub_days(days).unwrap()
1810 }
1811}
1812
1813/// A subtraction of `Duration` from `NaiveDate` discards the fractional days,
1814/// rounding to the closest integral number of days towards `Duration::zero()`.
1815/// It is the same as the addition with a negated `Duration`.
1816///
1817/// Panics on underflow or overflow. Use [`NaiveDate::checked_sub_signed`] to detect that.
1818///
1819/// # Example
1820///
1821/// ```
1822/// use chrono::{Duration, NaiveDate};
1823///
1824/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1825///
1826/// assert_eq!(from_ymd(2014, 1, 1) - Duration::zero(), from_ymd(2014, 1, 1));
1827/// assert_eq!(from_ymd(2014, 1, 1) - Duration::seconds(86399), from_ymd(2014, 1, 1));
1828/// assert_eq!(from_ymd(2014, 1, 1) - Duration::seconds(-86399), from_ymd(2014, 1, 1));
1829/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(1), from_ymd(2013, 12, 31));
1830/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(-1), from_ymd(2014, 1, 2));
1831/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(364), from_ymd(2013, 1, 2));
1832/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*4 + 1), from_ymd(2010, 1, 1));
1833/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*400 + 97), from_ymd(1614, 1, 1));
1834/// ```
1835///
1836/// [`NaiveDate::checked_sub_signed`]: crate::NaiveDate::checked_sub_signed
1837impl Sub<OldDuration> for NaiveDate {
1838 type Output = NaiveDate;
1839
1840 #[inline]
1841 fn sub(self, rhs: OldDuration) -> NaiveDate {
1842 self.checked_sub_signed(rhs).expect(msg:"`NaiveDate - Duration` overflowed")
1843 }
1844}
1845
1846impl SubAssign<OldDuration> for NaiveDate {
1847 #[inline]
1848 fn sub_assign(&mut self, rhs: OldDuration) {
1849 *self = self.sub(rhs);
1850 }
1851}
1852
1853/// Subtracts another `NaiveDate` from the current date.
1854/// Returns a `Duration` of integral numbers.
1855///
1856/// This does not overflow or underflow at all,
1857/// as all possible output fits in the range of `Duration`.
1858///
1859/// The implementation is a wrapper around
1860/// [`NaiveDate::signed_duration_since`](#method.signed_duration_since).
1861///
1862/// # Example
1863///
1864/// ```
1865/// use chrono::{Duration, NaiveDate};
1866///
1867/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
1868///
1869/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2014, 1, 1), Duration::zero());
1870/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2013, 12, 31), Duration::days(1));
1871/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2014, 1, 2), Duration::days(-1));
1872/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2013, 9, 23), Duration::days(100));
1873/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2013, 1, 1), Duration::days(365));
1874/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2010, 1, 1), Duration::days(365*4 + 1));
1875/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(1614, 1, 1), Duration::days(365*400 + 97));
1876/// ```
1877impl Sub<NaiveDate> for NaiveDate {
1878 type Output = OldDuration;
1879
1880 #[inline]
1881 fn sub(self, rhs: NaiveDate) -> OldDuration {
1882 self.signed_duration_since(rhs)
1883 }
1884}
1885
1886impl From<NaiveDateTime> for NaiveDate {
1887 fn from(naive_datetime: NaiveDateTime) -> Self {
1888 naive_datetime.date()
1889 }
1890}
1891
1892/// Iterator over `NaiveDate` with a step size of one day.
1893#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
1894pub struct NaiveDateDaysIterator {
1895 value: NaiveDate,
1896}
1897
1898impl Iterator for NaiveDateDaysIterator {
1899 type Item = NaiveDate;
1900
1901 fn next(&mut self) -> Option<Self::Item> {
1902 if self.value == NaiveDate::MAX {
1903 return None;
1904 }
1905 // current < NaiveDate::MAX from here on:
1906 let current: NaiveDate = self.value;
1907 // This can't panic because current is < NaiveDate::MAX:
1908 self.value = current.succ_opt().unwrap();
1909 Some(current)
1910 }
1911
1912 fn size_hint(&self) -> (usize, Option<usize>) {
1913 let exact_size: i64 = NaiveDate::MAX.signed_duration_since(self.value).num_days();
1914 (exact_size as usize, Some(exact_size as usize))
1915 }
1916}
1917
1918impl ExactSizeIterator for NaiveDateDaysIterator {}
1919
1920impl DoubleEndedIterator for NaiveDateDaysIterator {
1921 fn next_back(&mut self) -> Option<Self::Item> {
1922 if self.value == NaiveDate::MIN {
1923 return None;
1924 }
1925 let current: NaiveDate = self.value;
1926 self.value = current.pred_opt().unwrap();
1927 Some(current)
1928 }
1929}
1930
1931#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
1932pub struct NaiveDateWeeksIterator {
1933 value: NaiveDate,
1934}
1935
1936impl Iterator for NaiveDateWeeksIterator {
1937 type Item = NaiveDate;
1938
1939 fn next(&mut self) -> Option<Self::Item> {
1940 if NaiveDate::MAX - self.value < OldDuration::weeks(1) {
1941 return None;
1942 }
1943 let current: NaiveDate = self.value;
1944 self.value = current + OldDuration::weeks(1);
1945 Some(current)
1946 }
1947
1948 fn size_hint(&self) -> (usize, Option<usize>) {
1949 let exact_size: i64 = NaiveDate::MAX.signed_duration_since(self.value).num_weeks();
1950 (exact_size as usize, Some(exact_size as usize))
1951 }
1952}
1953
1954impl ExactSizeIterator for NaiveDateWeeksIterator {}
1955
1956impl DoubleEndedIterator for NaiveDateWeeksIterator {
1957 fn next_back(&mut self) -> Option<Self::Item> {
1958 if self.value - NaiveDate::MIN < OldDuration::weeks(1) {
1959 return None;
1960 }
1961 let current: NaiveDate = self.value;
1962 self.value = current - OldDuration::weeks(1);
1963 Some(current)
1964 }
1965}
1966
1967// TODO: NaiveDateDaysIterator and NaiveDateWeeksIterator should implement FusedIterator,
1968// TrustedLen, and Step once they becomes stable.
1969// See: https://github.com/chronotope/chrono/issues/208
1970
1971/// The `Debug` output of the naive date `d` is the same as
1972/// [`d.format("%Y-%m-%d")`](../format/strftime/index.html).
1973///
1974/// The string printed can be readily parsed via the `parse` method on `str`.
1975///
1976/// # Example
1977///
1978/// ```
1979/// use chrono::NaiveDate;
1980///
1981/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()), "2015-09-05");
1982/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( 0, 1, 1).unwrap()), "0000-01-01");
1983/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(9999, 12, 31).unwrap()), "9999-12-31");
1984/// ```
1985///
1986/// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE.
1987///
1988/// ```
1989/// # use chrono::NaiveDate;
1990/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt( -1, 1, 1).unwrap()), "-0001-01-01");
1991/// assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(10000, 12, 31).unwrap()), "+10000-12-31");
1992/// ```
1993impl fmt::Debug for NaiveDate {
1994 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1995 use core::fmt::Write;
1996
1997 let year: i32 = self.year();
1998 let mdf: Mdf = self.mdf();
1999 if (0..=9999).contains(&year) {
2000 write_hundreds(w:f, (year / 100) as u8)?;
2001 write_hundreds(w:f, (year % 100) as u8)?;
2002 } else {
2003 // ISO 8601 requires the explicit sign for out-of-range years
2004 write!(f, "{:+05}", year)?;
2005 }
2006
2007 f.write_char('-')?;
2008 write_hundreds(w:f, n:mdf.month() as u8)?;
2009 f.write_char('-')?;
2010 write_hundreds(w:f, n:mdf.day() as u8)
2011 }
2012}
2013
2014/// The `Display` output of the naive date `d` is the same as
2015/// [`d.format("%Y-%m-%d")`](../format/strftime/index.html).
2016///
2017/// The string printed can be readily parsed via the `parse` method on `str`.
2018///
2019/// # Example
2020///
2021/// ```
2022/// use chrono::NaiveDate;
2023///
2024/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(2015, 9, 5).unwrap()), "2015-09-05");
2025/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt( 0, 1, 1).unwrap()), "0000-01-01");
2026/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(9999, 12, 31).unwrap()), "9999-12-31");
2027/// ```
2028///
2029/// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE.
2030///
2031/// ```
2032/// # use chrono::NaiveDate;
2033/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt( -1, 1, 1).unwrap()), "-0001-01-01");
2034/// assert_eq!(format!("{}", NaiveDate::from_ymd_opt(10000, 12, 31).unwrap()), "+10000-12-31");
2035/// ```
2036impl fmt::Display for NaiveDate {
2037 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2038 fmt::Debug::fmt(self, f)
2039 }
2040}
2041
2042/// Parsing a `str` into a `NaiveDate` uses the same format,
2043/// [`%Y-%m-%d`](../format/strftime/index.html), as in `Debug` and `Display`.
2044///
2045/// # Example
2046///
2047/// ```
2048/// use chrono::NaiveDate;
2049///
2050/// let d = NaiveDate::from_ymd_opt(2015, 9, 18).unwrap();
2051/// assert_eq!("2015-09-18".parse::<NaiveDate>(), Ok(d));
2052///
2053/// let d = NaiveDate::from_ymd_opt(12345, 6, 7).unwrap();
2054/// assert_eq!("+12345-6-7".parse::<NaiveDate>(), Ok(d));
2055///
2056/// assert!("foo".parse::<NaiveDate>().is_err());
2057/// ```
2058impl str::FromStr for NaiveDate {
2059 type Err = ParseError;
2060
2061 fn from_str(s: &str) -> ParseResult<NaiveDate> {
2062 const ITEMS: &[Item<'static>] = &[
2063 Item::Numeric(Numeric::Year, Pad::Zero),
2064 Item::Space(""),
2065 Item::Literal("-"),
2066 Item::Numeric(Numeric::Month, Pad::Zero),
2067 Item::Space(""),
2068 Item::Literal("-"),
2069 Item::Numeric(Numeric::Day, Pad::Zero),
2070 Item::Space(""),
2071 ];
2072
2073 let mut parsed: Parsed = Parsed::new();
2074 parse(&mut parsed, s, ITEMS.iter())?;
2075 parsed.to_naive_date()
2076 }
2077}
2078
2079/// The default value for a NaiveDate is 1st of January 1970.
2080///
2081/// # Example
2082///
2083/// ```rust
2084/// use chrono::NaiveDate;
2085///
2086/// let default_date = NaiveDate::default();
2087/// assert_eq!(default_date, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
2088/// ```
2089impl Default for NaiveDate {
2090 fn default() -> Self {
2091 NaiveDate::from_ymd_opt(year:1970, month:1, day:1).unwrap()
2092 }
2093}
2094
2095fn div_mod_floor(val: i32, div: i32) -> (i32, i32) {
2096 (val.div_euclid(div), val.rem_euclid(div))
2097}
2098
2099#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
2100fn test_encodable_json<F, E>(to_string: F)
2101where
2102 F: Fn(&NaiveDate) -> Result<String, E>,
2103 E: ::std::fmt::Debug,
2104{
2105 assert_eq!(
2106 to_string(&NaiveDate::from_ymd_opt(2014, 7, 24).unwrap()).ok(),
2107 Some(r#""2014-07-24""#.into())
2108 );
2109 assert_eq!(
2110 to_string(&NaiveDate::from_ymd_opt(0, 1, 1).unwrap()).ok(),
2111 Some(r#""0000-01-01""#.into())
2112 );
2113 assert_eq!(
2114 to_string(&NaiveDate::from_ymd_opt(-1, 12, 31).unwrap()).ok(),
2115 Some(r#""-0001-12-31""#.into())
2116 );
2117 assert_eq!(to_string(&NaiveDate::MIN).ok(), Some(r#""-262144-01-01""#.into()));
2118 assert_eq!(to_string(&NaiveDate::MAX).ok(), Some(r#""+262143-12-31""#.into()));
2119}
2120
2121#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
2122fn test_decodable_json<F, E>(from_str: F)
2123where
2124 F: Fn(&str) -> Result<NaiveDate, E>,
2125 E: ::std::fmt::Debug,
2126{
2127 use std::{i32, i64};
2128
2129 assert_eq!(
2130 from_str(r#""2016-07-08""#).ok(),
2131 Some(NaiveDate::from_ymd_opt(2016, 7, 8).unwrap())
2132 );
2133 assert_eq!(from_str(r#""2016-7-8""#).ok(), Some(NaiveDate::from_ymd_opt(2016, 7, 8).unwrap()));
2134 assert_eq!(from_str(r#""+002016-07-08""#).ok(), NaiveDate::from_ymd_opt(2016, 7, 8));
2135 assert_eq!(from_str(r#""0000-01-01""#).ok(), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap()));
2136 assert_eq!(from_str(r#""0-1-1""#).ok(), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap()));
2137 assert_eq!(
2138 from_str(r#""-0001-12-31""#).ok(),
2139 Some(NaiveDate::from_ymd_opt(-1, 12, 31).unwrap())
2140 );
2141 assert_eq!(from_str(r#""-262144-01-01""#).ok(), Some(NaiveDate::MIN));
2142 assert_eq!(from_str(r#""+262143-12-31""#).ok(), Some(NaiveDate::MAX));
2143
2144 // bad formats
2145 assert!(from_str(r#""""#).is_err());
2146 assert!(from_str(r#""20001231""#).is_err());
2147 assert!(from_str(r#""2000-00-00""#).is_err());
2148 assert!(from_str(r#""2000-02-30""#).is_err());
2149 assert!(from_str(r#""2001-02-29""#).is_err());
2150 assert!(from_str(r#""2002-002-28""#).is_err());
2151 assert!(from_str(r#""yyyy-mm-dd""#).is_err());
2152 assert!(from_str(r#"0"#).is_err());
2153 assert!(from_str(r#"20.01"#).is_err());
2154 assert!(from_str(&i32::MIN.to_string()).is_err());
2155 assert!(from_str(&i32::MAX.to_string()).is_err());
2156 assert!(from_str(&i64::MIN.to_string()).is_err());
2157 assert!(from_str(&i64::MAX.to_string()).is_err());
2158 assert!(from_str(r#"{}"#).is_err());
2159 // pre-0.3.0 rustc-serialize format is now invalid
2160 assert!(from_str(r#"{"ymdf":20}"#).is_err());
2161 assert!(from_str(r#"null"#).is_err());
2162}
2163
2164#[cfg(feature = "rustc-serialize")]
2165#[cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))]
2166mod rustc_serialize {
2167 use super::NaiveDate;
2168 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
2169
2170 impl Encodable for NaiveDate {
2171 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
2172 format!("{:?}", self).encode(s)
2173 }
2174 }
2175
2176 impl Decodable for NaiveDate {
2177 fn decode<D: Decoder>(d: &mut D) -> Result<NaiveDate, D::Error> {
2178 d.read_str()?.parse().map_err(|_| d.error("invalid date"))
2179 }
2180 }
2181
2182 #[cfg(test)]
2183 use rustc_serialize::json;
2184
2185 #[test]
2186 fn test_encodable() {
2187 super::test_encodable_json(json::encode);
2188 }
2189
2190 #[test]
2191 fn test_decodable() {
2192 super::test_decodable_json(json::decode);
2193 }
2194}
2195
2196#[cfg(feature = "serde")]
2197#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
2198mod serde {
2199 use super::NaiveDate;
2200 use core::fmt;
2201 use serde::{de, ser};
2202
2203 // TODO not very optimized for space (binary formats would want something better)
2204
2205 impl ser::Serialize for NaiveDate {
2206 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2207 where
2208 S: ser::Serializer,
2209 {
2210 struct FormatWrapped<'a, D: 'a> {
2211 inner: &'a D,
2212 }
2213
2214 impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> {
2215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2216 self.inner.fmt(f)
2217 }
2218 }
2219
2220 serializer.collect_str(&FormatWrapped { inner: &self })
2221 }
2222 }
2223
2224 struct NaiveDateVisitor;
2225
2226 impl<'de> de::Visitor<'de> for NaiveDateVisitor {
2227 type Value = NaiveDate;
2228
2229 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2230 formatter.write_str("a formatted date string")
2231 }
2232
2233 #[cfg(any(feature = "std", test))]
2234 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2235 where
2236 E: de::Error,
2237 {
2238 value.parse().map_err(E::custom)
2239 }
2240
2241 #[cfg(not(any(feature = "std", test)))]
2242 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2243 where
2244 E: de::Error,
2245 {
2246 value.parse().map_err(E::custom)
2247 }
2248 }
2249
2250 impl<'de> de::Deserialize<'de> for NaiveDate {
2251 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2252 where
2253 D: de::Deserializer<'de>,
2254 {
2255 deserializer.deserialize_str(NaiveDateVisitor)
2256 }
2257 }
2258
2259 #[test]
2260 fn test_serde_serialize() {
2261 super::test_encodable_json(serde_json::to_string);
2262 }
2263
2264 #[test]
2265 fn test_serde_deserialize() {
2266 super::test_decodable_json(|input| serde_json::from_str(input));
2267 }
2268
2269 #[test]
2270 fn test_serde_bincode() {
2271 // Bincode is relevant to test separately from JSON because
2272 // it is not self-describing.
2273 use bincode::{deserialize, serialize};
2274
2275 let d = NaiveDate::from_ymd_opt(2014, 7, 24).unwrap();
2276 let encoded = serialize(&d).unwrap();
2277 let decoded: NaiveDate = deserialize(&encoded).unwrap();
2278 assert_eq!(d, decoded);
2279 }
2280}
2281
2282#[cfg(test)]
2283mod tests {
2284 use super::{
2285 Days, Months, NaiveDate, MAX_DAYS_FROM_YEAR_0, MAX_YEAR, MIN_DAYS_FROM_YEAR_0, MIN_YEAR,
2286 };
2287 use crate::oldtime::Duration;
2288 use crate::{Datelike, Weekday};
2289 use std::{i32, u32};
2290
2291 #[test]
2292 fn diff_months() {
2293 // identity
2294 assert_eq!(
2295 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(0)),
2296 Some(NaiveDate::from_ymd_opt(2022, 8, 3).unwrap())
2297 );
2298
2299 // add with months exceeding `i32::MAX`
2300 assert_eq!(
2301 NaiveDate::from_ymd_opt(2022, 8, 3)
2302 .unwrap()
2303 .checked_add_months(Months::new(i32::MAX as u32 + 1)),
2304 None
2305 );
2306
2307 // sub with months exceeding `i32::MIN`
2308 assert_eq!(
2309 NaiveDate::from_ymd_opt(2022, 8, 3)
2310 .unwrap()
2311 .checked_sub_months(Months::new(i32::MIN.unsigned_abs() + 1)),
2312 None
2313 );
2314
2315 // add overflowing year
2316 assert_eq!(NaiveDate::MAX.checked_add_months(Months::new(1)), None);
2317
2318 // add underflowing year
2319 assert_eq!(NaiveDate::MIN.checked_sub_months(Months::new(1)), None);
2320
2321 // sub crossing year 0 boundary
2322 assert_eq!(
2323 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(2050 * 12)),
2324 Some(NaiveDate::from_ymd_opt(-28, 8, 3).unwrap())
2325 );
2326
2327 // add crossing year boundary
2328 assert_eq!(
2329 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(6)),
2330 Some(NaiveDate::from_ymd_opt(2023, 2, 3).unwrap())
2331 );
2332
2333 // sub crossing year boundary
2334 assert_eq!(
2335 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(10)),
2336 Some(NaiveDate::from_ymd_opt(2021, 10, 3).unwrap())
2337 );
2338
2339 // add clamping day, non-leap year
2340 assert_eq!(
2341 NaiveDate::from_ymd_opt(2022, 1, 29).unwrap().checked_add_months(Months::new(1)),
2342 Some(NaiveDate::from_ymd_opt(2022, 2, 28).unwrap())
2343 );
2344
2345 // add to leap day
2346 assert_eq!(
2347 NaiveDate::from_ymd_opt(2022, 10, 29).unwrap().checked_add_months(Months::new(16)),
2348 Some(NaiveDate::from_ymd_opt(2024, 2, 29).unwrap())
2349 );
2350
2351 // add into december
2352 assert_eq!(
2353 NaiveDate::from_ymd_opt(2022, 10, 31).unwrap().checked_add_months(Months::new(2)),
2354 Some(NaiveDate::from_ymd_opt(2022, 12, 31).unwrap())
2355 );
2356
2357 // sub into december
2358 assert_eq!(
2359 NaiveDate::from_ymd_opt(2022, 10, 31).unwrap().checked_sub_months(Months::new(10)),
2360 Some(NaiveDate::from_ymd_opt(2021, 12, 31).unwrap())
2361 );
2362
2363 // add into january
2364 assert_eq!(
2365 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_add_months(Months::new(5)),
2366 Some(NaiveDate::from_ymd_opt(2023, 1, 3).unwrap())
2367 );
2368
2369 // sub into january
2370 assert_eq!(
2371 NaiveDate::from_ymd_opt(2022, 8, 3).unwrap().checked_sub_months(Months::new(7)),
2372 Some(NaiveDate::from_ymd_opt(2022, 1, 3).unwrap())
2373 );
2374 }
2375
2376 #[test]
2377 fn test_readme_doomsday() {
2378 for y in NaiveDate::MIN.year()..=NaiveDate::MAX.year() {
2379 // even months
2380 let d4 = NaiveDate::from_ymd_opt(y, 4, 4).unwrap();
2381 let d6 = NaiveDate::from_ymd_opt(y, 6, 6).unwrap();
2382 let d8 = NaiveDate::from_ymd_opt(y, 8, 8).unwrap();
2383 let d10 = NaiveDate::from_ymd_opt(y, 10, 10).unwrap();
2384 let d12 = NaiveDate::from_ymd_opt(y, 12, 12).unwrap();
2385
2386 // nine to five, seven-eleven
2387 let d59 = NaiveDate::from_ymd_opt(y, 5, 9).unwrap();
2388 let d95 = NaiveDate::from_ymd_opt(y, 9, 5).unwrap();
2389 let d711 = NaiveDate::from_ymd_opt(y, 7, 11).unwrap();
2390 let d117 = NaiveDate::from_ymd_opt(y, 11, 7).unwrap();
2391
2392 // "March 0"
2393 let d30 = NaiveDate::from_ymd_opt(y, 3, 1).unwrap().pred_opt().unwrap();
2394
2395 let weekday = d30.weekday();
2396 let other_dates = [d4, d6, d8, d10, d12, d59, d95, d711, d117];
2397 assert!(other_dates.iter().all(|d| d.weekday() == weekday));
2398 }
2399 }
2400
2401 #[test]
2402 fn test_date_from_ymd() {
2403 let ymd_opt = NaiveDate::from_ymd_opt;
2404
2405 assert!(ymd_opt(2012, 0, 1).is_none());
2406 assert!(ymd_opt(2012, 1, 1).is_some());
2407 assert!(ymd_opt(2012, 2, 29).is_some());
2408 assert!(ymd_opt(2014, 2, 29).is_none());
2409 assert!(ymd_opt(2014, 3, 0).is_none());
2410 assert!(ymd_opt(2014, 3, 1).is_some());
2411 assert!(ymd_opt(2014, 3, 31).is_some());
2412 assert!(ymd_opt(2014, 3, 32).is_none());
2413 assert!(ymd_opt(2014, 12, 31).is_some());
2414 assert!(ymd_opt(2014, 13, 1).is_none());
2415 }
2416
2417 #[test]
2418 fn test_date_from_yo() {
2419 let yo_opt = NaiveDate::from_yo_opt;
2420 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2421
2422 assert_eq!(yo_opt(2012, 0), None);
2423 assert_eq!(yo_opt(2012, 1), Some(ymd(2012, 1, 1)));
2424 assert_eq!(yo_opt(2012, 2), Some(ymd(2012, 1, 2)));
2425 assert_eq!(yo_opt(2012, 32), Some(ymd(2012, 2, 1)));
2426 assert_eq!(yo_opt(2012, 60), Some(ymd(2012, 2, 29)));
2427 assert_eq!(yo_opt(2012, 61), Some(ymd(2012, 3, 1)));
2428 assert_eq!(yo_opt(2012, 100), Some(ymd(2012, 4, 9)));
2429 assert_eq!(yo_opt(2012, 200), Some(ymd(2012, 7, 18)));
2430 assert_eq!(yo_opt(2012, 300), Some(ymd(2012, 10, 26)));
2431 assert_eq!(yo_opt(2012, 366), Some(ymd(2012, 12, 31)));
2432 assert_eq!(yo_opt(2012, 367), None);
2433
2434 assert_eq!(yo_opt(2014, 0), None);
2435 assert_eq!(yo_opt(2014, 1), Some(ymd(2014, 1, 1)));
2436 assert_eq!(yo_opt(2014, 2), Some(ymd(2014, 1, 2)));
2437 assert_eq!(yo_opt(2014, 32), Some(ymd(2014, 2, 1)));
2438 assert_eq!(yo_opt(2014, 59), Some(ymd(2014, 2, 28)));
2439 assert_eq!(yo_opt(2014, 60), Some(ymd(2014, 3, 1)));
2440 assert_eq!(yo_opt(2014, 100), Some(ymd(2014, 4, 10)));
2441 assert_eq!(yo_opt(2014, 200), Some(ymd(2014, 7, 19)));
2442 assert_eq!(yo_opt(2014, 300), Some(ymd(2014, 10, 27)));
2443 assert_eq!(yo_opt(2014, 365), Some(ymd(2014, 12, 31)));
2444 assert_eq!(yo_opt(2014, 366), None);
2445 }
2446
2447 #[test]
2448 fn test_date_from_isoywd() {
2449 let isoywd_opt = NaiveDate::from_isoywd_opt;
2450 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2451
2452 assert_eq!(isoywd_opt(2004, 0, Weekday::Sun), None);
2453 assert_eq!(isoywd_opt(2004, 1, Weekday::Mon), Some(ymd(2003, 12, 29)));
2454 assert_eq!(isoywd_opt(2004, 1, Weekday::Sun), Some(ymd(2004, 1, 4)));
2455 assert_eq!(isoywd_opt(2004, 2, Weekday::Mon), Some(ymd(2004, 1, 5)));
2456 assert_eq!(isoywd_opt(2004, 2, Weekday::Sun), Some(ymd(2004, 1, 11)));
2457 assert_eq!(isoywd_opt(2004, 52, Weekday::Mon), Some(ymd(2004, 12, 20)));
2458 assert_eq!(isoywd_opt(2004, 52, Weekday::Sun), Some(ymd(2004, 12, 26)));
2459 assert_eq!(isoywd_opt(2004, 53, Weekday::Mon), Some(ymd(2004, 12, 27)));
2460 assert_eq!(isoywd_opt(2004, 53, Weekday::Sun), Some(ymd(2005, 1, 2)));
2461 assert_eq!(isoywd_opt(2004, 54, Weekday::Mon), None);
2462
2463 assert_eq!(isoywd_opt(2011, 0, Weekday::Sun), None);
2464 assert_eq!(isoywd_opt(2011, 1, Weekday::Mon), Some(ymd(2011, 1, 3)));
2465 assert_eq!(isoywd_opt(2011, 1, Weekday::Sun), Some(ymd(2011, 1, 9)));
2466 assert_eq!(isoywd_opt(2011, 2, Weekday::Mon), Some(ymd(2011, 1, 10)));
2467 assert_eq!(isoywd_opt(2011, 2, Weekday::Sun), Some(ymd(2011, 1, 16)));
2468
2469 assert_eq!(isoywd_opt(2018, 51, Weekday::Mon), Some(ymd(2018, 12, 17)));
2470 assert_eq!(isoywd_opt(2018, 51, Weekday::Sun), Some(ymd(2018, 12, 23)));
2471 assert_eq!(isoywd_opt(2018, 52, Weekday::Mon), Some(ymd(2018, 12, 24)));
2472 assert_eq!(isoywd_opt(2018, 52, Weekday::Sun), Some(ymd(2018, 12, 30)));
2473 assert_eq!(isoywd_opt(2018, 53, Weekday::Mon), None);
2474 }
2475
2476 #[test]
2477 fn test_date_from_isoywd_and_iso_week() {
2478 for year in 2000..2401 {
2479 for week in 1..54 {
2480 for &weekday in [
2481 Weekday::Mon,
2482 Weekday::Tue,
2483 Weekday::Wed,
2484 Weekday::Thu,
2485 Weekday::Fri,
2486 Weekday::Sat,
2487 Weekday::Sun,
2488 ]
2489 .iter()
2490 {
2491 let d = NaiveDate::from_isoywd_opt(year, week, weekday);
2492 if let Some(d) = d {
2493 assert_eq!(d.weekday(), weekday);
2494 let w = d.iso_week();
2495 assert_eq!(w.year(), year);
2496 assert_eq!(w.week(), week);
2497 }
2498 }
2499 }
2500 }
2501
2502 for year in 2000..2401 {
2503 for month in 1..13 {
2504 for day in 1..32 {
2505 let d = NaiveDate::from_ymd_opt(year, month, day);
2506 if let Some(d) = d {
2507 let w = d.iso_week();
2508 let d_ = NaiveDate::from_isoywd_opt(w.year(), w.week(), d.weekday());
2509 assert_eq!(d, d_.unwrap());
2510 }
2511 }
2512 }
2513 }
2514 }
2515
2516 #[test]
2517 fn test_date_from_num_days_from_ce() {
2518 let from_ndays_from_ce = NaiveDate::from_num_days_from_ce_opt;
2519 assert_eq!(from_ndays_from_ce(1), Some(NaiveDate::from_ymd_opt(1, 1, 1).unwrap()));
2520 assert_eq!(from_ndays_from_ce(2), Some(NaiveDate::from_ymd_opt(1, 1, 2).unwrap()));
2521 assert_eq!(from_ndays_from_ce(31), Some(NaiveDate::from_ymd_opt(1, 1, 31).unwrap()));
2522 assert_eq!(from_ndays_from_ce(32), Some(NaiveDate::from_ymd_opt(1, 2, 1).unwrap()));
2523 assert_eq!(from_ndays_from_ce(59), Some(NaiveDate::from_ymd_opt(1, 2, 28).unwrap()));
2524 assert_eq!(from_ndays_from_ce(60), Some(NaiveDate::from_ymd_opt(1, 3, 1).unwrap()));
2525 assert_eq!(from_ndays_from_ce(365), Some(NaiveDate::from_ymd_opt(1, 12, 31).unwrap()));
2526 assert_eq!(from_ndays_from_ce(365 + 1), Some(NaiveDate::from_ymd_opt(2, 1, 1).unwrap()));
2527 assert_eq!(
2528 from_ndays_from_ce(365 * 2 + 1),
2529 Some(NaiveDate::from_ymd_opt(3, 1, 1).unwrap())
2530 );
2531 assert_eq!(
2532 from_ndays_from_ce(365 * 3 + 1),
2533 Some(NaiveDate::from_ymd_opt(4, 1, 1).unwrap())
2534 );
2535 assert_eq!(
2536 from_ndays_from_ce(365 * 4 + 2),
2537 Some(NaiveDate::from_ymd_opt(5, 1, 1).unwrap())
2538 );
2539 assert_eq!(
2540 from_ndays_from_ce(146097 + 1),
2541 Some(NaiveDate::from_ymd_opt(401, 1, 1).unwrap())
2542 );
2543 assert_eq!(
2544 from_ndays_from_ce(146097 * 5 + 1),
2545 Some(NaiveDate::from_ymd_opt(2001, 1, 1).unwrap())
2546 );
2547 assert_eq!(from_ndays_from_ce(719163), Some(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()));
2548 assert_eq!(from_ndays_from_ce(0), Some(NaiveDate::from_ymd_opt(0, 12, 31).unwrap())); // 1 BCE
2549 assert_eq!(from_ndays_from_ce(-365), Some(NaiveDate::from_ymd_opt(0, 1, 1).unwrap()));
2550 assert_eq!(from_ndays_from_ce(-366), Some(NaiveDate::from_ymd_opt(-1, 12, 31).unwrap())); // 2 BCE
2551
2552 for days in (-9999..10001).map(|x| x * 100) {
2553 assert_eq!(from_ndays_from_ce(days).map(|d| d.num_days_from_ce()), Some(days));
2554 }
2555
2556 assert_eq!(from_ndays_from_ce(NaiveDate::MIN.num_days_from_ce()), Some(NaiveDate::MIN));
2557 assert_eq!(from_ndays_from_ce(NaiveDate::MIN.num_days_from_ce() - 1), None);
2558 assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce()), Some(NaiveDate::MAX));
2559 assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce() + 1), None);
2560
2561 assert_eq!(from_ndays_from_ce(i32::MIN), None);
2562 assert_eq!(from_ndays_from_ce(i32::MAX), None);
2563 }
2564
2565 #[test]
2566 fn test_date_from_weekday_of_month_opt() {
2567 let ymwd = NaiveDate::from_weekday_of_month_opt;
2568 assert_eq!(ymwd(2018, 8, Weekday::Tue, 0), None);
2569 assert_eq!(
2570 ymwd(2018, 8, Weekday::Wed, 1),
2571 Some(NaiveDate::from_ymd_opt(2018, 8, 1).unwrap())
2572 );
2573 assert_eq!(
2574 ymwd(2018, 8, Weekday::Thu, 1),
2575 Some(NaiveDate::from_ymd_opt(2018, 8, 2).unwrap())
2576 );
2577 assert_eq!(
2578 ymwd(2018, 8, Weekday::Sun, 1),
2579 Some(NaiveDate::from_ymd_opt(2018, 8, 5).unwrap())
2580 );
2581 assert_eq!(
2582 ymwd(2018, 8, Weekday::Mon, 1),
2583 Some(NaiveDate::from_ymd_opt(2018, 8, 6).unwrap())
2584 );
2585 assert_eq!(
2586 ymwd(2018, 8, Weekday::Tue, 1),
2587 Some(NaiveDate::from_ymd_opt(2018, 8, 7).unwrap())
2588 );
2589 assert_eq!(
2590 ymwd(2018, 8, Weekday::Wed, 2),
2591 Some(NaiveDate::from_ymd_opt(2018, 8, 8).unwrap())
2592 );
2593 assert_eq!(
2594 ymwd(2018, 8, Weekday::Sun, 2),
2595 Some(NaiveDate::from_ymd_opt(2018, 8, 12).unwrap())
2596 );
2597 assert_eq!(
2598 ymwd(2018, 8, Weekday::Thu, 3),
2599 Some(NaiveDate::from_ymd_opt(2018, 8, 16).unwrap())
2600 );
2601 assert_eq!(
2602 ymwd(2018, 8, Weekday::Thu, 4),
2603 Some(NaiveDate::from_ymd_opt(2018, 8, 23).unwrap())
2604 );
2605 assert_eq!(
2606 ymwd(2018, 8, Weekday::Thu, 5),
2607 Some(NaiveDate::from_ymd_opt(2018, 8, 30).unwrap())
2608 );
2609 assert_eq!(
2610 ymwd(2018, 8, Weekday::Fri, 5),
2611 Some(NaiveDate::from_ymd_opt(2018, 8, 31).unwrap())
2612 );
2613 assert_eq!(ymwd(2018, 8, Weekday::Sat, 5), None);
2614 }
2615
2616 #[test]
2617 fn test_date_fields() {
2618 fn check(year: i32, month: u32, day: u32, ordinal: u32) {
2619 let d1 = NaiveDate::from_ymd_opt(year, month, day).unwrap();
2620 assert_eq!(d1.year(), year);
2621 assert_eq!(d1.month(), month);
2622 assert_eq!(d1.day(), day);
2623 assert_eq!(d1.ordinal(), ordinal);
2624
2625 let d2 = NaiveDate::from_yo_opt(year, ordinal).unwrap();
2626 assert_eq!(d2.year(), year);
2627 assert_eq!(d2.month(), month);
2628 assert_eq!(d2.day(), day);
2629 assert_eq!(d2.ordinal(), ordinal);
2630
2631 assert_eq!(d1, d2);
2632 }
2633
2634 check(2012, 1, 1, 1);
2635 check(2012, 1, 2, 2);
2636 check(2012, 2, 1, 32);
2637 check(2012, 2, 29, 60);
2638 check(2012, 3, 1, 61);
2639 check(2012, 4, 9, 100);
2640 check(2012, 7, 18, 200);
2641 check(2012, 10, 26, 300);
2642 check(2012, 12, 31, 366);
2643
2644 check(2014, 1, 1, 1);
2645 check(2014, 1, 2, 2);
2646 check(2014, 2, 1, 32);
2647 check(2014, 2, 28, 59);
2648 check(2014, 3, 1, 60);
2649 check(2014, 4, 10, 100);
2650 check(2014, 7, 19, 200);
2651 check(2014, 10, 27, 300);
2652 check(2014, 12, 31, 365);
2653 }
2654
2655 #[test]
2656 fn test_date_weekday() {
2657 assert_eq!(NaiveDate::from_ymd_opt(1582, 10, 15).unwrap().weekday(), Weekday::Fri);
2658 // May 20, 1875 = ISO 8601 reference date
2659 assert_eq!(NaiveDate::from_ymd_opt(1875, 5, 20).unwrap().weekday(), Weekday::Thu);
2660 assert_eq!(NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().weekday(), Weekday::Sat);
2661 }
2662
2663 #[test]
2664 fn test_date_with_fields() {
2665 let d = NaiveDate::from_ymd_opt(2000, 2, 29).unwrap();
2666 assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd_opt(-400, 2, 29).unwrap()));
2667 assert_eq!(d.with_year(-100), None);
2668 assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd_opt(1600, 2, 29).unwrap()));
2669 assert_eq!(d.with_year(1900), None);
2670 assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap()));
2671 assert_eq!(d.with_year(2001), None);
2672 assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd_opt(2004, 2, 29).unwrap()));
2673 assert_eq!(d.with_year(i32::MAX), None);
2674
2675 let d = NaiveDate::from_ymd_opt(2000, 4, 30).unwrap();
2676 assert_eq!(d.with_month(0), None);
2677 assert_eq!(d.with_month(1), Some(NaiveDate::from_ymd_opt(2000, 1, 30).unwrap()));
2678 assert_eq!(d.with_month(2), None);
2679 assert_eq!(d.with_month(3), Some(NaiveDate::from_ymd_opt(2000, 3, 30).unwrap()));
2680 assert_eq!(d.with_month(4), Some(NaiveDate::from_ymd_opt(2000, 4, 30).unwrap()));
2681 assert_eq!(d.with_month(12), Some(NaiveDate::from_ymd_opt(2000, 12, 30).unwrap()));
2682 assert_eq!(d.with_month(13), None);
2683 assert_eq!(d.with_month(u32::MAX), None);
2684
2685 let d = NaiveDate::from_ymd_opt(2000, 2, 8).unwrap();
2686 assert_eq!(d.with_day(0), None);
2687 assert_eq!(d.with_day(1), Some(NaiveDate::from_ymd_opt(2000, 2, 1).unwrap()));
2688 assert_eq!(d.with_day(29), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap()));
2689 assert_eq!(d.with_day(30), None);
2690 assert_eq!(d.with_day(u32::MAX), None);
2691
2692 let d = NaiveDate::from_ymd_opt(2000, 5, 5).unwrap();
2693 assert_eq!(d.with_ordinal(0), None);
2694 assert_eq!(d.with_ordinal(1), Some(NaiveDate::from_ymd_opt(2000, 1, 1).unwrap()));
2695 assert_eq!(d.with_ordinal(60), Some(NaiveDate::from_ymd_opt(2000, 2, 29).unwrap()));
2696 assert_eq!(d.with_ordinal(61), Some(NaiveDate::from_ymd_opt(2000, 3, 1).unwrap()));
2697 assert_eq!(d.with_ordinal(366), Some(NaiveDate::from_ymd_opt(2000, 12, 31).unwrap()));
2698 assert_eq!(d.with_ordinal(367), None);
2699 assert_eq!(d.with_ordinal(u32::MAX), None);
2700 }
2701
2702 #[test]
2703 fn test_date_num_days_from_ce() {
2704 assert_eq!(NaiveDate::from_ymd_opt(1, 1, 1).unwrap().num_days_from_ce(), 1);
2705
2706 for year in -9999..10001 {
2707 assert_eq!(
2708 NaiveDate::from_ymd_opt(year, 1, 1).unwrap().num_days_from_ce(),
2709 NaiveDate::from_ymd_opt(year - 1, 12, 31).unwrap().num_days_from_ce() + 1
2710 );
2711 }
2712 }
2713
2714 #[test]
2715 fn test_date_succ() {
2716 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2717 assert_eq!(ymd(2014, 5, 6).succ_opt(), Some(ymd(2014, 5, 7)));
2718 assert_eq!(ymd(2014, 5, 31).succ_opt(), Some(ymd(2014, 6, 1)));
2719 assert_eq!(ymd(2014, 12, 31).succ_opt(), Some(ymd(2015, 1, 1)));
2720 assert_eq!(ymd(2016, 2, 28).succ_opt(), Some(ymd(2016, 2, 29)));
2721 assert_eq!(ymd(NaiveDate::MAX.year(), 12, 31).succ_opt(), None);
2722 }
2723
2724 #[test]
2725 fn test_date_pred() {
2726 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2727 assert_eq!(ymd(2016, 3, 1).pred_opt(), Some(ymd(2016, 2, 29)));
2728 assert_eq!(ymd(2015, 1, 1).pred_opt(), Some(ymd(2014, 12, 31)));
2729 assert_eq!(ymd(2014, 6, 1).pred_opt(), Some(ymd(2014, 5, 31)));
2730 assert_eq!(ymd(2014, 5, 7).pred_opt(), Some(ymd(2014, 5, 6)));
2731 assert_eq!(ymd(NaiveDate::MIN.year(), 1, 1).pred_opt(), None);
2732 }
2733
2734 #[test]
2735 fn test_date_add() {
2736 fn check((y1, m1, d1): (i32, u32, u32), rhs: Duration, ymd: Option<(i32, u32, u32)>) {
2737 let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap();
2738 let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd_opt(y, m, d).unwrap());
2739 assert_eq!(lhs.checked_add_signed(rhs), sum);
2740 assert_eq!(lhs.checked_sub_signed(-rhs), sum);
2741 }
2742
2743 check((2014, 1, 1), Duration::zero(), Some((2014, 1, 1)));
2744 check((2014, 1, 1), Duration::seconds(86399), Some((2014, 1, 1)));
2745 // always round towards zero
2746 check((2014, 1, 1), Duration::seconds(-86399), Some((2014, 1, 1)));
2747 check((2014, 1, 1), Duration::days(1), Some((2014, 1, 2)));
2748 check((2014, 1, 1), Duration::days(-1), Some((2013, 12, 31)));
2749 check((2014, 1, 1), Duration::days(364), Some((2014, 12, 31)));
2750 check((2014, 1, 1), Duration::days(365 * 4 + 1), Some((2018, 1, 1)));
2751 check((2014, 1, 1), Duration::days(365 * 400 + 97), Some((2414, 1, 1)));
2752
2753 check((-7, 1, 1), Duration::days(365 * 12 + 3), Some((5, 1, 1)));
2754
2755 // overflow check
2756 check((0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64), Some((MAX_YEAR, 12, 31)));
2757 check((0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64 + 1), None);
2758 check((0, 1, 1), Duration::max_value(), None);
2759 check((0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64), Some((MIN_YEAR, 1, 1)));
2760 check((0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64 - 1), None);
2761 check((0, 1, 1), Duration::min_value(), None);
2762 }
2763
2764 #[test]
2765 fn test_date_sub() {
2766 fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: Duration) {
2767 let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap();
2768 let rhs = NaiveDate::from_ymd_opt(y2, m2, d2).unwrap();
2769 assert_eq!(lhs.signed_duration_since(rhs), diff);
2770 assert_eq!(rhs.signed_duration_since(lhs), -diff);
2771 }
2772
2773 check((2014, 1, 1), (2014, 1, 1), Duration::zero());
2774 check((2014, 1, 2), (2014, 1, 1), Duration::days(1));
2775 check((2014, 12, 31), (2014, 1, 1), Duration::days(364));
2776 check((2015, 1, 3), (2014, 1, 1), Duration::days(365 + 2));
2777 check((2018, 1, 1), (2014, 1, 1), Duration::days(365 * 4 + 1));
2778 check((2414, 1, 1), (2014, 1, 1), Duration::days(365 * 400 + 97));
2779
2780 check((MAX_YEAR, 12, 31), (0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64));
2781 check((MIN_YEAR, 1, 1), (0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64));
2782 }
2783
2784 #[test]
2785 fn test_date_add_days() {
2786 fn check((y1, m1, d1): (i32, u32, u32), rhs: Days, ymd: Option<(i32, u32, u32)>) {
2787 let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap();
2788 let sum = ymd.map(|(y, m, d)| NaiveDate::from_ymd_opt(y, m, d).unwrap());
2789 assert_eq!(lhs.checked_add_days(rhs), sum);
2790 }
2791
2792 check((2014, 1, 1), Days::new(0), Some((2014, 1, 1)));
2793 // always round towards zero
2794 check((2014, 1, 1), Days::new(1), Some((2014, 1, 2)));
2795 check((2014, 1, 1), Days::new(364), Some((2014, 12, 31)));
2796 check((2014, 1, 1), Days::new(365 * 4 + 1), Some((2018, 1, 1)));
2797 check((2014, 1, 1), Days::new(365 * 400 + 97), Some((2414, 1, 1)));
2798
2799 check((-7, 1, 1), Days::new(365 * 12 + 3), Some((5, 1, 1)));
2800
2801 // overflow check
2802 check(
2803 (0, 1, 1),
2804 Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()),
2805 Some((MAX_YEAR, 12, 31)),
2806 );
2807 check((0, 1, 1), Days::new(u64::try_from(MAX_DAYS_FROM_YEAR_0).unwrap() + 1), None);
2808 }
2809
2810 #[test]
2811 fn test_date_sub_days() {
2812 fn check((y1, m1, d1): (i32, u32, u32), (y2, m2, d2): (i32, u32, u32), diff: Days) {
2813 let lhs = NaiveDate::from_ymd_opt(y1, m1, d1).unwrap();
2814 let rhs = NaiveDate::from_ymd_opt(y2, m2, d2).unwrap();
2815 assert_eq!(lhs - diff, rhs);
2816 }
2817
2818 check((2014, 1, 1), (2014, 1, 1), Days::new(0));
2819 check((2014, 1, 2), (2014, 1, 1), Days::new(1));
2820 check((2014, 12, 31), (2014, 1, 1), Days::new(364));
2821 check((2015, 1, 3), (2014, 1, 1), Days::new(365 + 2));
2822 check((2018, 1, 1), (2014, 1, 1), Days::new(365 * 4 + 1));
2823 check((2414, 1, 1), (2014, 1, 1), Days::new(365 * 400 + 97));
2824
2825 check((MAX_YEAR, 12, 31), (0, 1, 1), Days::new(MAX_DAYS_FROM_YEAR_0.try_into().unwrap()));
2826 check((0, 1, 1), (MIN_YEAR, 1, 1), Days::new((-MIN_DAYS_FROM_YEAR_0).try_into().unwrap()));
2827 }
2828
2829 #[test]
2830 fn test_date_addassignment() {
2831 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2832 let mut date = ymd(2016, 10, 1);
2833 date += Duration::days(10);
2834 assert_eq!(date, ymd(2016, 10, 11));
2835 date += Duration::days(30);
2836 assert_eq!(date, ymd(2016, 11, 10));
2837 }
2838
2839 #[test]
2840 fn test_date_subassignment() {
2841 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2842 let mut date = ymd(2016, 10, 11);
2843 date -= Duration::days(10);
2844 assert_eq!(date, ymd(2016, 10, 1));
2845 date -= Duration::days(2);
2846 assert_eq!(date, ymd(2016, 9, 29));
2847 }
2848
2849 #[test]
2850 fn test_date_fmt() {
2851 assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(2012, 3, 4).unwrap()), "2012-03-04");
2852 assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(0, 3, 4).unwrap()), "0000-03-04");
2853 assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(-307, 3, 4).unwrap()), "-0307-03-04");
2854 assert_eq!(format!("{:?}", NaiveDate::from_ymd_opt(12345, 3, 4).unwrap()), "+12345-03-04");
2855
2856 assert_eq!(NaiveDate::from_ymd_opt(2012, 3, 4).unwrap().to_string(), "2012-03-04");
2857 assert_eq!(NaiveDate::from_ymd_opt(0, 3, 4).unwrap().to_string(), "0000-03-04");
2858 assert_eq!(NaiveDate::from_ymd_opt(-307, 3, 4).unwrap().to_string(), "-0307-03-04");
2859 assert_eq!(NaiveDate::from_ymd_opt(12345, 3, 4).unwrap().to_string(), "+12345-03-04");
2860
2861 // the format specifier should have no effect on `NaiveTime`
2862 assert_eq!(format!("{:+30?}", NaiveDate::from_ymd_opt(1234, 5, 6).unwrap()), "1234-05-06");
2863 assert_eq!(
2864 format!("{:30?}", NaiveDate::from_ymd_opt(12345, 6, 7).unwrap()),
2865 "+12345-06-07"
2866 );
2867 }
2868
2869 #[test]
2870 fn test_date_from_str() {
2871 // valid cases
2872 let valid = [
2873 "-0000000123456-1-2",
2874 " -123456 - 1 - 2 ",
2875 "-12345-1-2",
2876 "-1234-12-31",
2877 "-7-6-5",
2878 "350-2-28",
2879 "360-02-29",
2880 "0360-02-29",
2881 "2015-2 -18",
2882 "+70-2-18",
2883 "+70000-2-18",
2884 "+00007-2-18",
2885 ];
2886 for &s in &valid {
2887 let d = match s.parse::<NaiveDate>() {
2888 Ok(d) => d,
2889 Err(e) => panic!("parsing `{}` has failed: {}", s, e),
2890 };
2891 let s_ = format!("{:?}", d);
2892 // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same
2893 let d_ = match s_.parse::<NaiveDate>() {
2894 Ok(d) => d,
2895 Err(e) => {
2896 panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}", s, d, e)
2897 }
2898 };
2899 assert!(
2900 d == d_,
2901 "`{}` is parsed into `{:?}`, but reparsed result \
2902 `{:?}` does not match",
2903 s,
2904 d,
2905 d_
2906 );
2907 }
2908
2909 // some invalid cases
2910 // since `ParseErrorKind` is private, all we can do is to check if there was an error
2911 assert!("".parse::<NaiveDate>().is_err());
2912 assert!("x".parse::<NaiveDate>().is_err());
2913 assert!("2014".parse::<NaiveDate>().is_err());
2914 assert!("2014-01".parse::<NaiveDate>().is_err());
2915 assert!("2014-01-00".parse::<NaiveDate>().is_err());
2916 assert!("2014-13-57".parse::<NaiveDate>().is_err());
2917 assert!("9999999-9-9".parse::<NaiveDate>().is_err()); // out-of-bounds
2918 }
2919
2920 #[test]
2921 fn test_date_parse_from_str() {
2922 let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
2923 assert_eq!(
2924 NaiveDate::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
2925 Ok(ymd(2014, 5, 7))
2926 ); // ignore time and offset
2927 assert_eq!(
2928 NaiveDate::parse_from_str("2015-W06-1=2015-033", "%G-W%V-%u = %Y-%j"),
2929 Ok(ymd(2015, 2, 2))
2930 );
2931 assert_eq!(
2932 NaiveDate::parse_from_str("Fri, 09 Aug 13", "%a, %d %b %y"),
2933 Ok(ymd(2013, 8, 9))
2934 );
2935 assert!(NaiveDate::parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err());
2936 assert!(NaiveDate::parse_from_str("2014-57", "%Y-%m-%d").is_err());
2937 assert!(NaiveDate::parse_from_str("2014", "%Y").is_err()); // insufficient
2938
2939 assert_eq!(
2940 NaiveDate::parse_from_str("2020-01-0", "%Y-%W-%w").ok(),
2941 NaiveDate::from_ymd_opt(2020, 1, 12),
2942 );
2943
2944 assert_eq!(
2945 NaiveDate::parse_from_str("2019-01-0", "%Y-%W-%w").ok(),
2946 NaiveDate::from_ymd_opt(2019, 1, 13),
2947 );
2948 }
2949
2950 #[test]
2951 fn test_date_format() {
2952 let d = NaiveDate::from_ymd_opt(2012, 3, 4).unwrap();
2953 assert_eq!(d.format("%Y,%C,%y,%G,%g").to_string(), "2012,20,12,2012,12");
2954 assert_eq!(d.format("%m,%b,%h,%B").to_string(), "03,Mar,Mar,March");
2955 assert_eq!(d.format("%d,%e").to_string(), "04, 4");
2956 assert_eq!(d.format("%U,%W,%V").to_string(), "10,09,09");
2957 assert_eq!(d.format("%a,%A,%w,%u").to_string(), "Sun,Sunday,0,7");
2958 assert_eq!(d.format("%j").to_string(), "064"); // since 2012 is a leap year
2959 assert_eq!(d.format("%D,%x").to_string(), "03/04/12,03/04/12");
2960 assert_eq!(d.format("%F").to_string(), "2012-03-04");
2961 assert_eq!(d.format("%v").to_string(), " 4-Mar-2012");
2962 assert_eq!(d.format("%t%n%%%n%t").to_string(), "\t\n%\n\t");
2963
2964 // non-four-digit years
2965 assert_eq!(
2966 NaiveDate::from_ymd_opt(12345, 1, 1).unwrap().format("%Y").to_string(),
2967 "+12345"
2968 );
2969 assert_eq!(NaiveDate::from_ymd_opt(1234, 1, 1).unwrap().format("%Y").to_string(), "1234");
2970 assert_eq!(NaiveDate::from_ymd_opt(123, 1, 1).unwrap().format("%Y").to_string(), "0123");
2971 assert_eq!(NaiveDate::from_ymd_opt(12, 1, 1).unwrap().format("%Y").to_string(), "0012");
2972 assert_eq!(NaiveDate::from_ymd_opt(1, 1, 1).unwrap().format("%Y").to_string(), "0001");
2973 assert_eq!(NaiveDate::from_ymd_opt(0, 1, 1).unwrap().format("%Y").to_string(), "0000");
2974 assert_eq!(NaiveDate::from_ymd_opt(-1, 1, 1).unwrap().format("%Y").to_string(), "-0001");
2975 assert_eq!(NaiveDate::from_ymd_opt(-12, 1, 1).unwrap().format("%Y").to_string(), "-0012");
2976 assert_eq!(NaiveDate::from_ymd_opt(-123, 1, 1).unwrap().format("%Y").to_string(), "-0123");
2977 assert_eq!(NaiveDate::from_ymd_opt(-1234, 1, 1).unwrap().format("%Y").to_string(), "-1234");
2978 assert_eq!(
2979 NaiveDate::from_ymd_opt(-12345, 1, 1).unwrap().format("%Y").to_string(),
2980 "-12345"
2981 );
2982
2983 // corner cases
2984 assert_eq!(
2985 NaiveDate::from_ymd_opt(2007, 12, 31).unwrap().format("%G,%g,%U,%W,%V").to_string(),
2986 "2008,08,52,53,01"
2987 );
2988 assert_eq!(
2989 NaiveDate::from_ymd_opt(2010, 1, 3).unwrap().format("%G,%g,%U,%W,%V").to_string(),
2990 "2009,09,01,00,53"
2991 );
2992 }
2993
2994 #[test]
2995 fn test_day_iterator_limit() {
2996 assert_eq!(NaiveDate::from_ymd_opt(262143, 12, 29).unwrap().iter_days().take(4).count(), 2);
2997 assert_eq!(
2998 NaiveDate::from_ymd_opt(-262144, 1, 3).unwrap().iter_days().rev().take(4).count(),
2999 2
3000 );
3001 }
3002
3003 #[test]
3004 fn test_week_iterator_limit() {
3005 assert_eq!(
3006 NaiveDate::from_ymd_opt(262143, 12, 12).unwrap().iter_weeks().take(4).count(),
3007 2
3008 );
3009 assert_eq!(
3010 NaiveDate::from_ymd_opt(-262144, 1, 15).unwrap().iter_weeks().rev().take(4).count(),
3011 2
3012 );
3013 }
3014
3015 #[test]
3016 fn test_naiveweek() {
3017 let date = NaiveDate::from_ymd_opt(2022, 5, 18).unwrap();
3018 let asserts = vec![
3019 (Weekday::Mon, "Mon 2022-05-16", "Sun 2022-05-22"),
3020 (Weekday::Tue, "Tue 2022-05-17", "Mon 2022-05-23"),
3021 (Weekday::Wed, "Wed 2022-05-18", "Tue 2022-05-24"),
3022 (Weekday::Thu, "Thu 2022-05-12", "Wed 2022-05-18"),
3023 (Weekday::Fri, "Fri 2022-05-13", "Thu 2022-05-19"),
3024 (Weekday::Sat, "Sat 2022-05-14", "Fri 2022-05-20"),
3025 (Weekday::Sun, "Sun 2022-05-15", "Sat 2022-05-21"),
3026 ];
3027 for (start, first_day, last_day) in asserts {
3028 let week = date.week(start);
3029 let days = week.days();
3030 assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%a %Y-%m-%d"));
3031 assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%a %Y-%m-%d"));
3032 assert!(days.contains(&date));
3033 }
3034 }
3035
3036 #[test]
3037 fn test_naiveweek_min_max() {
3038 let date_max = NaiveDate::MAX;
3039 assert!(date_max.week(Weekday::Mon).first_day() <= date_max);
3040 let date_min = NaiveDate::MIN;
3041 assert!(date_min.week(Weekday::Mon).last_day() >= date_min);
3042 }
3043
3044 #[test]
3045 fn test_weeks_from() {
3046 // tests per: https://github.com/chronotope/chrono/issues/961
3047 // these internally use `weeks_from` via the parsing infrastructure
3048 assert_eq!(
3049 NaiveDate::parse_from_str("2020-01-0", "%Y-%W-%w").ok(),
3050 NaiveDate::from_ymd_opt(2020, 1, 12),
3051 );
3052 assert_eq!(
3053 NaiveDate::parse_from_str("2019-01-0", "%Y-%W-%w").ok(),
3054 NaiveDate::from_ymd_opt(2019, 1, 13),
3055 );
3056
3057 // direct tests
3058 for (y, starts_on) in &[
3059 (2019, Weekday::Tue),
3060 (2020, Weekday::Wed),
3061 (2021, Weekday::Fri),
3062 (2022, Weekday::Sat),
3063 (2023, Weekday::Sun),
3064 (2024, Weekday::Mon),
3065 (2025, Weekday::Wed),
3066 (2026, Weekday::Thu),
3067 ] {
3068 for day in &[
3069 Weekday::Mon,
3070 Weekday::Tue,
3071 Weekday::Wed,
3072 Weekday::Thu,
3073 Weekday::Fri,
3074 Weekday::Sat,
3075 Weekday::Sun,
3076 ] {
3077 assert_eq!(
3078 NaiveDate::from_ymd_opt(*y, 1, 1).map(|d| d.weeks_from(*day)),
3079 Some(if day == starts_on { 1 } else { 0 })
3080 );
3081
3082 // last day must always be in week 52 or 53
3083 assert!([52, 53]
3084 .contains(&NaiveDate::from_ymd_opt(*y, 12, 31).unwrap().weeks_from(*day)),);
3085 }
3086 }
3087
3088 let base = NaiveDate::from_ymd_opt(2019, 1, 1).unwrap();
3089
3090 // 400 years covers all year types
3091 for day in &[
3092 Weekday::Mon,
3093 Weekday::Tue,
3094 Weekday::Wed,
3095 Weekday::Thu,
3096 Weekday::Fri,
3097 Weekday::Sat,
3098 Weekday::Sun,
3099 ] {
3100 // must always be below 54
3101 for dplus in 1..(400 * 366) {
3102 assert!((base + Days::new(dplus)).weeks_from(*day) < 54)
3103 }
3104 }
3105 }
3106
3107 #[test]
3108 fn test_with_0_overflow() {
3109 let dt = NaiveDate::from_ymd_opt(2023, 4, 18).unwrap();
3110 assert!(dt.with_month0(4294967295).is_none());
3111 assert!(dt.with_day0(4294967295).is_none());
3112 assert!(dt.with_ordinal0(4294967295).is_none());
3113 }
3114}
3115