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