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