]> git.proxmox.com Git - rustc.git/blame - src/vendor/chrono/src/naive/date.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / 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
6use std::{str, fmt, hash};
7use std::ops::{Add, Sub, AddAssign, SubAssign};
8use num::traits::ToPrimitive;
9use oldtime::Duration as OldDuration;
10
11use {Weekday, Datelike};
12use div::div_mod_floor;
13use naive::{NaiveTime, NaiveDateTime, IsoWeek};
14use format::{Item, Numeric, Pad};
15use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
16
17use super::isoweek;
18use super::internals::{self, DateImpl, Of, Mdf, YearFlags};
19
20const MAX_YEAR: i32 = internals::MAX_YEAR;
21const MIN_YEAR: i32 = internals::MIN_YEAR;
22
23// MAX_YEAR-12-31 minus 0000-01-01
24// = ((MAX_YEAR+1)-01-01 minus 0001-01-01) + (0001-01-01 minus 0000-01-01) - 1 day
25// = ((MAX_YEAR+1)-01-01 minus 0001-01-01) + 365 days
26// = MAX_YEAR * 365 + (# of leap years from 0001 to MAX_YEAR) + 365 days
27#[cfg(test)] // only used for testing
28const MAX_DAYS_FROM_YEAR_0: i32 = MAX_YEAR * 365 +
29 MAX_YEAR / 4 -
30 MAX_YEAR / 100 +
31 MAX_YEAR / 400 + 365;
32
33// MIN_YEAR-01-01 minus 0000-01-01
34// = (MIN_YEAR+400n+1)-01-01 minus (400n+1)-01-01
35// = ((MIN_YEAR+400n+1)-01-01 minus 0001-01-01) - ((400n+1)-01-01 minus 0001-01-01)
36// = ((MIN_YEAR+400n+1)-01-01 minus 0001-01-01) - 146097n days
37//
38// n is set to 1000 for convenience.
39#[cfg(test)] // only used for testing
40const MIN_DAYS_FROM_YEAR_0: i32 = (MIN_YEAR + 400_000) * 365 +
41 (MIN_YEAR + 400_000) / 4 -
42 (MIN_YEAR + 400_000) / 100 +
43 (MIN_YEAR + 400_000) / 400 - 146097_000;
44
45#[cfg(test)] // only used for testing, but duplicated in naive::datetime
46const MAX_BITS: usize = 44;
47
48/// ISO 8601 calendar date without timezone.
49/// Allows for every [proleptic Gregorian date](#calendar-date)
50/// from Jan 1, 262145 BCE to Dec 31, 262143 CE.
51/// Also supports the conversion from ISO 8601 ordinal and week date.
52///
53/// # Calendar Date
54///
55/// The ISO 8601 **calendar date** follows the proleptic Gregorian calendar.
56/// It is like a normal civil calendar but note some slight differences:
57///
58/// * Dates before the Gregorian calendar's inception in 1582 are defined via the extrapolation.
59/// Be careful, as historical dates are often noted in the Julian calendar and others
60/// and the transition to Gregorian may differ across countries (as late as early 20C).
61///
62/// (Some example: Both Shakespeare from Britain and Cervantes from Spain seemingly died
63/// on the same calendar date---April 23, 1616---but in the different calendar.
64/// Britain used the Julian calendar at that time, so Shakespeare's death is later.)
65///
66/// * ISO 8601 calendars has the year 0, which is 1 BCE (a year before 1 CE).
67/// If you need a typical BCE/BC and CE/AD notation for year numbers,
68/// use the [`Datelike::year_ce`](../trait.Datelike.html#method.year_ce) method.
69///
70/// # Week Date
71///
72/// The ISO 8601 **week date** is a triple of year number, week number
73/// and [day of the week](../enum.Weekday.html) with the following rules:
74///
75/// * A week consists of Monday through Sunday, and is always numbered within some year.
76/// The week number ranges from 1 to 52 or 53 depending on the year.
77///
78/// * The week 1 of given year is defined as the first week containing January 4 of that year,
79/// or equivalently, the first week containing four or more days in that year.
80///
81/// * The year number in the week date may *not* correspond to the actual Gregorian year.
82/// For example, January 3, 2016 (Sunday) was on the last (53rd) week of 2015.
83///
84/// Chrono's date types default to the ISO 8601 [calendar date](#calendar-date),
85/// but [`Datelike::iso_week`](../trait.Datelike.html#tymethod.iso_week) and
86/// [`Datelike::weekday`](../trait.Datelike.html#tymethod.weekday) methods
87/// can be used to get the corresponding week date.
88///
89/// # Ordinal Date
90///
91/// The ISO 8601 **ordinal date** is a pair of year number and day of the year ("ordinal").
92/// The ordinal number ranges from 1 to 365 or 366 depending on the year.
93/// The year number is same to that of the [calendar date](#calendar-date).
94///
95/// This is currently the internal format of Chrono's date types.
96#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
97pub struct NaiveDate {
98 ymdf: DateImpl, // (year << 13) | of
99}
100
101/// The minimum possible `NaiveDate` (January 1, 262145 BCE).
102pub const MIN_DATE: NaiveDate = NaiveDate { ymdf: (MIN_YEAR << 13) | (1 << 4) | 0o07 /*FE*/ };
103/// The maximum possible `NaiveDate` (December 31, 262143 CE).
104pub const MAX_DATE: NaiveDate = NaiveDate { ymdf: (MAX_YEAR << 13) | (365 << 4) | 0o17 /*F*/ };
105
106// as it is hard to verify year flags in `MIN_DATE` and `MAX_DATE`,
107// we use a separate run-time test.
108#[test]
109fn test_date_bounds() {
110 let calculated_min = NaiveDate::from_ymd(MIN_YEAR, 1, 1);
111 let calculated_max = NaiveDate::from_ymd(MAX_YEAR, 12, 31);
112 assert!(MIN_DATE == calculated_min,
113 "`MIN_DATE` should have a year flag {:?}", calculated_min.of().flags());
114 assert!(MAX_DATE == calculated_max,
115 "`MAX_DATE` should have a year flag {:?}", calculated_max.of().flags());
116
117 // let's also check that the entire range do not exceed 2^44 seconds
118 // (sometimes used for bounding `Duration` against overflow)
119 let maxsecs = MAX_DATE.signed_duration_since(MIN_DATE).num_seconds();
120 let maxsecs = maxsecs + 86401; // also take care of DateTime
121 assert!(maxsecs < (1 << MAX_BITS),
122 "The entire `NaiveDate` range somehow exceeds 2^{} seconds", MAX_BITS);
123}
124
125impl NaiveDate {
126 /// Makes a new `NaiveDate` from year and packed ordinal-flags, with a verification.
127 fn from_of(year: i32, of: Of) -> Option<NaiveDate> {
128 if year >= MIN_YEAR && year <= MAX_YEAR && of.valid() {
129 let Of(of) = of;
130 Some(NaiveDate { ymdf: (year << 13) | (of as DateImpl) })
131 } else {
132 None
133 }
134 }
135
136 /// Makes a new `NaiveDate` from year and packed month-day-flags, with a verification.
137 fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
138 NaiveDate::from_of(year, mdf.to_of())
139 }
140
141 /// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
142 /// (year, month and day).
143 ///
144 /// Panics on the out-of-range date, invalid month and/or day.
145 ///
146 /// # Example
147 ///
148 /// ~~~~
149 /// use chrono::{NaiveDate, Datelike, Weekday};
150 ///
151 /// let d = NaiveDate::from_ymd(2015, 3, 14);
152 /// assert_eq!(d.year(), 2015);
153 /// assert_eq!(d.month(), 3);
154 /// assert_eq!(d.day(), 14);
155 /// assert_eq!(d.ordinal(), 73); // day of year
156 /// assert_eq!(d.iso_week().year(), 2015);
157 /// assert_eq!(d.iso_week().week(), 11);
158 /// assert_eq!(d.weekday(), Weekday::Sat);
159 /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE
160 /// ~~~~
161 pub fn from_ymd(year: i32, month: u32, day: u32) -> NaiveDate {
162 NaiveDate::from_ymd_opt(year, month, day).expect("invalid or out-of-range date")
163 }
164
165 /// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
166 /// (year, month and day).
167 ///
168 /// Returns `None` on the out-of-range date, invalid month and/or day.
169 ///
170 /// # Example
171 ///
172 /// ~~~~
173 /// use chrono::NaiveDate;
174 ///
175 /// let from_ymd_opt = NaiveDate::from_ymd_opt;
176 ///
177 /// assert!(from_ymd_opt(2015, 3, 14).is_some());
178 /// assert!(from_ymd_opt(2015, 0, 14).is_none());
179 /// assert!(from_ymd_opt(2015, 2, 29).is_none());
180 /// assert!(from_ymd_opt(-4, 2, 29).is_some()); // 5 BCE is a leap year
181 /// assert!(from_ymd_opt(400000, 1, 1).is_none());
182 /// assert!(from_ymd_opt(-400000, 1, 1).is_none());
183 /// ~~~~
184 pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
185 let flags = YearFlags::from_year(year);
186 NaiveDate::from_mdf(year, Mdf::new(month, day, flags))
187 }
188
189 /// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date)
190 /// (year and day of the year).
191 ///
192 /// Panics on the out-of-range date and/or invalid day of year.
193 ///
194 /// # Example
195 ///
196 /// ~~~~
197 /// use chrono::{NaiveDate, Datelike, Weekday};
198 ///
199 /// let d = NaiveDate::from_yo(2015, 73);
200 /// assert_eq!(d.ordinal(), 73);
201 /// assert_eq!(d.year(), 2015);
202 /// assert_eq!(d.month(), 3);
203 /// assert_eq!(d.day(), 14);
204 /// assert_eq!(d.iso_week().year(), 2015);
205 /// assert_eq!(d.iso_week().week(), 11);
206 /// assert_eq!(d.weekday(), Weekday::Sat);
207 /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE
208 /// ~~~~
209 pub fn from_yo(year: i32, ordinal: u32) -> NaiveDate {
210 NaiveDate::from_yo_opt(year, ordinal).expect("invalid or out-of-range date")
211 }
212
213 /// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date)
214 /// (year and day of the year).
215 ///
216 /// Returns `None` on the out-of-range date and/or invalid day of year.
217 ///
218 /// # Example
219 ///
220 /// ~~~~
221 /// use chrono::NaiveDate;
222 ///
223 /// let from_yo_opt = NaiveDate::from_yo_opt;
224 ///
225 /// assert!(from_yo_opt(2015, 100).is_some());
226 /// assert!(from_yo_opt(2015, 0).is_none());
227 /// assert!(from_yo_opt(2015, 365).is_some());
228 /// assert!(from_yo_opt(2015, 366).is_none());
229 /// assert!(from_yo_opt(-4, 366).is_some()); // 5 BCE is a leap year
230 /// assert!(from_yo_opt(400000, 1).is_none());
231 /// assert!(from_yo_opt(-400000, 1).is_none());
232 /// ~~~~
233 pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> {
234 let flags = YearFlags::from_year(year);
235 NaiveDate::from_of(year, Of::new(ordinal, flags))
236 }
237
238 /// Makes a new `NaiveDate` from the [ISO week date](#week-date)
239 /// (year, week number and day of the week).
240 /// The resulting `NaiveDate` may have a different year from the input year.
241 ///
242 /// Panics on the out-of-range date and/or invalid week number.
243 ///
244 /// # Example
245 ///
246 /// ~~~~
247 /// use chrono::{NaiveDate, Datelike, Weekday};
248 ///
249 /// let d = NaiveDate::from_isoywd(2015, 11, Weekday::Sat);
250 /// assert_eq!(d.iso_week().year(), 2015);
251 /// assert_eq!(d.iso_week().week(), 11);
252 /// assert_eq!(d.weekday(), Weekday::Sat);
253 /// assert_eq!(d.year(), 2015);
254 /// assert_eq!(d.month(), 3);
255 /// assert_eq!(d.day(), 14);
256 /// assert_eq!(d.ordinal(), 73); // day of year
257 /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE
258 /// ~~~~
259 pub fn from_isoywd(year: i32, week: u32, weekday: Weekday) -> NaiveDate {
260 NaiveDate::from_isoywd_opt(year, week, weekday).expect("invalid or out-of-range date")
261 }
262
263 /// Makes a new `NaiveDate` from the [ISO week date](#week-date)
264 /// (year, week number and day of the week).
265 /// The resulting `NaiveDate` may have a different year from the input year.
266 ///
267 /// Returns `None` on the out-of-range date and/or invalid week number.
268 ///
269 /// # Example
270 ///
271 /// ~~~~
272 /// use chrono::{NaiveDate, Weekday};
273 ///
274 /// let from_ymd = NaiveDate::from_ymd;
275 /// let from_isoywd_opt = NaiveDate::from_isoywd_opt;
276 ///
277 /// assert_eq!(from_isoywd_opt(2015, 0, Weekday::Sun), None);
278 /// assert_eq!(from_isoywd_opt(2015, 10, Weekday::Sun), Some(from_ymd(2015, 3, 8)));
279 /// assert_eq!(from_isoywd_opt(2015, 30, Weekday::Mon), Some(from_ymd(2015, 7, 20)));
280 /// assert_eq!(from_isoywd_opt(2015, 60, Weekday::Mon), None);
281 ///
282 /// assert_eq!(from_isoywd_opt(400000, 10, Weekday::Fri), None);
283 /// assert_eq!(from_isoywd_opt(-400000, 10, Weekday::Sat), None);
284 /// ~~~~
285 ///
286 /// The year number of ISO week date may differ from that of the calendar date.
287 ///
288 /// ~~~~
289 /// # use chrono::{NaiveDate, Weekday};
290 /// # let from_ymd = NaiveDate::from_ymd;
291 /// # let from_isoywd_opt = NaiveDate::from_isoywd_opt;
292 /// // Mo Tu We Th Fr Sa Su
293 /// // 2014-W52 22 23 24 25 26 27 28 has 4+ days of new year,
294 /// // 2015-W01 29 30 31 1 2 3 4 <- so this is the first week
295 /// assert_eq!(from_isoywd_opt(2014, 52, Weekday::Sun), Some(from_ymd(2014, 12, 28)));
296 /// assert_eq!(from_isoywd_opt(2014, 53, Weekday::Mon), None);
297 /// assert_eq!(from_isoywd_opt(2015, 1, Weekday::Mon), Some(from_ymd(2014, 12, 29)));
298 ///
299 /// // 2015-W52 21 22 23 24 25 26 27 has 4+ days of old year,
300 /// // 2015-W53 28 29 30 31 1 2 3 <- so this is the last week
301 /// // 2016-W01 4 5 6 7 8 9 10
302 /// assert_eq!(from_isoywd_opt(2015, 52, Weekday::Sun), Some(from_ymd(2015, 12, 27)));
303 /// assert_eq!(from_isoywd_opt(2015, 53, Weekday::Sun), Some(from_ymd(2016, 1, 3)));
304 /// assert_eq!(from_isoywd_opt(2015, 54, Weekday::Mon), None);
305 /// assert_eq!(from_isoywd_opt(2016, 1, Weekday::Mon), Some(from_ymd(2016, 1, 4)));
306 /// ~~~~
307 pub fn from_isoywd_opt(year: i32, week: u32, weekday: Weekday) -> Option<NaiveDate> {
308 let flags = YearFlags::from_year(year);
309 let nweeks = flags.nisoweeks();
310 if 1 <= week && week <= nweeks {
311 // ordinal = week ordinal - delta
312 let weekord = week * 7 + weekday as u32;
313 let delta = flags.isoweek_delta();
314 if weekord <= delta { // ordinal < 1, previous year
315 let prevflags = YearFlags::from_year(year - 1);
316 NaiveDate::from_of(year - 1, Of::new(weekord + prevflags.ndays() - delta,
317 prevflags))
318 } else {
319 let ordinal = weekord - delta;
320 let ndays = flags.ndays();
321 if ordinal <= ndays { // this year
322 NaiveDate::from_of(year, Of::new(ordinal, flags))
323 } else { // ordinal > ndays, next year
324 let nextflags = YearFlags::from_year(year + 1);
325 NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags))
326 }
327 }
328 } else {
329 None
330 }
331 }
332
333 /// Makes a new `NaiveDate` from the number of days since January 1, 1 (Day 1)
334 /// in the proleptic Gregorian calendar.
335 ///
336 /// Panics on the out-of-range date.
337 ///
338 /// # Example
339 ///
340 /// ~~~~
341 /// use chrono::{NaiveDate, Datelike, Weekday};
342 ///
343 /// let d = NaiveDate::from_num_days_from_ce(735671);
344 /// assert_eq!(d.num_days_from_ce(), 735671); // days since January 1, 1 CE
345 /// assert_eq!(d.year(), 2015);
346 /// assert_eq!(d.month(), 3);
347 /// assert_eq!(d.day(), 14);
348 /// assert_eq!(d.ordinal(), 73); // day of year
349 /// assert_eq!(d.iso_week().year(), 2015);
350 /// assert_eq!(d.iso_week().week(), 11);
351 /// assert_eq!(d.weekday(), Weekday::Sat);
352 /// ~~~~
353 ///
354 /// While not directly supported by Chrono,
355 /// it is easy to convert from the Julian day number
356 /// (January 1, 4713 BCE in the *Julian* calendar being Day 0)
357 /// to Gregorian with this method.
358 /// (Note that this panics when `jd` is out of range.)
359 ///
360 /// ~~~~
361 /// use chrono::NaiveDate;
362 ///
363 /// fn jd_to_date(jd: i32) -> NaiveDate {
364 /// // keep in mind that the Julian day number is 0-based
365 /// // while this method requires an 1-based number.
366 /// NaiveDate::from_num_days_from_ce(jd - 1721425)
367 /// }
368 ///
369 /// // January 1, 4713 BCE in Julian = November 24, 4714 BCE in Gregorian
370 /// assert_eq!(jd_to_date(0), NaiveDate::from_ymd(-4713, 11, 24));
371 ///
372 /// assert_eq!(jd_to_date(1721426), NaiveDate::from_ymd(1, 1, 1));
373 /// assert_eq!(jd_to_date(2450000), NaiveDate::from_ymd(1995, 10, 9));
374 /// assert_eq!(jd_to_date(2451545), NaiveDate::from_ymd(2000, 1, 1));
375 /// ~~~~
376 #[inline]
377 pub fn from_num_days_from_ce(days: i32) -> NaiveDate {
378 NaiveDate::from_num_days_from_ce_opt(days).expect("out-of-range date")
379 }
380
381 /// Makes a new `NaiveDate` from the number of days since January 1, 1 (Day 1)
382 /// in the proleptic Gregorian calendar.
383 ///
384 /// Returns `None` on the out-of-range date.
385 ///
386 /// # Example
387 ///
388 /// ~~~~
389 /// use chrono::NaiveDate;
390 ///
391 /// let from_ndays_opt = NaiveDate::from_num_days_from_ce_opt;
392 /// let from_ymd = NaiveDate::from_ymd;
393 ///
394 /// assert_eq!(from_ndays_opt(730_000), Some(from_ymd(1999, 9, 3)));
395 /// assert_eq!(from_ndays_opt(1), Some(from_ymd(1, 1, 1)));
396 /// assert_eq!(from_ndays_opt(0), Some(from_ymd(0, 12, 31)));
397 /// assert_eq!(from_ndays_opt(-1), Some(from_ymd(0, 12, 30)));
398 /// assert_eq!(from_ndays_opt(100_000_000), None);
399 /// assert_eq!(from_ndays_opt(-100_000_000), None);
400 /// ~~~~
401 pub fn from_num_days_from_ce_opt(days: i32) -> Option<NaiveDate> {
402 let days = days + 365; // make December 31, 1 BCE equal to day 0
403 let (year_div_400, cycle) = div_mod_floor(days, 146097);
404 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
405 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
406 NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32,
407 Of::new(ordinal, flags))
408 }
409
410 /// Parses a string with the specified format string and returns a new `NaiveDate`.
411 /// See the [`format::strftime` module](../format/strftime/index.html)
412 /// on the supported escape sequences.
413 ///
414 /// # Example
415 ///
416 /// ~~~~
417 /// use chrono::NaiveDate;
418 ///
419 /// let parse_from_str = NaiveDate::parse_from_str;
420 ///
421 /// assert_eq!(parse_from_str("2015-09-05", "%Y-%m-%d"),
422 /// Ok(NaiveDate::from_ymd(2015, 9, 5)));
423 /// assert_eq!(parse_from_str("5sep2015", "%d%b%Y"),
424 /// Ok(NaiveDate::from_ymd(2015, 9, 5)));
425 /// ~~~~
426 ///
427 /// Time and offset is ignored for the purpose of parsing.
428 ///
429 /// ~~~~
430 /// # use chrono::NaiveDate;
431 /// # let parse_from_str = NaiveDate::parse_from_str;
432 /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
433 /// Ok(NaiveDate::from_ymd(2014, 5, 17)));
434 /// ~~~~
435 ///
436 /// Out-of-bound dates or insufficient fields are errors.
437 ///
438 /// ~~~~
439 /// # use chrono::NaiveDate;
440 /// # let parse_from_str = NaiveDate::parse_from_str;
441 /// assert!(parse_from_str("2015/9", "%Y/%m").is_err());
442 /// assert!(parse_from_str("2015/9/31", "%Y/%m/%d").is_err());
443 /// ~~~~
444 ///
445 /// All parsed fields should be consistent to each other, otherwise it's an error.
446 ///
447 /// ~~~~
448 /// # use chrono::NaiveDate;
449 /// # let parse_from_str = NaiveDate::parse_from_str;
450 /// assert!(parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err());
451 /// ~~~~
452 pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDate> {
453 let mut parsed = Parsed::new();
454 try!(parse(&mut parsed, s, StrftimeItems::new(fmt)));
455 parsed.to_naive_date()
456 }
457
458 /// Makes a new `NaiveDateTime` from the current date and given `NaiveTime`.
459 ///
460 /// # Example
461 ///
462 /// ~~~~
463 /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime};
464 ///
465 /// let d = NaiveDate::from_ymd(2015, 6, 3);
466 /// let t = NaiveTime::from_hms_milli(12, 34, 56, 789);
467 ///
468 /// let dt: NaiveDateTime = d.and_time(t);
469 /// assert_eq!(dt.date(), d);
470 /// assert_eq!(dt.time(), t);
471 /// ~~~~
472 #[inline]
473 pub fn and_time(&self, time: NaiveTime) -> NaiveDateTime {
474 NaiveDateTime::new(*self, time)
475 }
476
477 /// Makes a new `NaiveDateTime` from the current date, hour, minute and second.
478 ///
479 /// No [leap second](./struct.NaiveTime.html#leap-second-handling) is allowed here;
480 /// use `NaiveDate::and_hms_*` methods with a subsecond parameter instead.
481 ///
482 /// Panics on invalid hour, minute and/or second.
483 ///
484 /// # Example
485 ///
486 /// ~~~~
487 /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday};
488 ///
489 /// let d = NaiveDate::from_ymd(2015, 6, 3);
490 ///
491 /// let dt: NaiveDateTime = d.and_hms(12, 34, 56);
492 /// assert_eq!(dt.year(), 2015);
493 /// assert_eq!(dt.weekday(), Weekday::Wed);
494 /// assert_eq!(dt.second(), 56);
495 /// ~~~~
496 #[inline]
497 pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> NaiveDateTime {
498 self.and_hms_opt(hour, min, sec).expect("invalid time")
499 }
500
501 /// Makes a new `NaiveDateTime` from the current date, hour, minute and second.
502 ///
503 /// No [leap second](./struct.NaiveTime.html#leap-second-handling) is allowed here;
504 /// use `NaiveDate::and_hms_*_opt` methods with a subsecond parameter instead.
505 ///
506 /// Returns `None` on invalid hour, minute and/or second.
507 ///
508 /// # Example
509 ///
510 /// ~~~~
511 /// use chrono::NaiveDate;
512 ///
513 /// let d = NaiveDate::from_ymd(2015, 6, 3);
514 /// assert!(d.and_hms_opt(12, 34, 56).is_some());
515 /// assert!(d.and_hms_opt(12, 34, 60).is_none()); // use `and_hms_milli_opt` instead
516 /// assert!(d.and_hms_opt(12, 60, 56).is_none());
517 /// assert!(d.and_hms_opt(24, 34, 56).is_none());
518 /// ~~~~
519 #[inline]
520 pub fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> {
521 NaiveTime::from_hms_opt(hour, min, sec).map(|time| self.and_time(time))
522 }
523
524 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and millisecond.
525 ///
526 /// The millisecond part can exceed 1,000
527 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
528 ///
529 /// Panics on invalid hour, minute, second and/or millisecond.
530 ///
531 /// # Example
532 ///
533 /// ~~~~
534 /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday};
535 ///
536 /// let d = NaiveDate::from_ymd(2015, 6, 3);
537 ///
538 /// let dt: NaiveDateTime = d.and_hms_milli(12, 34, 56, 789);
539 /// assert_eq!(dt.year(), 2015);
540 /// assert_eq!(dt.weekday(), Weekday::Wed);
541 /// assert_eq!(dt.second(), 56);
542 /// assert_eq!(dt.nanosecond(), 789_000_000);
543 /// ~~~~
544 #[inline]
545 pub fn and_hms_milli(&self, hour: u32, min: u32, sec: u32, milli: u32) -> NaiveDateTime {
546 self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
547 }
548
549 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and millisecond.
550 ///
551 /// The millisecond part can exceed 1,000
552 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
553 ///
554 /// Returns `None` on invalid hour, minute, second and/or millisecond.
555 ///
556 /// # Example
557 ///
558 /// ~~~~
559 /// use chrono::NaiveDate;
560 ///
561 /// let d = NaiveDate::from_ymd(2015, 6, 3);
562 /// assert!(d.and_hms_milli_opt(12, 34, 56, 789).is_some());
563 /// assert!(d.and_hms_milli_opt(12, 34, 59, 1_789).is_some()); // leap second
564 /// assert!(d.and_hms_milli_opt(12, 34, 59, 2_789).is_none());
565 /// assert!(d.and_hms_milli_opt(12, 34, 60, 789).is_none());
566 /// assert!(d.and_hms_milli_opt(12, 60, 56, 789).is_none());
567 /// assert!(d.and_hms_milli_opt(24, 34, 56, 789).is_none());
568 /// ~~~~
569 #[inline]
570 pub fn and_hms_milli_opt(&self, hour: u32, min: u32, sec: u32,
571 milli: u32) -> Option<NaiveDateTime> {
572 NaiveTime::from_hms_milli_opt(hour, min, sec, milli).map(|time| self.and_time(time))
573 }
574
575 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and microsecond.
576 ///
577 /// The microsecond part can exceed 1,000,000
578 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
579 ///
580 /// Panics on invalid hour, minute, second and/or microsecond.
581 ///
582 /// # Example
583 ///
584 /// ~~~~
585 /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday};
586 ///
587 /// let d = NaiveDate::from_ymd(2015, 6, 3);
588 ///
589 /// let dt: NaiveDateTime = d.and_hms_micro(12, 34, 56, 789_012);
590 /// assert_eq!(dt.year(), 2015);
591 /// assert_eq!(dt.weekday(), Weekday::Wed);
592 /// assert_eq!(dt.second(), 56);
593 /// assert_eq!(dt.nanosecond(), 789_012_000);
594 /// ~~~~
595 #[inline]
596 pub fn and_hms_micro(&self, hour: u32, min: u32, sec: u32, micro: u32) -> NaiveDateTime {
597 self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
598 }
599
600 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and microsecond.
601 ///
602 /// The microsecond part can exceed 1,000,000
603 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
604 ///
605 /// Returns `None` on invalid hour, minute, second and/or microsecond.
606 ///
607 /// # Example
608 ///
609 /// ~~~~
610 /// use chrono::NaiveDate;
611 ///
612 /// let d = NaiveDate::from_ymd(2015, 6, 3);
613 /// assert!(d.and_hms_micro_opt(12, 34, 56, 789_012).is_some());
614 /// assert!(d.and_hms_micro_opt(12, 34, 59, 1_789_012).is_some()); // leap second
615 /// assert!(d.and_hms_micro_opt(12, 34, 59, 2_789_012).is_none());
616 /// assert!(d.and_hms_micro_opt(12, 34, 60, 789_012).is_none());
617 /// assert!(d.and_hms_micro_opt(12, 60, 56, 789_012).is_none());
618 /// assert!(d.and_hms_micro_opt(24, 34, 56, 789_012).is_none());
619 /// ~~~~
620 #[inline]
621 pub fn and_hms_micro_opt(&self, hour: u32, min: u32, sec: u32,
622 micro: u32) -> Option<NaiveDateTime> {
623 NaiveTime::from_hms_micro_opt(hour, min, sec, micro).map(|time| self.and_time(time))
624 }
625
626 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and nanosecond.
627 ///
628 /// The nanosecond part can exceed 1,000,000,000
629 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
630 ///
631 /// Panics on invalid hour, minute, second and/or nanosecond.
632 ///
633 /// # Example
634 ///
635 /// ~~~~
636 /// use chrono::{NaiveDate, NaiveDateTime, Datelike, Timelike, Weekday};
637 ///
638 /// let d = NaiveDate::from_ymd(2015, 6, 3);
639 ///
640 /// let dt: NaiveDateTime = d.and_hms_nano(12, 34, 56, 789_012_345);
641 /// assert_eq!(dt.year(), 2015);
642 /// assert_eq!(dt.weekday(), Weekday::Wed);
643 /// assert_eq!(dt.second(), 56);
644 /// assert_eq!(dt.nanosecond(), 789_012_345);
645 /// ~~~~
646 #[inline]
647 pub fn and_hms_nano(&self, hour: u32, min: u32, sec: u32, nano: u32) -> NaiveDateTime {
648 self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
649 }
650
651 /// Makes a new `NaiveDateTime` from the current date, hour, minute, second and nanosecond.
652 ///
653 /// The nanosecond part can exceed 1,000,000,000
654 /// in order to represent the [leap second](./struct.NaiveTime.html#leap-second-handling).
655 ///
656 /// Returns `None` on invalid hour, minute, second and/or nanosecond.
657 ///
658 /// # Example
659 ///
660 /// ~~~~
661 /// use chrono::NaiveDate;
662 ///
663 /// let d = NaiveDate::from_ymd(2015, 6, 3);
664 /// assert!(d.and_hms_nano_opt(12, 34, 56, 789_012_345).is_some());
665 /// assert!(d.and_hms_nano_opt(12, 34, 59, 1_789_012_345).is_some()); // leap second
666 /// assert!(d.and_hms_nano_opt(12, 34, 59, 2_789_012_345).is_none());
667 /// assert!(d.and_hms_nano_opt(12, 34, 60, 789_012_345).is_none());
668 /// assert!(d.and_hms_nano_opt(12, 60, 56, 789_012_345).is_none());
669 /// assert!(d.and_hms_nano_opt(24, 34, 56, 789_012_345).is_none());
670 /// ~~~~
671 #[inline]
672 pub fn and_hms_nano_opt(&self, hour: u32, min: u32, sec: u32,
673 nano: u32) -> Option<NaiveDateTime> {
674 NaiveTime::from_hms_nano_opt(hour, min, sec, nano).map(|time| self.and_time(time))
675 }
676
677 /// Returns the packed month-day-flags.
678 #[inline]
679 fn mdf(&self) -> Mdf {
680 self.of().to_mdf()
681 }
682
683 /// Returns the packed ordinal-flags.
684 #[inline]
685 fn of(&self) -> Of {
686 Of((self.ymdf & 0b1111_11111_1111) as u32)
687 }
688
689 /// Makes a new `NaiveDate` with the packed month-day-flags changed.
690 ///
691 /// Returns `None` when the resulting `NaiveDate` would be invalid.
692 #[inline]
693 fn with_mdf(&self, mdf: Mdf) -> Option<NaiveDate> {
694 self.with_of(mdf.to_of())
695 }
696
697 /// Makes a new `NaiveDate` with the packed ordinal-flags changed.
698 ///
699 /// Returns `None` when the resulting `NaiveDate` would be invalid.
700 #[inline]
701 fn with_of(&self, of: Of) -> Option<NaiveDate> {
702 if of.valid() {
703 let Of(of) = of;
704 Some(NaiveDate { ymdf: (self.ymdf & !0b111111111_1111) | of as DateImpl })
705 } else {
706 None
707 }
708 }
709
710 /// Makes a new `NaiveDate` for the next calendar date.
711 ///
712 /// Panics when `self` is the last representable date.
713 ///
714 /// # Example
715 ///
716 /// ~~~~
717 /// use chrono::NaiveDate;
718 ///
719 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).succ(), NaiveDate::from_ymd(2015, 6, 4));
720 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 30).succ(), NaiveDate::from_ymd(2015, 7, 1));
721 /// assert_eq!(NaiveDate::from_ymd(2015, 12, 31).succ(), NaiveDate::from_ymd(2016, 1, 1));
722 /// ~~~~
723 #[inline]
724 pub fn succ(&self) -> NaiveDate {
725 self.succ_opt().expect("out of bound")
726 }
727
728 /// Makes a new `NaiveDate` for the next calendar date.
729 ///
730 /// Returns `None` when `self` is the last representable date.
731 ///
732 /// # Example
733 ///
734 /// ~~~~
735 /// use chrono::NaiveDate;
736 /// use chrono::naive::MAX_DATE;
737 ///
738 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).succ_opt(),
739 /// Some(NaiveDate::from_ymd(2015, 6, 4)));
740 /// assert_eq!(MAX_DATE.succ_opt(), None);
741 /// ~~~~
742 #[inline]
743 pub fn succ_opt(&self) -> Option<NaiveDate> {
744 self.with_of(self.of().succ()).or_else(|| NaiveDate::from_ymd_opt(self.year() + 1, 1, 1))
745 }
746
747 /// Makes a new `NaiveDate` for the previous calendar date.
748 ///
749 /// Panics when `self` is the first representable date.
750 ///
751 /// # Example
752 ///
753 /// ~~~~
754 /// use chrono::NaiveDate;
755 ///
756 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).pred(), NaiveDate::from_ymd(2015, 6, 2));
757 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 1).pred(), NaiveDate::from_ymd(2015, 5, 31));
758 /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).pred(), NaiveDate::from_ymd(2014, 12, 31));
759 /// ~~~~
760 #[inline]
761 pub fn pred(&self) -> NaiveDate {
762 self.pred_opt().expect("out of bound")
763 }
764
765 /// Makes a new `NaiveDate` for the previous calendar date.
766 ///
767 /// Returns `None` when `self` is the first representable date.
768 ///
769 /// # Example
770 ///
771 /// ~~~~
772 /// use chrono::NaiveDate;
773 /// use chrono::naive::MIN_DATE;
774 ///
775 /// assert_eq!(NaiveDate::from_ymd(2015, 6, 3).pred_opt(),
776 /// Some(NaiveDate::from_ymd(2015, 6, 2)));
777 /// assert_eq!(MIN_DATE.pred_opt(), None);
778 /// ~~~~
779 #[inline]
780 pub fn pred_opt(&self) -> Option<NaiveDate> {
781 self.with_of(self.of().pred()).or_else(|| NaiveDate::from_ymd_opt(self.year() - 1, 12, 31))
782 }
783
784 /// Adds the `days` part of given `Duration` to the current date.
785 ///
786 /// Returns `None` when it will result in overflow.
787 ///
788 /// # Example
789 ///
790 /// ~~~~
791 /// # extern crate chrono; extern crate time; fn main() {
792 /// use chrono::NaiveDate;
793 /// use chrono::naive::MAX_DATE;
794 /// use time::Duration;
795 ///
796 /// let d = NaiveDate::from_ymd(2015, 9, 5);
797 /// assert_eq!(d.checked_add_signed(Duration::days(40)),
798 /// Some(NaiveDate::from_ymd(2015, 10, 15)));
799 /// assert_eq!(d.checked_add_signed(Duration::days(-40)),
800 /// Some(NaiveDate::from_ymd(2015, 7, 27)));
801 /// assert_eq!(d.checked_add_signed(Duration::days(1_000_000_000)), None);
802 /// assert_eq!(d.checked_add_signed(Duration::days(-1_000_000_000)), None);
803 /// assert_eq!(MAX_DATE.checked_add_signed(Duration::days(1)), None);
804 /// # }
805 /// ~~~~
806 pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
807 let year = self.year();
808 let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
809 let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
810 let cycle = try_opt!((cycle as i32).checked_add(try_opt!(rhs.num_days().to_i32())));
811 let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146097);
812 year_div_400 += cycle_div_400y;
813
814 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
815 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
816 NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32,
817 Of::new(ordinal, flags))
818 }
819
820 /// Subtracts the `days` part of given `Duration` from the current date.
821 ///
822 /// Returns `None` when it will result in overflow.
823 ///
824 /// # Example
825 ///
826 /// ~~~~
827 /// # extern crate chrono; extern crate time; fn main() {
828 /// use chrono::NaiveDate;
829 /// use chrono::naive::MIN_DATE;
830 /// use time::Duration;
831 ///
832 /// let d = NaiveDate::from_ymd(2015, 9, 5);
833 /// assert_eq!(d.checked_sub_signed(Duration::days(40)),
834 /// Some(NaiveDate::from_ymd(2015, 7, 27)));
835 /// assert_eq!(d.checked_sub_signed(Duration::days(-40)),
836 /// Some(NaiveDate::from_ymd(2015, 10, 15)));
837 /// assert_eq!(d.checked_sub_signed(Duration::days(1_000_000_000)), None);
838 /// assert_eq!(d.checked_sub_signed(Duration::days(-1_000_000_000)), None);
839 /// assert_eq!(MIN_DATE.checked_sub_signed(Duration::days(1)), None);
840 /// # }
841 /// ~~~~
842 pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
843 let year = self.year();
844 let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
845 let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
846 let cycle = try_opt!((cycle as i32).checked_sub(try_opt!(rhs.num_days().to_i32())));
847 let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146097);
848 year_div_400 += cycle_div_400y;
849
850 let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
851 let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
852 NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32,
853 Of::new(ordinal, flags))
854 }
855
856 /// Subtracts another `NaiveDate` from the current date.
857 /// Returns a `Duration` of integral numbers.
858 ///
859 /// This does not overflow or underflow at all,
860 /// as all possible output fits in the range of `Duration`.
861 ///
862 /// # Example
863 ///
864 /// ~~~~
865 /// # extern crate chrono; extern crate time; fn main() {
866 /// use chrono::NaiveDate;
867 /// use time::Duration;
868 ///
869 /// let from_ymd = NaiveDate::from_ymd;
870 /// let since = NaiveDate::signed_duration_since;
871 ///
872 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2014, 1, 1)), Duration::zero());
873 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 12, 31)), Duration::days(1));
874 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2014, 1, 2)), Duration::days(-1));
875 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 9, 23)), Duration::days(100));
876 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2013, 1, 1)), Duration::days(365));
877 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2010, 1, 1)), Duration::days(365*4 + 1));
878 /// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(1614, 1, 1)), Duration::days(365*400 + 97));
879 /// # }
880 /// ~~~~
881 pub fn signed_duration_since(self, rhs: NaiveDate) -> OldDuration {
882 let year1 = self.year();
883 let year2 = rhs.year();
884 let (year1_div_400, year1_mod_400) = div_mod_floor(year1, 400);
885 let (year2_div_400, year2_mod_400) = div_mod_floor(year2, 400);
886 let cycle1 = internals::yo_to_cycle(year1_mod_400 as u32, self.of().ordinal()) as i64;
887 let cycle2 = internals::yo_to_cycle(year2_mod_400 as u32, rhs.of().ordinal()) as i64;
888 OldDuration::days((year1_div_400 as i64 - year2_div_400 as i64) * 146097 +
889 (cycle1 - cycle2))
890 }
891
892 /// Formats the date with the specified formatting items.
893 /// Otherwise it is same to the ordinary `format` method.
894 ///
895 /// The `Iterator` of items should be `Clone`able,
896 /// since the resulting `DelayedFormat` value may be formatted multiple times.
897 ///
898 /// # Example
899 ///
900 /// ~~~~
901 /// use chrono::NaiveDate;
902 /// use chrono::format::strftime::StrftimeItems;
903 ///
904 /// let fmt = StrftimeItems::new("%Y-%m-%d");
905 /// let d = NaiveDate::from_ymd(2015, 9, 5);
906 /// assert_eq!(d.format_with_items(fmt.clone()).to_string(), "2015-09-05");
907 /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05");
908 /// ~~~~
909 ///
910 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
911 ///
912 /// ~~~~
913 /// # use chrono::NaiveDate;
914 /// # use chrono::format::strftime::StrftimeItems;
915 /// # let fmt = StrftimeItems::new("%Y-%m-%d").clone();
916 /// # let d = NaiveDate::from_ymd(2015, 9, 5);
917 /// assert_eq!(format!("{}", d.format_with_items(fmt)), "2015-09-05");
918 /// ~~~~
919 #[inline]
920 pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
921 where I: Iterator<Item=Item<'a>> + Clone {
922 DelayedFormat::new(Some(*self), None, items)
923 }
924
925 /// Formats the date with the specified format string.
926 /// See the [`format::strftime` module](../format/strftime/index.html)
927 /// on the supported escape sequences.
928 ///
929 /// This returns a `DelayedFormat`,
930 /// which gets converted to a string only when actual formatting happens.
931 /// You may use the `to_string` method to get a `String`,
932 /// or just feed it into `print!` and other formatting macros.
933 /// (In this way it avoids the redundant memory allocation.)
934 ///
935 /// A wrong format string does *not* issue an error immediately.
936 /// Rather, converting or formatting the `DelayedFormat` fails.
937 /// You are recommended to immediately use `DelayedFormat` for this reason.
938 ///
939 /// # Example
940 ///
941 /// ~~~~
942 /// use chrono::NaiveDate;
943 ///
944 /// let d = NaiveDate::from_ymd(2015, 9, 5);
945 /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05");
946 /// assert_eq!(d.format("%A, %-d %B, %C%y").to_string(), "Saturday, 5 September, 2015");
947 /// ~~~~
948 ///
949 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
950 ///
951 /// ~~~~
952 /// # use chrono::NaiveDate;
953 /// # let d = NaiveDate::from_ymd(2015, 9, 5);
954 /// assert_eq!(format!("{}", d.format("%Y-%m-%d")), "2015-09-05");
955 /// assert_eq!(format!("{}", d.format("%A, %-d %B, %C%y")), "Saturday, 5 September, 2015");
956 /// ~~~~
957 #[inline]
958 pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
959 self.format_with_items(StrftimeItems::new(fmt))
960 }
961}
962
963impl Datelike for NaiveDate {
964 /// Returns the year number in the [calendar date](#calendar-date).
965 ///
966 /// # Example
967 ///
968 /// ~~~~
969 /// use chrono::{NaiveDate, Datelike};
970 ///
971 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).year(), 2015);
972 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).year(), -308); // 309 BCE
973 /// ~~~~
974 #[inline]
975 fn year(&self) -> i32 {
976 self.ymdf >> 13
977 }
978
979 /// Returns the month number starting from 1.
980 ///
981 /// The return value ranges from 1 to 12.
982 ///
983 /// # Example
984 ///
985 /// ~~~~
986 /// use chrono::{NaiveDate, Datelike};
987 ///
988 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).month(), 9);
989 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).month(), 3);
990 /// ~~~~
991 #[inline]
992 fn month(&self) -> u32 {
993 self.mdf().month()
994 }
995
996 /// Returns the month number starting from 0.
997 ///
998 /// The return value ranges from 0 to 11.
999 ///
1000 /// # Example
1001 ///
1002 /// ~~~~
1003 /// use chrono::{NaiveDate, Datelike};
1004 ///
1005 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).month0(), 8);
1006 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).month0(), 2);
1007 /// ~~~~
1008 #[inline]
1009 fn month0(&self) -> u32 {
1010 self.mdf().month() - 1
1011 }
1012
1013 /// Returns the day of month starting from 1.
1014 ///
1015 /// The return value ranges from 1 to 31. (The last day of month differs by months.)
1016 ///
1017 /// # Example
1018 ///
1019 /// ~~~~
1020 /// use chrono::{NaiveDate, Datelike};
1021 ///
1022 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).day(), 8);
1023 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).day(), 14);
1024 /// ~~~~
1025 ///
1026 /// Combined with [`NaiveDate::pred`](#method.pred),
1027 /// one can determine the number of days in a particular month.
1028 /// (Note that this panics when `year` is out of range.)
1029 ///
1030 /// ~~~~
1031 /// use chrono::{NaiveDate, Datelike};
1032 ///
1033 /// fn ndays_in_month(year: i32, month: u32) -> u32 {
1034 /// // the first day of the next month...
1035 /// let (y, m) = if month == 12 { (year + 1, 1) } else { (year, month + 1) };
1036 /// let d = NaiveDate::from_ymd(y, m, 1);
1037 ///
1038 /// // ...is preceded by the last day of the original month
1039 /// d.pred().day()
1040 /// }
1041 ///
1042 /// assert_eq!(ndays_in_month(2015, 8), 31);
1043 /// assert_eq!(ndays_in_month(2015, 9), 30);
1044 /// assert_eq!(ndays_in_month(2015, 12), 31);
1045 /// assert_eq!(ndays_in_month(2016, 2), 29);
1046 /// assert_eq!(ndays_in_month(2017, 2), 28);
1047 /// ~~~~
1048 #[inline]
1049 fn day(&self) -> u32 {
1050 self.mdf().day()
1051 }
1052
1053 /// Returns the day of month starting from 0.
1054 ///
1055 /// The return value ranges from 0 to 30. (The last day of month differs by months.)
1056 ///
1057 /// # Example
1058 ///
1059 /// ~~~~
1060 /// use chrono::{NaiveDate, Datelike};
1061 ///
1062 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).day0(), 7);
1063 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).day0(), 13);
1064 /// ~~~~
1065 #[inline]
1066 fn day0(&self) -> u32 {
1067 self.mdf().day() - 1
1068 }
1069
1070 /// Returns the day of year starting from 1.
1071 ///
1072 /// The return value ranges from 1 to 366. (The last day of year differs by years.)
1073 ///
1074 /// # Example
1075 ///
1076 /// ~~~~
1077 /// use chrono::{NaiveDate, Datelike};
1078 ///
1079 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).ordinal(), 251);
1080 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).ordinal(), 74);
1081 /// ~~~~
1082 ///
1083 /// Combined with [`NaiveDate::pred`](#method.pred),
1084 /// one can determine the number of days in a particular year.
1085 /// (Note that this panics when `year` is out of range.)
1086 ///
1087 /// ~~~~
1088 /// use chrono::{NaiveDate, Datelike};
1089 ///
1090 /// fn ndays_in_year(year: i32) -> u32 {
1091 /// // the first day of the next year...
1092 /// let d = NaiveDate::from_ymd(year + 1, 1, 1);
1093 ///
1094 /// // ...is preceded by the last day of the original year
1095 /// d.pred().ordinal()
1096 /// }
1097 ///
1098 /// assert_eq!(ndays_in_year(2015), 365);
1099 /// assert_eq!(ndays_in_year(2016), 366);
1100 /// assert_eq!(ndays_in_year(2017), 365);
1101 /// assert_eq!(ndays_in_year(2000), 366);
1102 /// assert_eq!(ndays_in_year(2100), 365);
1103 /// ~~~~
1104 #[inline]
1105 fn ordinal(&self) -> u32 {
1106 self.of().ordinal()
1107 }
1108
1109 /// Returns the day of year starting from 0.
1110 ///
1111 /// The return value ranges from 0 to 365. (The last day of year differs by years.)
1112 ///
1113 /// # Example
1114 ///
1115 /// ~~~~
1116 /// use chrono::{NaiveDate, Datelike};
1117 ///
1118 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).ordinal0(), 250);
1119 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).ordinal0(), 73);
1120 /// ~~~~
1121 #[inline]
1122 fn ordinal0(&self) -> u32 {
1123 self.of().ordinal() - 1
1124 }
1125
1126 /// Returns the day of week.
1127 ///
1128 /// # Example
1129 ///
1130 /// ~~~~
1131 /// use chrono::{NaiveDate, Datelike, Weekday};
1132 ///
1133 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).weekday(), Weekday::Tue);
1134 /// assert_eq!(NaiveDate::from_ymd(-308, 3, 14).weekday(), Weekday::Fri);
1135 /// ~~~~
1136 #[inline]
1137 fn weekday(&self) -> Weekday {
1138 self.of().weekday()
1139 }
1140
1141 #[inline]
1142 fn iso_week(&self) -> IsoWeek {
1143 isoweek::iso_week_from_yof(self.year(), self.of())
1144 }
1145
1146 /// Makes a new `NaiveDate` with the year number changed.
1147 ///
1148 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1149 ///
1150 /// # Example
1151 ///
1152 /// ~~~~
1153 /// use chrono::{NaiveDate, Datelike};
1154 ///
1155 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_year(2016),
1156 /// Some(NaiveDate::from_ymd(2016, 9, 8)));
1157 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_year(-308),
1158 /// Some(NaiveDate::from_ymd(-308, 9, 8)));
1159 /// ~~~~
1160 ///
1161 /// A leap day (February 29) is a good example that this method can return `None`.
1162 ///
1163 /// ~~~~
1164 /// # use chrono::{NaiveDate, Datelike};
1165 /// assert!(NaiveDate::from_ymd(2016, 2, 29).with_year(2015).is_none());
1166 /// assert!(NaiveDate::from_ymd(2016, 2, 29).with_year(2020).is_some());
1167 /// ~~~~
1168 #[inline]
1169 fn with_year(&self, year: i32) -> Option<NaiveDate> {
1170 // we need to operate with `mdf` since we should keep the month and day number as is
1171 let mdf = self.mdf();
1172
1173 // adjust the flags as needed
1174 let flags = YearFlags::from_year(year);
1175 let mdf = mdf.with_flags(flags);
1176
1177 NaiveDate::from_mdf(year, mdf)
1178 }
1179
1180 /// Makes a new `NaiveDate` with the month number (starting from 1) changed.
1181 ///
1182 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1183 ///
1184 /// # Example
1185 ///
1186 /// ~~~~
1187 /// use chrono::{NaiveDate, Datelike};
1188 ///
1189 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month(10),
1190 /// Some(NaiveDate::from_ymd(2015, 10, 8)));
1191 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month(13), None); // no month 13
1192 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).with_month(2), None); // no February 30
1193 /// ~~~~
1194 #[inline]
1195 fn with_month(&self, month: u32) -> Option<NaiveDate> {
1196 self.with_mdf(self.mdf().with_month(month))
1197 }
1198
1199 /// Makes a new `NaiveDate` with the month number (starting from 0) changed.
1200 ///
1201 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1202 ///
1203 /// # Example
1204 ///
1205 /// ~~~~
1206 /// use chrono::{NaiveDate, Datelike};
1207 ///
1208 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month0(9),
1209 /// Some(NaiveDate::from_ymd(2015, 10, 8)));
1210 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_month0(12), None); // no month 13
1211 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).with_month0(1), None); // no February 30
1212 /// ~~~~
1213 #[inline]
1214 fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
1215 self.with_mdf(self.mdf().with_month(month0 + 1))
1216 }
1217
1218 /// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
1219 ///
1220 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1221 ///
1222 /// # Example
1223 ///
1224 /// ~~~~
1225 /// use chrono::{NaiveDate, Datelike};
1226 ///
1227 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day(30),
1228 /// Some(NaiveDate::from_ymd(2015, 9, 30)));
1229 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day(31),
1230 /// None); // no September 31
1231 /// ~~~~
1232 #[inline]
1233 fn with_day(&self, day: u32) -> Option<NaiveDate> {
1234 self.with_mdf(self.mdf().with_day(day))
1235 }
1236
1237 /// Makes a new `NaiveDate` with the day of month (starting from 0) changed.
1238 ///
1239 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1240 ///
1241 /// # Example
1242 ///
1243 /// ~~~~
1244 /// use chrono::{NaiveDate, Datelike};
1245 ///
1246 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day0(29),
1247 /// Some(NaiveDate::from_ymd(2015, 9, 30)));
1248 /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).with_day0(30),
1249 /// None); // no September 31
1250 /// ~~~~
1251 #[inline]
1252 fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
1253 self.with_mdf(self.mdf().with_day(day0 + 1))
1254 }
1255
1256 /// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
1257 ///
1258 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1259 ///
1260 /// # Example
1261 ///
1262 /// ~~~~
1263 /// use chrono::{NaiveDate, Datelike};
1264 ///
1265 /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal(60),
1266 /// Some(NaiveDate::from_ymd(2015, 3, 1)));
1267 /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal(366),
1268 /// None); // 2015 had only 365 days
1269 ///
1270 /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal(60),
1271 /// Some(NaiveDate::from_ymd(2016, 2, 29)));
1272 /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal(366),
1273 /// Some(NaiveDate::from_ymd(2016, 12, 31)));
1274 /// ~~~~
1275 #[inline]
1276 fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
1277 self.with_of(self.of().with_ordinal(ordinal))
1278 }
1279
1280 /// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
1281 ///
1282 /// Returns `None` when the resulting `NaiveDate` would be invalid.
1283 ///
1284 /// # Example
1285 ///
1286 /// ~~~~
1287 /// use chrono::{NaiveDate, Datelike};
1288 ///
1289 /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal0(59),
1290 /// Some(NaiveDate::from_ymd(2015, 3, 1)));
1291 /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).with_ordinal0(365),
1292 /// None); // 2015 had only 365 days
1293 ///
1294 /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal0(59),
1295 /// Some(NaiveDate::from_ymd(2016, 2, 29)));
1296 /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).with_ordinal0(365),
1297 /// Some(NaiveDate::from_ymd(2016, 12, 31)));
1298 /// ~~~~
1299 #[inline]
1300 fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
1301 self.with_of(self.of().with_ordinal(ordinal0 + 1))
1302 }
1303}
1304
1305/// `NaiveDate` can be used as a key to the hash maps.
1306impl hash::Hash for NaiveDate {
1307 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1308 // don't need to strip flags, as we can safely assume that it is correct
1309 self.ymdf.hash(state);
1310 }
1311}
1312
1313/// An addition of `Duration` to `NaiveDate` discards the fractional days,
1314/// rounding to the closest integral number of days towards `Duration::zero()`.
1315///
1316/// Panics on underflow or overflow.
1317/// Use [`NaiveDate::checked_add_signed`](#method.checked_add_signed) to detect that.
1318///
1319/// # Example
1320///
1321/// ~~~~
1322/// # extern crate chrono; extern crate time; fn main() {
1323/// use chrono::NaiveDate;
1324/// use time::Duration;
1325///
1326/// let from_ymd = NaiveDate::from_ymd;
1327///
1328/// assert_eq!(from_ymd(2014, 1, 1) + Duration::zero(), from_ymd(2014, 1, 1));
1329/// assert_eq!(from_ymd(2014, 1, 1) + Duration::seconds(86399), from_ymd(2014, 1, 1));
1330/// assert_eq!(from_ymd(2014, 1, 1) + Duration::seconds(-86399), from_ymd(2014, 1, 1));
1331/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(1), from_ymd(2014, 1, 2));
1332/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(-1), from_ymd(2013, 12, 31));
1333/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(364), from_ymd(2014, 12, 31));
1334/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*4 + 1), from_ymd(2018, 1, 1));
1335/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*400 + 97), from_ymd(2414, 1, 1));
1336/// # }
1337/// ~~~~
1338impl Add<OldDuration> for NaiveDate {
1339 type Output = NaiveDate;
1340
1341 #[inline]
1342 fn add(self, rhs: OldDuration) -> NaiveDate {
1343 self.checked_add_signed(rhs).expect("`NaiveDate + Duration` overflowed")
1344 }
1345}
1346
1347impl AddAssign<OldDuration> for NaiveDate {
1348 #[inline]
1349 fn add_assign(&mut self, rhs: OldDuration) {
1350 *self = self.add(rhs);
1351 }
1352}
1353
1354/// A subtraction of `Duration` from `NaiveDate` discards the fractional days,
1355/// rounding to the closest integral number of days towards `Duration::zero()`.
1356/// It is same to the addition with a negated `Duration`.
1357///
1358/// Panics on underflow or overflow.
1359/// Use [`NaiveDate::checked_sub_signed`](#method.checked_sub_signed) to detect that.
1360///
1361/// # Example
1362///
1363/// ~~~~
1364/// # extern crate chrono; extern crate time; fn main() {
1365/// use chrono::NaiveDate;
1366/// use time::Duration;
1367///
1368/// let from_ymd = NaiveDate::from_ymd;
1369///
1370/// assert_eq!(from_ymd(2014, 1, 1) - Duration::zero(), from_ymd(2014, 1, 1));
1371/// assert_eq!(from_ymd(2014, 1, 1) - Duration::seconds(86399), from_ymd(2014, 1, 1));
1372/// assert_eq!(from_ymd(2014, 1, 1) - Duration::seconds(-86399), from_ymd(2014, 1, 1));
1373/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(1), from_ymd(2013, 12, 31));
1374/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(-1), from_ymd(2014, 1, 2));
1375/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(364), from_ymd(2013, 1, 2));
1376/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*4 + 1), from_ymd(2010, 1, 1));
1377/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*400 + 97), from_ymd(1614, 1, 1));
1378/// # }
1379/// ~~~~
1380impl Sub<OldDuration> for NaiveDate {
1381 type Output = NaiveDate;
1382
1383 #[inline]
1384 fn sub(self, rhs: OldDuration) -> NaiveDate {
1385 self.checked_sub_signed(rhs).expect("`NaiveDate - Duration` overflowed")
1386 }
1387}
1388
1389impl SubAssign<OldDuration> for NaiveDate {
1390 #[inline]
1391 fn sub_assign(&mut self, rhs: OldDuration) {
1392 *self = self.sub(rhs);
1393 }
1394}
1395
1396/// The `Debug` output of the naive date `d` is same to
1397/// [`d.format("%Y-%m-%d")`](../format/strftime/index.html).
1398///
1399/// The string printed can be readily parsed via the `parse` method on `str`.
1400///
1401/// # Example
1402///
1403/// ~~~~
1404/// use chrono::NaiveDate;
1405///
1406/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(2015, 9, 5)), "2015-09-05");
1407/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( 0, 1, 1)), "0000-01-01");
1408/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(9999, 12, 31)), "9999-12-31");
1409/// ~~~~
1410///
1411/// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE.
1412///
1413/// ~~~~
1414/// # use chrono::NaiveDate;
1415/// assert_eq!(format!("{:?}", NaiveDate::from_ymd( -1, 1, 1)), "-0001-01-01");
1416/// assert_eq!(format!("{:?}", NaiveDate::from_ymd(10000, 12, 31)), "+10000-12-31");
1417/// ~~~~
1418impl fmt::Debug for NaiveDate {
1419 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1420 let year = self.year();
1421 let mdf = self.mdf();
1422 if 0 <= year && year <= 9999 {
1423 write!(f, "{:04}-{:02}-{:02}", year, mdf.month(), mdf.day())
1424 } else {
1425 // ISO 8601 requires the explicit sign for out-of-range years
1426 write!(f, "{:+05}-{:02}-{:02}", year, mdf.month(), mdf.day())
1427 }
1428 }
1429}
1430
1431/// The `Display` output of the naive date `d` is same to
1432/// [`d.format("%Y-%m-%d")`](../format/strftime/index.html).
1433///
1434/// The string printed can be readily parsed via the `parse` method on `str`.
1435///
1436/// # Example
1437///
1438/// ~~~~
1439/// use chrono::NaiveDate;
1440///
1441/// assert_eq!(format!("{}", NaiveDate::from_ymd(2015, 9, 5)), "2015-09-05");
1442/// assert_eq!(format!("{}", NaiveDate::from_ymd( 0, 1, 1)), "0000-01-01");
1443/// assert_eq!(format!("{}", NaiveDate::from_ymd(9999, 12, 31)), "9999-12-31");
1444/// ~~~~
1445///
1446/// ISO 8601 requires an explicit sign for years before 1 BCE or after 9999 CE.
1447///
1448/// ~~~~
1449/// # use chrono::NaiveDate;
1450/// assert_eq!(format!("{}", NaiveDate::from_ymd( -1, 1, 1)), "-0001-01-01");
1451/// assert_eq!(format!("{}", NaiveDate::from_ymd(10000, 12, 31)), "+10000-12-31");
1452/// ~~~~
1453impl fmt::Display for NaiveDate {
1454 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) }
1455}
1456
1457/// Parsing a `str` into a `NaiveDate` uses the same format,
1458/// [`%Y-%m-%d`](../format/strftime/index.html), as in `Debug` and `Display`.
1459///
1460/// # Example
1461///
1462/// ~~~~
1463/// use chrono::NaiveDate;
1464///
1465/// let d = NaiveDate::from_ymd(2015, 9, 18);
1466/// assert_eq!("2015-09-18".parse::<NaiveDate>(), Ok(d));
1467///
1468/// let d = NaiveDate::from_ymd(12345, 6, 7);
1469/// assert_eq!("+12345-6-7".parse::<NaiveDate>(), Ok(d));
1470///
1471/// assert!("foo".parse::<NaiveDate>().is_err());
1472/// ~~~~
1473impl str::FromStr for NaiveDate {
1474 type Err = ParseError;
1475
1476 fn from_str(s: &str) -> ParseResult<NaiveDate> {
1477 const ITEMS: &'static [Item<'static>] = &[
1478 Item::Space(""), Item::Numeric(Numeric::Year, Pad::Zero),
1479 Item::Space(""), Item::Literal("-"),
1480 Item::Space(""), Item::Numeric(Numeric::Month, Pad::Zero),
1481 Item::Space(""), Item::Literal("-"),
1482 Item::Space(""), Item::Numeric(Numeric::Day, Pad::Zero),
1483 Item::Space(""),
1484 ];
1485
1486 let mut parsed = Parsed::new();
1487 try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
1488 parsed.to_naive_date()
1489 }
1490}
1491
1492#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1493fn test_encodable_json<F, E>(to_string: F)
1494 where F: Fn(&NaiveDate) -> Result<String, E>, E: ::std::fmt::Debug
1495{
1496 assert_eq!(to_string(&NaiveDate::from_ymd(2014, 7, 24)).ok(),
1497 Some(r#""2014-07-24""#.into()));
1498 assert_eq!(to_string(&NaiveDate::from_ymd(0, 1, 1)).ok(),
1499 Some(r#""0000-01-01""#.into()));
1500 assert_eq!(to_string(&NaiveDate::from_ymd(-1, 12, 31)).ok(),
1501 Some(r#""-0001-12-31""#.into()));
1502 assert_eq!(to_string(&MIN_DATE).ok(),
1503 Some(r#""-262144-01-01""#.into()));
1504 assert_eq!(to_string(&MAX_DATE).ok(),
1505 Some(r#""+262143-12-31""#.into()));
1506}
1507
1508#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1509fn test_decodable_json<F, E>(from_str: F)
1510 where F: Fn(&str) -> Result<NaiveDate, E>, E: ::std::fmt::Debug
1511{
1512 use std::{i32, i64};
1513
1514 assert_eq!(from_str(r#""2016-07-08""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8)));
1515 assert_eq!(from_str(r#""2016-7-8""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8)));
1516 assert_eq!(from_str(r#""+002016-07-08""#).ok(), Some(NaiveDate::from_ymd(2016, 7, 8)));
1517 assert_eq!(from_str(r#""0000-01-01""#).ok(), Some(NaiveDate::from_ymd(0, 1, 1)));
1518 assert_eq!(from_str(r#""0-1-1""#).ok(), Some(NaiveDate::from_ymd(0, 1, 1)));
1519 assert_eq!(from_str(r#""-0001-12-31""#).ok(), Some(NaiveDate::from_ymd(-1, 12, 31)));
1520 assert_eq!(from_str(r#""-262144-01-01""#).ok(), Some(MIN_DATE));
1521 assert_eq!(from_str(r#""+262143-12-31""#).ok(), Some(MAX_DATE));
1522
1523 // bad formats
1524 assert!(from_str(r#""""#).is_err());
1525 assert!(from_str(r#""20001231""#).is_err());
1526 assert!(from_str(r#""2000-00-00""#).is_err());
1527 assert!(from_str(r#""2000-02-30""#).is_err());
1528 assert!(from_str(r#""2001-02-29""#).is_err());
1529 assert!(from_str(r#""2002-002-28""#).is_err());
1530 assert!(from_str(r#""yyyy-mm-dd""#).is_err());
1531 assert!(from_str(r#"0"#).is_err());
1532 assert!(from_str(r#"20.01"#).is_err());
1533 assert!(from_str(&i32::MIN.to_string()).is_err());
1534 assert!(from_str(&i32::MAX.to_string()).is_err());
1535 assert!(from_str(&i64::MIN.to_string()).is_err());
1536 assert!(from_str(&i64::MAX.to_string()).is_err());
1537 assert!(from_str(r#"{}"#).is_err());
1538 // pre-0.3.0 rustc-serialize format is now invalid
1539 assert!(from_str(r#"{"ymdf":20}"#).is_err());
1540 assert!(from_str(r#"null"#).is_err());
1541}
1542
1543#[cfg(feature = "rustc-serialize")]
1544mod rustc_serialize {
1545 use super::NaiveDate;
1546 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
1547
1548 impl Encodable for NaiveDate {
1549 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1550 format!("{:?}", self).encode(s)
1551 }
1552 }
1553
1554 impl Decodable for NaiveDate {
1555 fn decode<D: Decoder>(d: &mut D) -> Result<NaiveDate, D::Error> {
1556 d.read_str()?.parse().map_err(|_| d.error("invalid date"))
1557 }
1558 }
1559
1560 #[cfg(test)] use rustc_serialize::json;
1561
1562 #[test]
1563 fn test_encodable() {
1564 super::test_encodable_json(json::encode);
1565 }
1566
1567 #[test]
1568 fn test_decodable() {
1569 super::test_decodable_json(json::decode);
1570 }
1571}
1572
1573#[cfg(feature = "serde")]
1574mod serde {
1575 use std::fmt;
1576 use super::NaiveDate;
1577 use serdelib::{ser, de};
1578
1579 // TODO not very optimized for space (binary formats would want something better)
1580
1581 impl ser::Serialize for NaiveDate {
1582 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1583 where S: ser::Serializer
1584 {
1585 struct FormatWrapped<'a, D: 'a> {
1586 inner: &'a D
1587 }
1588
1589 impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> {
1590 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1591 self.inner.fmt(f)
1592 }
1593 }
1594
1595 serializer.collect_str(&FormatWrapped { inner: &self })
1596 }
1597 }
1598
1599 struct NaiveDateVisitor;
1600
1601 impl<'de> de::Visitor<'de> for NaiveDateVisitor {
1602 type Value = NaiveDate;
1603
1604 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
1605 {
1606 write!(formatter, "a formatted date string")
1607 }
1608
1609 fn visit_str<E>(self, value: &str) -> Result<NaiveDate, E>
1610 where E: de::Error
1611 {
1612 value.parse().map_err(|err| E::custom(format!("{}", err)))
1613 }
1614 }
1615
1616 impl<'de> de::Deserialize<'de> for NaiveDate {
1617 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1618 where D: de::Deserializer<'de>
1619 {
1620 deserializer.deserialize_str(NaiveDateVisitor)
1621 }
1622 }
1623
1624 #[cfg(test)] extern crate serde_json;
1625 #[cfg(test)] extern crate bincode;
1626
1627 #[test]
1628 fn test_serde_serialize() {
1629 super::test_encodable_json(self::serde_json::to_string);
1630 }
1631
1632 #[test]
1633 fn test_serde_deserialize() {
1634 super::test_decodable_json(|input| self::serde_json::from_str(&input));
1635 }
1636
1637 #[test]
1638 fn test_serde_bincode() {
1639 // Bincode is relevant to test separately from JSON because
1640 // it is not self-describing.
1641 use self::bincode::{Infinite, serialize, deserialize};
1642
1643 let d = NaiveDate::from_ymd(2014, 7, 24);
1644 let encoded = serialize(&d, Infinite).unwrap();
1645 let decoded: NaiveDate = deserialize(&encoded).unwrap();
1646 assert_eq!(d, decoded);
1647 }
1648}
1649
1650#[cfg(test)]
1651mod tests {
1652 use super::NaiveDate;
1653 use super::{MIN_DATE, MIN_YEAR, MIN_DAYS_FROM_YEAR_0};
1654 use super::{MAX_DATE, MAX_YEAR, MAX_DAYS_FROM_YEAR_0};
1655 use {Datelike, Weekday};
1656 use std::{i32, u32};
1657 use oldtime::Duration;
1658
1659 #[test]
1660 fn test_date_from_ymd() {
1661 let ymd_opt = |y,m,d| NaiveDate::from_ymd_opt(y, m, d);
1662
1663 assert!(ymd_opt(2012, 0, 1).is_none());
1664 assert!(ymd_opt(2012, 1, 1).is_some());
1665 assert!(ymd_opt(2012, 2, 29).is_some());
1666 assert!(ymd_opt(2014, 2, 29).is_none());
1667 assert!(ymd_opt(2014, 3, 0).is_none());
1668 assert!(ymd_opt(2014, 3, 1).is_some());
1669 assert!(ymd_opt(2014, 3, 31).is_some());
1670 assert!(ymd_opt(2014, 3, 32).is_none());
1671 assert!(ymd_opt(2014, 12, 31).is_some());
1672 assert!(ymd_opt(2014, 13, 1).is_none());
1673 }
1674
1675 #[test]
1676 fn test_date_from_yo() {
1677 let yo_opt = |y,o| NaiveDate::from_yo_opt(y, o);
1678 let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d);
1679
1680 assert_eq!(yo_opt(2012, 0), None);
1681 assert_eq!(yo_opt(2012, 1), Some(ymd(2012, 1, 1)));
1682 assert_eq!(yo_opt(2012, 2), Some(ymd(2012, 1, 2)));
1683 assert_eq!(yo_opt(2012, 32), Some(ymd(2012, 2, 1)));
1684 assert_eq!(yo_opt(2012, 60), Some(ymd(2012, 2, 29)));
1685 assert_eq!(yo_opt(2012, 61), Some(ymd(2012, 3, 1)));
1686 assert_eq!(yo_opt(2012, 100), Some(ymd(2012, 4, 9)));
1687 assert_eq!(yo_opt(2012, 200), Some(ymd(2012, 7, 18)));
1688 assert_eq!(yo_opt(2012, 300), Some(ymd(2012, 10, 26)));
1689 assert_eq!(yo_opt(2012, 366), Some(ymd(2012, 12, 31)));
1690 assert_eq!(yo_opt(2012, 367), None);
1691
1692 assert_eq!(yo_opt(2014, 0), None);
1693 assert_eq!(yo_opt(2014, 1), Some(ymd(2014, 1, 1)));
1694 assert_eq!(yo_opt(2014, 2), Some(ymd(2014, 1, 2)));
1695 assert_eq!(yo_opt(2014, 32), Some(ymd(2014, 2, 1)));
1696 assert_eq!(yo_opt(2014, 59), Some(ymd(2014, 2, 28)));
1697 assert_eq!(yo_opt(2014, 60), Some(ymd(2014, 3, 1)));
1698 assert_eq!(yo_opt(2014, 100), Some(ymd(2014, 4, 10)));
1699 assert_eq!(yo_opt(2014, 200), Some(ymd(2014, 7, 19)));
1700 assert_eq!(yo_opt(2014, 300), Some(ymd(2014, 10, 27)));
1701 assert_eq!(yo_opt(2014, 365), Some(ymd(2014, 12, 31)));
1702 assert_eq!(yo_opt(2014, 366), None);
1703 }
1704
1705 #[test]
1706 fn test_date_from_isoywd() {
1707 let isoywd_opt = |y,w,d| NaiveDate::from_isoywd_opt(y, w, d);
1708 let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d);
1709
1710 assert_eq!(isoywd_opt(2004, 0, Weekday::Sun), None);
1711 assert_eq!(isoywd_opt(2004, 1, Weekday::Mon), Some(ymd(2003, 12, 29)));
1712 assert_eq!(isoywd_opt(2004, 1, Weekday::Sun), Some(ymd(2004, 1, 4)));
1713 assert_eq!(isoywd_opt(2004, 2, Weekday::Mon), Some(ymd(2004, 1, 5)));
1714 assert_eq!(isoywd_opt(2004, 2, Weekday::Sun), Some(ymd(2004, 1, 11)));
1715 assert_eq!(isoywd_opt(2004, 52, Weekday::Mon), Some(ymd(2004, 12, 20)));
1716 assert_eq!(isoywd_opt(2004, 52, Weekday::Sun), Some(ymd(2004, 12, 26)));
1717 assert_eq!(isoywd_opt(2004, 53, Weekday::Mon), Some(ymd(2004, 12, 27)));
1718 assert_eq!(isoywd_opt(2004, 53, Weekday::Sun), Some(ymd(2005, 1, 2)));
1719 assert_eq!(isoywd_opt(2004, 54, Weekday::Mon), None);
1720
1721 assert_eq!(isoywd_opt(2011, 0, Weekday::Sun), None);
1722 assert_eq!(isoywd_opt(2011, 1, Weekday::Mon), Some(ymd(2011, 1, 3)));
1723 assert_eq!(isoywd_opt(2011, 1, Weekday::Sun), Some(ymd(2011, 1, 9)));
1724 assert_eq!(isoywd_opt(2011, 2, Weekday::Mon), Some(ymd(2011, 1, 10)));
1725 assert_eq!(isoywd_opt(2011, 2, Weekday::Sun), Some(ymd(2011, 1, 16)));
1726
1727 assert_eq!(isoywd_opt(2018, 51, Weekday::Mon), Some(ymd(2018, 12, 17)));
1728 assert_eq!(isoywd_opt(2018, 51, Weekday::Sun), Some(ymd(2018, 12, 23)));
1729 assert_eq!(isoywd_opt(2018, 52, Weekday::Mon), Some(ymd(2018, 12, 24)));
1730 assert_eq!(isoywd_opt(2018, 52, Weekday::Sun), Some(ymd(2018, 12, 30)));
1731 assert_eq!(isoywd_opt(2018, 53, Weekday::Mon), None);
1732 }
1733
1734 #[test]
1735 fn test_date_from_isoywd_and_iso_week() {
1736 for year in 2000..2401 {
1737 for week in 1..54 {
1738 for &weekday in [Weekday::Mon, Weekday::Tue, Weekday::Wed, Weekday::Thu,
1739 Weekday::Fri, Weekday::Sat, Weekday::Sun].iter() {
1740 let d = NaiveDate::from_isoywd_opt(year, week, weekday);
1741 if d.is_some() {
1742 let d = d.unwrap();
1743 assert_eq!(d.weekday(), weekday);
1744 let w = d.iso_week();
1745 assert_eq!(w.year(), year);
1746 assert_eq!(w.week(), week);
1747 }
1748 }
1749 }
1750 }
1751
1752 for year in 2000..2401 {
1753 for month in 1..13 {
1754 for day in 1..32 {
1755 let d = NaiveDate::from_ymd_opt(year, month, day);
1756 if d.is_some() {
1757 let d = d.unwrap();
1758 let w = d.iso_week();
1759 let d_ = NaiveDate::from_isoywd(w.year(), w.week(), d.weekday());
1760 assert_eq!(d, d_);
1761 }
1762 }
1763 }
1764 }
1765 }
1766
1767 #[test]
1768 fn test_date_from_num_days_from_ce() {
1769 let from_ndays_from_ce = |days| NaiveDate::from_num_days_from_ce_opt(days);
1770 assert_eq!(from_ndays_from_ce(1), Some(NaiveDate::from_ymd(1, 1, 1)));
1771 assert_eq!(from_ndays_from_ce(2), Some(NaiveDate::from_ymd(1, 1, 2)));
1772 assert_eq!(from_ndays_from_ce(31), Some(NaiveDate::from_ymd(1, 1, 31)));
1773 assert_eq!(from_ndays_from_ce(32), Some(NaiveDate::from_ymd(1, 2, 1)));
1774 assert_eq!(from_ndays_from_ce(59), Some(NaiveDate::from_ymd(1, 2, 28)));
1775 assert_eq!(from_ndays_from_ce(60), Some(NaiveDate::from_ymd(1, 3, 1)));
1776 assert_eq!(from_ndays_from_ce(365), Some(NaiveDate::from_ymd(1, 12, 31)));
1777 assert_eq!(from_ndays_from_ce(365*1 + 1), Some(NaiveDate::from_ymd(2, 1, 1)));
1778 assert_eq!(from_ndays_from_ce(365*2 + 1), Some(NaiveDate::from_ymd(3, 1, 1)));
1779 assert_eq!(from_ndays_from_ce(365*3 + 1), Some(NaiveDate::from_ymd(4, 1, 1)));
1780 assert_eq!(from_ndays_from_ce(365*4 + 2), Some(NaiveDate::from_ymd(5, 1, 1)));
1781 assert_eq!(from_ndays_from_ce(146097 + 1), Some(NaiveDate::from_ymd(401, 1, 1)));
1782 assert_eq!(from_ndays_from_ce(146097*5 + 1), Some(NaiveDate::from_ymd(2001, 1, 1)));
1783 assert_eq!(from_ndays_from_ce(719163), Some(NaiveDate::from_ymd(1970, 1, 1)));
1784 assert_eq!(from_ndays_from_ce(0), Some(NaiveDate::from_ymd(0, 12, 31))); // 1 BCE
1785 assert_eq!(from_ndays_from_ce(-365), Some(NaiveDate::from_ymd(0, 1, 1)));
1786 assert_eq!(from_ndays_from_ce(-366), Some(NaiveDate::from_ymd(-1, 12, 31))); // 2 BCE
1787
1788 for days in (-9999..10001).map(|x| x * 100) {
1789 assert_eq!(from_ndays_from_ce(days).map(|d| d.num_days_from_ce()), Some(days));
1790 }
1791
1792 assert_eq!(from_ndays_from_ce(MIN_DATE.num_days_from_ce()), Some(MIN_DATE));
1793 assert_eq!(from_ndays_from_ce(MIN_DATE.num_days_from_ce() - 1), None);
1794 assert_eq!(from_ndays_from_ce(MAX_DATE.num_days_from_ce()), Some(MAX_DATE));
1795 assert_eq!(from_ndays_from_ce(MAX_DATE.num_days_from_ce() + 1), None);
1796 }
1797
1798 #[test]
1799 fn test_date_fields() {
1800 fn check(year: i32, month: u32, day: u32, ordinal: u32) {
1801 let d1 = NaiveDate::from_ymd(year, month, day);
1802 assert_eq!(d1.year(), year);
1803 assert_eq!(d1.month(), month);
1804 assert_eq!(d1.day(), day);
1805 assert_eq!(d1.ordinal(), ordinal);
1806
1807 let d2 = NaiveDate::from_yo(year, ordinal);
1808 assert_eq!(d2.year(), year);
1809 assert_eq!(d2.month(), month);
1810 assert_eq!(d2.day(), day);
1811 assert_eq!(d2.ordinal(), ordinal);
1812
1813 assert_eq!(d1, d2);
1814 }
1815
1816 check(2012, 1, 1, 1);
1817 check(2012, 1, 2, 2);
1818 check(2012, 2, 1, 32);
1819 check(2012, 2, 29, 60);
1820 check(2012, 3, 1, 61);
1821 check(2012, 4, 9, 100);
1822 check(2012, 7, 18, 200);
1823 check(2012, 10, 26, 300);
1824 check(2012, 12, 31, 366);
1825
1826 check(2014, 1, 1, 1);
1827 check(2014, 1, 2, 2);
1828 check(2014, 2, 1, 32);
1829 check(2014, 2, 28, 59);
1830 check(2014, 3, 1, 60);
1831 check(2014, 4, 10, 100);
1832 check(2014, 7, 19, 200);
1833 check(2014, 10, 27, 300);
1834 check(2014, 12, 31, 365);
1835 }
1836
1837 #[test]
1838 fn test_date_weekday() {
1839 assert_eq!(NaiveDate::from_ymd(1582, 10, 15).weekday(), Weekday::Fri);
1840 // May 20, 1875 = ISO 8601 reference date
1841 assert_eq!(NaiveDate::from_ymd(1875, 5, 20).weekday(), Weekday::Thu);
1842 assert_eq!(NaiveDate::from_ymd(2000, 1, 1).weekday(), Weekday::Sat);
1843 }
1844
1845 #[test]
1846 fn test_date_with_fields() {
1847 let d = NaiveDate::from_ymd(2000, 2, 29);
1848 assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd(-400, 2, 29)));
1849 assert_eq!(d.with_year(-100), None);
1850 assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd(1600, 2, 29)));
1851 assert_eq!(d.with_year(1900), None);
1852 assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd(2000, 2, 29)));
1853 assert_eq!(d.with_year(2001), None);
1854 assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd(2004, 2, 29)));
1855 assert_eq!(d.with_year(i32::MAX), None);
1856
1857 let d = NaiveDate::from_ymd(2000, 4, 30);
1858 assert_eq!(d.with_month(0), None);
1859 assert_eq!(d.with_month(1), Some(NaiveDate::from_ymd(2000, 1, 30)));
1860 assert_eq!(d.with_month(2), None);
1861 assert_eq!(d.with_month(3), Some(NaiveDate::from_ymd(2000, 3, 30)));
1862 assert_eq!(d.with_month(4), Some(NaiveDate::from_ymd(2000, 4, 30)));
1863 assert_eq!(d.with_month(12), Some(NaiveDate::from_ymd(2000, 12, 30)));
1864 assert_eq!(d.with_month(13), None);
1865 assert_eq!(d.with_month(u32::MAX), None);
1866
1867 let d = NaiveDate::from_ymd(2000, 2, 8);
1868 assert_eq!(d.with_day(0), None);
1869 assert_eq!(d.with_day(1), Some(NaiveDate::from_ymd(2000, 2, 1)));
1870 assert_eq!(d.with_day(29), Some(NaiveDate::from_ymd(2000, 2, 29)));
1871 assert_eq!(d.with_day(30), None);
1872 assert_eq!(d.with_day(u32::MAX), None);
1873
1874 let d = NaiveDate::from_ymd(2000, 5, 5);
1875 assert_eq!(d.with_ordinal(0), None);
1876 assert_eq!(d.with_ordinal(1), Some(NaiveDate::from_ymd(2000, 1, 1)));
1877 assert_eq!(d.with_ordinal(60), Some(NaiveDate::from_ymd(2000, 2, 29)));
1878 assert_eq!(d.with_ordinal(61), Some(NaiveDate::from_ymd(2000, 3, 1)));
1879 assert_eq!(d.with_ordinal(366), Some(NaiveDate::from_ymd(2000, 12, 31)));
1880 assert_eq!(d.with_ordinal(367), None);
1881 assert_eq!(d.with_ordinal(u32::MAX), None);
1882 }
1883
1884 #[test]
1885 fn test_date_num_days_from_ce() {
1886 assert_eq!(NaiveDate::from_ymd(1, 1, 1).num_days_from_ce(), 1);
1887
1888 for year in -9999..10001 {
1889 assert_eq!(NaiveDate::from_ymd(year, 1, 1).num_days_from_ce(),
1890 NaiveDate::from_ymd(year - 1, 12, 31).num_days_from_ce() + 1);
1891 }
1892 }
1893
1894 #[test]
1895 fn test_date_succ() {
1896 let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d);
1897 assert_eq!(ymd(2014, 5, 6).succ_opt(), Some(ymd(2014, 5, 7)));
1898 assert_eq!(ymd(2014, 5, 31).succ_opt(), Some(ymd(2014, 6, 1)));
1899 assert_eq!(ymd(2014, 12, 31).succ_opt(), Some(ymd(2015, 1, 1)));
1900 assert_eq!(ymd(2016, 2, 28).succ_opt(), Some(ymd(2016, 2, 29)));
1901 assert_eq!(ymd(MAX_DATE.year(), 12, 31).succ_opt(), None);
1902 }
1903
1904 #[test]
1905 fn test_date_pred() {
1906 let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d);
1907 assert_eq!(ymd(2016, 3, 1).pred_opt(), Some(ymd(2016, 2, 29)));
1908 assert_eq!(ymd(2015, 1, 1).pred_opt(), Some(ymd(2014, 12, 31)));
1909 assert_eq!(ymd(2014, 6, 1).pred_opt(), Some(ymd(2014, 5, 31)));
1910 assert_eq!(ymd(2014, 5, 7).pred_opt(), Some(ymd(2014, 5, 6)));
1911 assert_eq!(ymd(MIN_DATE.year(), 1, 1).pred_opt(), None);
1912 }
1913
1914 #[test]
1915 fn test_date_add() {
1916 fn check((y1,m1,d1): (i32, u32, u32), rhs: Duration, ymd: Option<(i32, u32, u32)>) {
1917 let lhs = NaiveDate::from_ymd(y1, m1, d1);
1918 let sum = ymd.map(|(y,m,d)| NaiveDate::from_ymd(y, m, d));
1919 assert_eq!(lhs.checked_add_signed(rhs), sum);
1920 assert_eq!(lhs.checked_sub_signed(-rhs), sum);
1921 }
1922
1923 check((2014, 1, 1), Duration::zero(), Some((2014, 1, 1)));
1924 check((2014, 1, 1), Duration::seconds(86399), Some((2014, 1, 1)));
1925 // always round towards zero
1926 check((2014, 1, 1), Duration::seconds(-86399), Some((2014, 1, 1)));
1927 check((2014, 1, 1), Duration::days(1), Some((2014, 1, 2)));
1928 check((2014, 1, 1), Duration::days(-1), Some((2013, 12, 31)));
1929 check((2014, 1, 1), Duration::days(364), Some((2014, 12, 31)));
1930 check((2014, 1, 1), Duration::days(365*4 + 1), Some((2018, 1, 1)));
1931 check((2014, 1, 1), Duration::days(365*400 + 97), Some((2414, 1, 1)));
1932
1933 check((-7, 1, 1), Duration::days(365*12 + 3), Some((5, 1, 1)));
1934
1935 // overflow check
1936 check((0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64), Some((MAX_YEAR, 12, 31)));
1937 check((0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64 + 1), None);
1938 check((0, 1, 1), Duration::max_value(), None);
1939 check((0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64), Some((MIN_YEAR, 1, 1)));
1940 check((0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64 - 1), None);
1941 check((0, 1, 1), Duration::min_value(), None);
1942 }
1943
1944 #[test]
1945 fn test_date_sub() {
1946 fn check((y1,m1,d1): (i32, u32, u32), (y2,m2,d2): (i32, u32, u32), diff: Duration) {
1947 let lhs = NaiveDate::from_ymd(y1, m1, d1);
1948 let rhs = NaiveDate::from_ymd(y2, m2, d2);
1949 assert_eq!(lhs.signed_duration_since(rhs), diff);
1950 assert_eq!(rhs.signed_duration_since(lhs), -diff);
1951 }
1952
1953 check((2014, 1, 1), (2014, 1, 1), Duration::zero());
1954 check((2014, 1, 2), (2014, 1, 1), Duration::days(1));
1955 check((2014, 12, 31), (2014, 1, 1), Duration::days(364));
1956 check((2015, 1, 3), (2014, 1, 1), Duration::days(365 + 2));
1957 check((2018, 1, 1), (2014, 1, 1), Duration::days(365*4 + 1));
1958 check((2414, 1, 1), (2014, 1, 1), Duration::days(365*400 + 97));
1959
1960 check((MAX_YEAR, 12, 31), (0, 1, 1), Duration::days(MAX_DAYS_FROM_YEAR_0 as i64));
1961 check((MIN_YEAR, 1, 1), (0, 1, 1), Duration::days(MIN_DAYS_FROM_YEAR_0 as i64));
1962 }
1963
1964 #[test]
1965 fn test_date_addassignment() {
1966 let ymd = NaiveDate::from_ymd;
1967 let mut date = ymd(2016, 10, 1);
1968 date += Duration::days(10);
1969 assert_eq!(date, ymd(2016, 10, 11));
1970 date += Duration::days(30);
1971 assert_eq!(date, ymd(2016, 11, 10));
1972 }
1973
1974 #[test]
1975 fn test_date_subassignment() {
1976 let ymd = NaiveDate::from_ymd;
1977 let mut date = ymd(2016, 10, 11);
1978 date -= Duration::days(10);
1979 assert_eq!(date, ymd(2016, 10, 1));
1980 date -= Duration::days(2);
1981 assert_eq!(date, ymd(2016, 9, 29));
1982 }
1983
1984 #[test]
1985 fn test_date_fmt() {
1986 assert_eq!(format!("{:?}", NaiveDate::from_ymd(2012, 3, 4)), "2012-03-04");
1987 assert_eq!(format!("{:?}", NaiveDate::from_ymd(0, 3, 4)), "0000-03-04");
1988 assert_eq!(format!("{:?}", NaiveDate::from_ymd(-307, 3, 4)), "-0307-03-04");
1989 assert_eq!(format!("{:?}", NaiveDate::from_ymd(12345, 3, 4)), "+12345-03-04");
1990
1991 assert_eq!(NaiveDate::from_ymd(2012, 3, 4).to_string(), "2012-03-04");
1992 assert_eq!(NaiveDate::from_ymd(0, 3, 4).to_string(), "0000-03-04");
1993 assert_eq!(NaiveDate::from_ymd(-307, 3, 4).to_string(), "-0307-03-04");
1994 assert_eq!(NaiveDate::from_ymd(12345, 3, 4).to_string(), "+12345-03-04");
1995
1996 // the format specifier should have no effect on `NaiveTime`
1997 assert_eq!(format!("{:+30?}", NaiveDate::from_ymd(1234, 5, 6)), "1234-05-06");
1998 assert_eq!(format!("{:30?}", NaiveDate::from_ymd(12345, 6, 7)), "+12345-06-07");
1999 }
2000
2001 #[test]
2002 fn test_date_from_str() {
2003 // valid cases
2004 let valid = [
2005 "-0000000123456-1-2",
2006 " -123456 - 1 - 2 ",
2007 "-12345-1-2",
2008 "-1234-12-31",
2009 "-7-6-5",
2010 "350-2-28",
2011 "360-02-29",
2012 "0360-02-29",
2013 "2015-2 -18",
2014 "+70-2-18",
2015 "+70000-2-18",
2016 "+00007-2-18",
2017 ];
2018 for &s in &valid {
2019 let d = match s.parse::<NaiveDate>() {
2020 Ok(d) => d,
2021 Err(e) => panic!("parsing `{}` has failed: {}", s, e)
2022 };
2023 let s_ = format!("{:?}", d);
2024 // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same
2025 let d_ = match s_.parse::<NaiveDate>() {
2026 Ok(d) => d,
2027 Err(e) => panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}",
2028 s, d, e)
2029 };
2030 assert!(d == d_, "`{}` is parsed into `{:?}`, but reparsed result \
2031 `{:?}` does not match", s, d, d_);
2032 }
2033
2034 // some invalid cases
2035 // since `ParseErrorKind` is private, all we can do is to check if there was an error
2036 assert!("".parse::<NaiveDate>().is_err());
2037 assert!("x".parse::<NaiveDate>().is_err());
2038 assert!("2014".parse::<NaiveDate>().is_err());
2039 assert!("2014-01".parse::<NaiveDate>().is_err());
2040 assert!("2014-01-00".parse::<NaiveDate>().is_err());
2041 assert!("2014-13-57".parse::<NaiveDate>().is_err());
2042 assert!("9999999-9-9".parse::<NaiveDate>().is_err()); // out-of-bounds
2043 }
2044
2045 #[test]
2046 fn test_date_parse_from_str() {
2047 let ymd = |y,m,d| NaiveDate::from_ymd(y,m,d);
2048 assert_eq!(NaiveDate::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
2049 Ok(ymd(2014, 5, 7))); // ignore time and offset
2050 assert_eq!(NaiveDate::parse_from_str("2015-W06-1=2015-033", "%G-W%V-%u = %Y-%j"),
2051 Ok(ymd(2015, 2, 2)));
2052 assert_eq!(NaiveDate::parse_from_str("Fri, 09 Aug 13", "%a, %d %b %y"),
2053 Ok(ymd(2013, 8, 9)));
2054 assert!(NaiveDate::parse_from_str("Sat, 09 Aug 2013", "%a, %d %b %Y").is_err());
2055 assert!(NaiveDate::parse_from_str("2014-57", "%Y-%m-%d").is_err());
2056 assert!(NaiveDate::parse_from_str("2014", "%Y").is_err()); // insufficient
2057 }
2058
2059 #[test]
2060 fn test_date_format() {
2061 let d = NaiveDate::from_ymd(2012, 3, 4);
2062 assert_eq!(d.format("%Y,%C,%y,%G,%g").to_string(), "2012,20,12,2012,12");
2063 assert_eq!(d.format("%m,%b,%h,%B").to_string(), "03,Mar,Mar,March");
2064 assert_eq!(d.format("%d,%e").to_string(), "04, 4");
2065 assert_eq!(d.format("%U,%W,%V").to_string(), "10,09,09");
2066 assert_eq!(d.format("%a,%A,%w,%u").to_string(), "Sun,Sunday,0,7");
2067 assert_eq!(d.format("%j").to_string(), "064"); // since 2012 is a leap year
2068 assert_eq!(d.format("%D,%x").to_string(), "03/04/12,03/04/12");
2069 assert_eq!(d.format("%F").to_string(), "2012-03-04");
2070 assert_eq!(d.format("%v").to_string(), " 4-Mar-2012");
2071 assert_eq!(d.format("%t%n%%%n%t").to_string(), "\t\n%\n\t");
2072
2073 // non-four-digit years
2074 assert_eq!(NaiveDate::from_ymd(12345, 1, 1).format("%Y").to_string(), "+12345");
2075 assert_eq!(NaiveDate::from_ymd(1234, 1, 1).format("%Y").to_string(), "1234");
2076 assert_eq!(NaiveDate::from_ymd(123, 1, 1).format("%Y").to_string(), "0123");
2077 assert_eq!(NaiveDate::from_ymd(12, 1, 1).format("%Y").to_string(), "0012");
2078 assert_eq!(NaiveDate::from_ymd(1, 1, 1).format("%Y").to_string(), "0001");
2079 assert_eq!(NaiveDate::from_ymd(0, 1, 1).format("%Y").to_string(), "0000");
2080 assert_eq!(NaiveDate::from_ymd(-1, 1, 1).format("%Y").to_string(), "-0001");
2081 assert_eq!(NaiveDate::from_ymd(-12, 1, 1).format("%Y").to_string(), "-0012");
2082 assert_eq!(NaiveDate::from_ymd(-123, 1, 1).format("%Y").to_string(), "-0123");
2083 assert_eq!(NaiveDate::from_ymd(-1234, 1, 1).format("%Y").to_string(), "-1234");
2084 assert_eq!(NaiveDate::from_ymd(-12345, 1, 1).format("%Y").to_string(), "-12345");
2085
2086 // corner cases
2087 assert_eq!(NaiveDate::from_ymd(2007, 12, 31).format("%G,%g,%U,%W,%V").to_string(),
2088 "2008,08,53,53,01");
2089 assert_eq!(NaiveDate::from_ymd(2010, 1, 3).format("%G,%g,%U,%W,%V").to_string(),
2090 "2009,09,01,00,53");
2091 }
2092}
2093