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