]> git.proxmox.com Git - cargo.git/blob - vendor/chrono/src/naive/time.rs
New upstream version 0.33.0
[cargo.git] / vendor / chrono / src / naive / time.rs
1 // This is a part of Chrono.
2 // See README.md and LICENSE.txt for details.
3
4 //! ISO 8601 time without timezone.
5
6 use std::{str, fmt, hash};
7 use std::ops::{Add, Sub, AddAssign, SubAssign};
8 use oldtime::Duration as OldDuration;
9
10 use Timelike;
11 use div::div_mod_floor;
12 use format::{Item, Numeric, Pad, Fixed};
13 use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
14
15 /// ISO 8601 time without timezone.
16 /// Allows for the nanosecond precision and optional leap second representation.
17 ///
18 /// # Leap Second Handling
19 ///
20 /// Since 1960s, the manmade atomic clock has been so accurate that
21 /// it is much more accurate than Earth's own motion.
22 /// It became desirable to define the civil time in terms of the atomic clock,
23 /// but that risks the desynchronization of the civil time from Earth.
24 /// To account for this, the designers of the Coordinated Universal Time (UTC)
25 /// made that the UTC should be kept within 0.9 seconds of the observed Earth-bound time.
26 /// When the mean solar day is longer than the ideal (86,400 seconds),
27 /// the error slowly accumulates and it is necessary to add a **leap second**
28 /// to slow the UTC down a bit.
29 /// (We may also remove a second to speed the UTC up a bit, but it never happened.)
30 /// The leap second, if any, follows 23:59:59 of June 30 or December 31 in the UTC.
31 ///
32 /// Fast forward to the 21st century,
33 /// we have seen 26 leap seconds from January 1972 to December 2015.
34 /// Yes, 26 seconds. Probably you can read this paragraph within 26 seconds.
35 /// But those 26 seconds, and possibly more in the future, are never predictable,
36 /// and whether to add a leap second or not is known only before 6 months.
37 /// Internet-based clocks (via NTP) do account for known leap seconds,
38 /// but the system API normally doesn't (and often can't, with no network connection)
39 /// and there is no reliable way to retrieve leap second information.
40 ///
41 /// Chrono does not try to accurately implement leap seconds; it is impossible.
42 /// Rather, **it allows for leap seconds but behaves as if there are *no other* leap seconds.**
43 /// Various operations will ignore any possible leap second(s)
44 /// except when any of the operands were actually leap seconds.
45 ///
46 /// If you cannot tolerate this behavior,
47 /// you must use a separate `TimeZone` for the International Atomic Time (TAI).
48 /// TAI is like UTC but has no leap seconds, and thus slightly differs from UTC.
49 /// Chrono does not yet provide such implementation, but it is planned.
50 ///
51 /// ## Representing Leap Seconds
52 ///
53 /// The leap second is indicated via fractional seconds more than 1 second.
54 /// This makes possible to treat a leap second as the prior non-leap second
55 /// if you don't care about sub-second accuracy.
56 /// You should use the proper formatting to get the raw leap second.
57 ///
58 /// All methods accepting fractional seconds will accept such values.
59 ///
60 /// ~~~~
61 /// use chrono::{NaiveDate, NaiveTime, Utc, TimeZone};
62 ///
63 /// let t = NaiveTime::from_hms_milli(8, 59, 59, 1_000);
64 ///
65 /// let dt1 = NaiveDate::from_ymd(2015, 7, 1).and_hms_micro(8, 59, 59, 1_000_000);
66 ///
67 /// let dt2 = Utc.ymd(2015, 6, 30).and_hms_nano(23, 59, 59, 1_000_000_000);
68 /// # let _ = (t, dt1, dt2);
69 /// ~~~~
70 ///
71 /// Note that the leap second can happen anytime given an appropriate time zone;
72 /// 2015-07-01 01:23:60 would be a proper leap second if UTC+01:24 had existed.
73 /// Practically speaking, though, by the time of the first leap second on 1972-06-30,
74 /// every time zone offset around the world has standardized to the 5-minute alignment.
75 ///
76 /// ## Date And Time Arithmetics
77 ///
78 /// As a concrete example, let's assume that `03:00:60` and `04:00:60` are leap seconds.
79 /// In reality, of course, leap seconds are separated by at least 6 months.
80 /// We will also use some intuitive concise notations for the explanation.
81 ///
82 /// `Time + Duration`
83 /// (short for [`NaiveTime::overflowing_add_signed`](#method.overflowing_add_signed)):
84 ///
85 /// - `03:00:00 + 1s = 03:00:01`.
86 /// - `03:00:59 + 60s = 03:02:00`.
87 /// - `03:00:59 + 1s = 03:01:00`.
88 /// - `03:00:60 + 1s = 03:01:00`.
89 /// Note that the sum is identical to the previous.
90 /// - `03:00:60 + 60s = 03:01:59`.
91 /// - `03:00:60 + 61s = 03:02:00`.
92 /// - `03:00:60.1 + 0.8s = 03:00:60.9`.
93 ///
94 /// `Time - Duration`
95 /// (short for [`NaiveTime::overflowing_sub_signed`](#method.overflowing_sub_signed)):
96 ///
97 /// - `03:00:00 - 1s = 02:59:59`.
98 /// - `03:01:00 - 1s = 03:00:59`.
99 /// - `03:01:00 - 60s = 03:00:00`.
100 /// - `03:00:60 - 60s = 03:00:00`.
101 /// Note that the result is identical to the previous.
102 /// - `03:00:60.7 - 0.4s = 03:00:60.3`.
103 /// - `03:00:60.7 - 0.9s = 03:00:59.8`.
104 ///
105 /// `Time - Time`
106 /// (short for [`NaiveTime::signed_duration_since`](#method.signed_duration_since)):
107 ///
108 /// - `04:00:00 - 03:00:00 = 3600s`.
109 /// - `03:01:00 - 03:00:00 = 60s`.
110 /// - `03:00:60 - 03:00:00 = 60s`.
111 /// Note that the difference is identical to the previous.
112 /// - `03:00:60.6 - 03:00:59.4 = 1.2s`.
113 /// - `03:01:00 - 03:00:59.8 = 0.2s`.
114 /// - `03:01:00 - 03:00:60.5 = 0.5s`.
115 /// Note that the difference is larger than the previous,
116 /// even though the leap second clearly follows the previous whole second.
117 /// - `04:00:60.9 - 03:00:60.1 =
118 /// (04:00:60.9 - 04:00:00) + (04:00:00 - 03:01:00) + (03:01:00 - 03:00:60.1) =
119 /// 60.9s + 3540s + 0.9s = 3601.8s`.
120 ///
121 /// In general,
122 ///
123 /// - `Time + Duration` unconditionally equals to `Duration + Time`.
124 ///
125 /// - `Time - Duration` unconditionally equals to `Time + (-Duration)`.
126 ///
127 /// - `Time1 - Time2` unconditionally equals to `-(Time2 - Time1)`.
128 ///
129 /// - Associativity does not generally hold, because
130 /// `(Time + Duration1) - Duration2` no longer equals to `Time + (Duration1 - Duration2)`
131 /// for two positive durations.
132 ///
133 /// - As a special case, `(Time + Duration) - Duration` also does not equal to `Time`.
134 ///
135 /// - If you can assume that all durations have the same sign, however,
136 /// then the associativity holds:
137 /// `(Time + Duration1) + Duration2` equals to `Time + (Duration1 + Duration2)`
138 /// for two positive durations.
139 ///
140 /// ## Reading And Writing Leap Seconds
141 ///
142 /// The "typical" leap seconds on the minute boundary are
143 /// correctly handled both in the formatting and parsing.
144 /// The leap second in the human-readable representation
145 /// will be represented as the second part being 60, as required by ISO 8601.
146 ///
147 /// ~~~~
148 /// use chrono::{Utc, TimeZone};
149 ///
150 /// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_000);
151 /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60Z");
152 /// ~~~~
153 ///
154 /// There are hypothetical leap seconds not on the minute boundary
155 /// nevertheless supported by Chrono.
156 /// They are allowed for the sake of completeness and consistency;
157 /// there were several "exotic" time zone offsets with fractional minutes prior to UTC after all.
158 /// For such cases the human-readable representation is ambiguous
159 /// and would be read back to the next non-leap second.
160 ///
161 /// ~~~~
162 /// use chrono::{DateTime, Utc, TimeZone};
163 ///
164 /// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 56, 4, 1_000);
165 /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z");
166 ///
167 /// let dt = Utc.ymd(2015, 6, 30).and_hms(23, 56, 5);
168 /// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z");
169 /// assert_eq!(DateTime::parse_from_rfc3339("2015-06-30T23:56:05Z").unwrap(), dt);
170 /// ~~~~
171 ///
172 /// Since Chrono alone cannot determine any existence of leap seconds,
173 /// **there is absolutely no guarantee that the leap second read has actually happened**.
174 #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
175 pub struct NaiveTime {
176 secs: u32,
177 frac: u32,
178 }
179
180 impl NaiveTime {
181 /// Makes a new `NaiveTime` from hour, minute and second.
182 ///
183 /// No [leap second](#leap-second-handling) is allowed here;
184 /// use `NaiveTime::from_hms_*` methods with a subsecond parameter instead.
185 ///
186 /// Panics on invalid hour, minute and/or second.
187 ///
188 /// # Example
189 ///
190 /// ~~~~
191 /// use chrono::{NaiveTime, Timelike};
192 ///
193 /// let t = NaiveTime::from_hms(23, 56, 4);
194 /// assert_eq!(t.hour(), 23);
195 /// assert_eq!(t.minute(), 56);
196 /// assert_eq!(t.second(), 4);
197 /// assert_eq!(t.nanosecond(), 0);
198 /// ~~~~
199 #[inline]
200 pub fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTime {
201 NaiveTime::from_hms_opt(hour, min, sec).expect("invalid time")
202 }
203
204 /// Makes a new `NaiveTime` from hour, minute and second.
205 ///
206 /// No [leap second](#leap-second-handling) is allowed here;
207 /// use `NaiveTime::from_hms_*_opt` methods with a subsecond parameter instead.
208 ///
209 /// Returns `None` on invalid hour, minute and/or second.
210 ///
211 /// # Example
212 ///
213 /// ~~~~
214 /// use chrono::NaiveTime;
215 ///
216 /// let from_hms_opt = NaiveTime::from_hms_opt;
217 ///
218 /// assert!(from_hms_opt(0, 0, 0).is_some());
219 /// assert!(from_hms_opt(23, 59, 59).is_some());
220 /// assert!(from_hms_opt(24, 0, 0).is_none());
221 /// assert!(from_hms_opt(23, 60, 0).is_none());
222 /// assert!(from_hms_opt(23, 59, 60).is_none());
223 /// ~~~~
224 #[inline]
225 pub fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> {
226 NaiveTime::from_hms_nano_opt(hour, min, sec, 0)
227 }
228
229 /// Makes a new `NaiveTime` from hour, minute, second and millisecond.
230 ///
231 /// The millisecond part can exceed 1,000
232 /// in order to represent the [leap second](#leap-second-handling).
233 ///
234 /// Panics on invalid hour, minute, second and/or millisecond.
235 ///
236 /// # Example
237 ///
238 /// ~~~~
239 /// use chrono::{NaiveTime, Timelike};
240 ///
241 /// let t = NaiveTime::from_hms_milli(23, 56, 4, 12);
242 /// assert_eq!(t.hour(), 23);
243 /// assert_eq!(t.minute(), 56);
244 /// assert_eq!(t.second(), 4);
245 /// assert_eq!(t.nanosecond(), 12_000_000);
246 /// ~~~~
247 #[inline]
248 pub fn from_hms_milli(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTime {
249 NaiveTime::from_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
250 }
251
252 /// Makes a new `NaiveTime` from hour, minute, second and millisecond.
253 ///
254 /// The millisecond part can exceed 1,000
255 /// in order to represent the [leap second](#leap-second-handling).
256 ///
257 /// Returns `None` on invalid hour, minute, second and/or millisecond.
258 ///
259 /// # Example
260 ///
261 /// ~~~~
262 /// use chrono::NaiveTime;
263 ///
264 /// let from_hmsm_opt = NaiveTime::from_hms_milli_opt;
265 ///
266 /// assert!(from_hmsm_opt(0, 0, 0, 0).is_some());
267 /// assert!(from_hmsm_opt(23, 59, 59, 999).is_some());
268 /// assert!(from_hmsm_opt(23, 59, 59, 1_999).is_some()); // a leap second after 23:59:59
269 /// assert!(from_hmsm_opt(24, 0, 0, 0).is_none());
270 /// assert!(from_hmsm_opt(23, 60, 0, 0).is_none());
271 /// assert!(from_hmsm_opt(23, 59, 60, 0).is_none());
272 /// assert!(from_hmsm_opt(23, 59, 59, 2_000).is_none());
273 /// ~~~~
274 #[inline]
275 pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> {
276 milli.checked_mul(1_000_000)
277 .and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
278 }
279
280 /// Makes a new `NaiveTime` from hour, minute, second and microsecond.
281 ///
282 /// The microsecond part can exceed 1,000,000
283 /// in order to represent the [leap second](#leap-second-handling).
284 ///
285 /// Panics on invalid hour, minute, second and/or microsecond.
286 ///
287 /// # Example
288 ///
289 /// ~~~~
290 /// use chrono::{NaiveTime, Timelike};
291 ///
292 /// let t = NaiveTime::from_hms_micro(23, 56, 4, 12_345);
293 /// assert_eq!(t.hour(), 23);
294 /// assert_eq!(t.minute(), 56);
295 /// assert_eq!(t.second(), 4);
296 /// assert_eq!(t.nanosecond(), 12_345_000);
297 /// ~~~~
298 #[inline]
299 pub fn from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> NaiveTime {
300 NaiveTime::from_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
301 }
302
303 /// Makes a new `NaiveTime` from hour, minute, second and microsecond.
304 ///
305 /// The microsecond part can exceed 1,000,000
306 /// in order to represent the [leap second](#leap-second-handling).
307 ///
308 /// Returns `None` on invalid hour, minute, second and/or microsecond.
309 ///
310 /// # Example
311 ///
312 /// ~~~~
313 /// use chrono::NaiveTime;
314 ///
315 /// let from_hmsu_opt = NaiveTime::from_hms_micro_opt;
316 ///
317 /// assert!(from_hmsu_opt(0, 0, 0, 0).is_some());
318 /// assert!(from_hmsu_opt(23, 59, 59, 999_999).is_some());
319 /// assert!(from_hmsu_opt(23, 59, 59, 1_999_999).is_some()); // a leap second after 23:59:59
320 /// assert!(from_hmsu_opt(24, 0, 0, 0).is_none());
321 /// assert!(from_hmsu_opt(23, 60, 0, 0).is_none());
322 /// assert!(from_hmsu_opt(23, 59, 60, 0).is_none());
323 /// assert!(from_hmsu_opt(23, 59, 59, 2_000_000).is_none());
324 /// ~~~~
325 #[inline]
326 pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> {
327 micro.checked_mul(1_000)
328 .and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
329 }
330
331 /// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
332 ///
333 /// The nanosecond part can exceed 1,000,000,000
334 /// in order to represent the [leap second](#leap-second-handling).
335 ///
336 /// Panics on invalid hour, minute, second and/or nanosecond.
337 ///
338 /// # Example
339 ///
340 /// ~~~~
341 /// use chrono::{NaiveTime, Timelike};
342 ///
343 /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
344 /// assert_eq!(t.hour(), 23);
345 /// assert_eq!(t.minute(), 56);
346 /// assert_eq!(t.second(), 4);
347 /// assert_eq!(t.nanosecond(), 12_345_678);
348 /// ~~~~
349 #[inline]
350 pub fn from_hms_nano(hour: u32, min: u32, sec: u32, nano: u32) -> NaiveTime {
351 NaiveTime::from_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
352 }
353
354 /// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
355 ///
356 /// The nanosecond part can exceed 1,000,000,000
357 /// in order to represent the [leap second](#leap-second-handling).
358 ///
359 /// Returns `None` on invalid hour, minute, second and/or nanosecond.
360 ///
361 /// # Example
362 ///
363 /// ~~~~
364 /// use chrono::NaiveTime;
365 ///
366 /// let from_hmsn_opt = NaiveTime::from_hms_nano_opt;
367 ///
368 /// assert!(from_hmsn_opt(0, 0, 0, 0).is_some());
369 /// assert!(from_hmsn_opt(23, 59, 59, 999_999_999).is_some());
370 /// assert!(from_hmsn_opt(23, 59, 59, 1_999_999_999).is_some()); // a leap second after 23:59:59
371 /// assert!(from_hmsn_opt(24, 0, 0, 0).is_none());
372 /// assert!(from_hmsn_opt(23, 60, 0, 0).is_none());
373 /// assert!(from_hmsn_opt(23, 59, 60, 0).is_none());
374 /// assert!(from_hmsn_opt(23, 59, 59, 2_000_000_000).is_none());
375 /// ~~~~
376 #[inline]
377 pub fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> {
378 if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; }
379 let secs = hour * 3600 + min * 60 + sec;
380 Some(NaiveTime { secs: secs, frac: nano })
381 }
382
383 /// Makes a new `NaiveTime` from the number of seconds since midnight and nanosecond.
384 ///
385 /// The nanosecond part can exceed 1,000,000,000
386 /// in order to represent the [leap second](#leap-second-handling).
387 ///
388 /// Panics on invalid number of seconds and/or nanosecond.
389 ///
390 /// # Example
391 ///
392 /// ~~~~
393 /// use chrono::{NaiveTime, Timelike};
394 ///
395 /// let t = NaiveTime::from_num_seconds_from_midnight(86164, 12_345_678);
396 /// assert_eq!(t.hour(), 23);
397 /// assert_eq!(t.minute(), 56);
398 /// assert_eq!(t.second(), 4);
399 /// assert_eq!(t.nanosecond(), 12_345_678);
400 /// ~~~~
401 #[inline]
402 pub fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> NaiveTime {
403 NaiveTime::from_num_seconds_from_midnight_opt(secs, nano).expect("invalid time")
404 }
405
406 /// Makes a new `NaiveTime` from the number of seconds since midnight and nanosecond.
407 ///
408 /// The nanosecond part can exceed 1,000,000,000
409 /// in order to represent the [leap second](#leap-second-handling).
410 ///
411 /// Returns `None` on invalid number of seconds and/or nanosecond.
412 ///
413 /// # Example
414 ///
415 /// ~~~~
416 /// use chrono::NaiveTime;
417 ///
418 /// let from_nsecs_opt = NaiveTime::from_num_seconds_from_midnight_opt;
419 ///
420 /// assert!(from_nsecs_opt(0, 0).is_some());
421 /// assert!(from_nsecs_opt(86399, 999_999_999).is_some());
422 /// assert!(from_nsecs_opt(86399, 1_999_999_999).is_some()); // a leap second after 23:59:59
423 /// assert!(from_nsecs_opt(86_400, 0).is_none());
424 /// assert!(from_nsecs_opt(86399, 2_000_000_000).is_none());
425 /// ~~~~
426 #[inline]
427 pub fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime> {
428 if secs >= 86_400 || nano >= 2_000_000_000 { return None; }
429 Some(NaiveTime { secs: secs, frac: nano })
430 }
431
432 /// Parses a string with the specified format string and returns a new `NaiveTime`.
433 /// See the [`format::strftime` module](../format/strftime/index.html)
434 /// on the supported escape sequences.
435 ///
436 /// # Example
437 ///
438 /// ~~~~
439 /// use chrono::NaiveTime;
440 ///
441 /// let parse_from_str = NaiveTime::parse_from_str;
442 ///
443 /// assert_eq!(parse_from_str("23:56:04", "%H:%M:%S"),
444 /// Ok(NaiveTime::from_hms(23, 56, 4)));
445 /// assert_eq!(parse_from_str("pm012345.6789", "%p%I%M%S%.f"),
446 /// Ok(NaiveTime::from_hms_micro(13, 23, 45, 678_900)));
447 /// ~~~~
448 ///
449 /// Date and offset is ignored for the purpose of parsing.
450 ///
451 /// ~~~~
452 /// # use chrono::NaiveTime;
453 /// # let parse_from_str = NaiveTime::parse_from_str;
454 /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
455 /// Ok(NaiveTime::from_hms(12, 34, 56)));
456 /// ~~~~
457 ///
458 /// [Leap seconds](#leap-second-handling) are correctly handled by
459 /// treating any time of the form `hh:mm:60` as a leap second.
460 /// (This equally applies to the formatting, so the round trip is possible.)
461 ///
462 /// ~~~~
463 /// # use chrono::NaiveTime;
464 /// # let parse_from_str = NaiveTime::parse_from_str;
465 /// assert_eq!(parse_from_str("08:59:60.123", "%H:%M:%S%.f"),
466 /// Ok(NaiveTime::from_hms_milli(8, 59, 59, 1_123)));
467 /// ~~~~
468 ///
469 /// Missing seconds are assumed to be zero,
470 /// but out-of-bound times or insufficient fields are errors otherwise.
471 ///
472 /// ~~~~
473 /// # use chrono::NaiveTime;
474 /// # let parse_from_str = NaiveTime::parse_from_str;
475 /// assert_eq!(parse_from_str("7:15", "%H:%M"),
476 /// Ok(NaiveTime::from_hms(7, 15, 0)));
477 ///
478 /// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err());
479 /// assert!(parse_from_str("12", "%H").is_err());
480 /// assert!(parse_from_str("17:60", "%H:%M").is_err());
481 /// assert!(parse_from_str("24:00:00", "%H:%M:%S").is_err());
482 /// ~~~~
483 ///
484 /// All parsed fields should be consistent to each other, otherwise it's an error.
485 /// Here `%H` is for 24-hour clocks, unlike `%I`,
486 /// and thus can be independently determined without AM/PM.
487 ///
488 /// ~~~~
489 /// # use chrono::NaiveTime;
490 /// # let parse_from_str = NaiveTime::parse_from_str;
491 /// assert!(parse_from_str("13:07 AM", "%H:%M %p").is_err());
492 /// ~~~~
493 pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime> {
494 let mut parsed = Parsed::new();
495 try!(parse(&mut parsed, s, StrftimeItems::new(fmt)));
496 parsed.to_naive_time()
497 }
498
499 /// Adds given `Duration` to the current time,
500 /// and also returns the number of *seconds*
501 /// in the integral number of days ignored from the addition.
502 /// (We cannot return `Duration` because it is subject to overflow or underflow.)
503 ///
504 /// # Example
505 ///
506 /// ~~~~
507 /// # extern crate chrono; extern crate time; fn main() {
508 /// use chrono::NaiveTime;
509 /// use time::Duration;
510 ///
511 /// let from_hms = NaiveTime::from_hms;
512 ///
513 /// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(11)),
514 /// (from_hms(14, 4, 5), 0));
515 /// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(23)),
516 /// (from_hms(2, 4, 5), 86_400));
517 /// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(-7)),
518 /// (from_hms(20, 4, 5), -86_400));
519 /// # }
520 /// ~~~~
521 #[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
522 pub fn overflowing_add_signed(&self, mut rhs: OldDuration) -> (NaiveTime, i64) {
523 let mut secs = self.secs;
524 let mut frac = self.frac;
525
526 // check if `self` is a leap second and adding `rhs` would escape that leap second.
527 // if it's the case, update `self` and `rhs` to involve no leap second;
528 // otherwise the addition immediately finishes.
529 if frac >= 1_000_000_000 {
530 let rfrac = 2_000_000_000 - frac;
531 if rhs >= OldDuration::nanoseconds(i64::from(rfrac)) {
532 rhs = rhs - OldDuration::nanoseconds(i64::from(rfrac));
533 secs += 1;
534 frac = 0;
535 } else if rhs < OldDuration::nanoseconds(-i64::from(frac)) {
536 rhs = rhs + OldDuration::nanoseconds(i64::from(frac));
537 frac = 0;
538 } else {
539 frac = (i64::from(frac) + rhs.num_nanoseconds().unwrap()) as u32;
540 debug_assert!(frac < 2_000_000_000);
541 return (NaiveTime { secs: secs, frac: frac }, 0);
542 }
543 }
544 debug_assert!(secs <= 86_400);
545 debug_assert!(frac < 1_000_000_000);
546
547 let rhssecs = rhs.num_seconds();
548 let rhsfrac = (rhs - OldDuration::seconds(rhssecs)).num_nanoseconds().unwrap();
549 debug_assert_eq!(OldDuration::seconds(rhssecs) + OldDuration::nanoseconds(rhsfrac), rhs);
550 let rhssecsinday = rhssecs % 86_400;
551 let mut morerhssecs = rhssecs - rhssecsinday;
552 let rhssecs = rhssecsinday as i32;
553 let rhsfrac = rhsfrac as i32;
554 debug_assert!(-86_400 < rhssecs && rhssecs < 86_400);
555 debug_assert_eq!(morerhssecs % 86_400, 0);
556 debug_assert!(-1_000_000_000 < rhsfrac && rhsfrac < 1_000_000_000);
557
558 let mut secs = secs as i32 + rhssecs;
559 let mut frac = frac as i32 + rhsfrac;
560 debug_assert!(-86_400 < secs && secs < 2 * 86_400);
561 debug_assert!(-1_000_000_000 < frac && frac < 2_000_000_000);
562
563 if frac < 0 {
564 frac += 1_000_000_000;
565 secs -= 1;
566 } else if frac >= 1_000_000_000 {
567 frac -= 1_000_000_000;
568 secs += 1;
569 }
570 debug_assert!(-86_400 <= secs && secs < 2 * 86_400);
571 debug_assert!(0 <= frac && frac < 1_000_000_000);
572
573 if secs < 0 {
574 secs += 86_400;
575 morerhssecs -= 86_400;
576 } else if secs >= 86_400 {
577 secs -= 86_400;
578 morerhssecs += 86_400;
579 }
580 debug_assert!(0 <= secs && secs < 86_400);
581
582 (NaiveTime { secs: secs as u32, frac: frac as u32 }, morerhssecs)
583 }
584
585 /// Subtracts given `Duration` from the current time,
586 /// and also returns the number of *seconds*
587 /// in the integral number of days ignored from the subtraction.
588 /// (We cannot return `Duration` because it is subject to overflow or underflow.)
589 ///
590 /// # Example
591 ///
592 /// ~~~~
593 /// # extern crate chrono; extern crate time; fn main() {
594 /// use chrono::NaiveTime;
595 /// use time::Duration;
596 ///
597 /// let from_hms = NaiveTime::from_hms;
598 ///
599 /// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(2)),
600 /// (from_hms(1, 4, 5), 0));
601 /// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(17)),
602 /// (from_hms(10, 4, 5), 86_400));
603 /// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(-22)),
604 /// (from_hms(1, 4, 5), -86_400));
605 /// # }
606 /// ~~~~
607 #[inline]
608 pub fn overflowing_sub_signed(&self, rhs: OldDuration) -> (NaiveTime, i64) {
609 let (time, rhs) = self.overflowing_add_signed(-rhs);
610 (time, -rhs) // safe to negate, rhs is within +/- (2^63 / 1000)
611 }
612
613 /// Subtracts another `NaiveTime` from the current time.
614 /// Returns a `Duration` within +/- 1 day.
615 /// This does not overflow or underflow at all.
616 ///
617 /// As a part of Chrono's [leap second handling](#leap-second-handling),
618 /// the subtraction assumes that **there is no leap second ever**,
619 /// except when any of the `NaiveTime`s themselves represents a leap second
620 /// in which case the assumption becomes that
621 /// **there are exactly one (or two) leap second(s) ever**.
622 ///
623 /// # Example
624 ///
625 /// ~~~~
626 /// # extern crate chrono; extern crate time; fn main() {
627 /// use chrono::NaiveTime;
628 /// use time::Duration;
629 ///
630 /// let from_hmsm = NaiveTime::from_hms_milli;
631 /// let since = NaiveTime::signed_duration_since;
632 ///
633 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 7, 900)),
634 /// Duration::zero());
635 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 7, 875)),
636 /// Duration::milliseconds(25));
637 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 6, 925)),
638 /// Duration::milliseconds(975));
639 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 0, 900)),
640 /// Duration::seconds(7));
641 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 0, 7, 900)),
642 /// Duration::seconds(5 * 60));
643 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(0, 5, 7, 900)),
644 /// Duration::seconds(3 * 3600));
645 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(4, 5, 7, 900)),
646 /// Duration::seconds(-3600));
647 /// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(2, 4, 6, 800)),
648 /// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100));
649 /// # }
650 /// ~~~~
651 ///
652 /// Leap seconds are handled, but the subtraction assumes that
653 /// there were no other leap seconds happened.
654 ///
655 /// ~~~~
656 /// # extern crate chrono; extern crate time; fn main() {
657 /// # use chrono::NaiveTime;
658 /// # use time::Duration;
659 /// # let from_hmsm = NaiveTime::from_hms_milli;
660 /// # let since = NaiveTime::signed_duration_since;
661 /// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(3, 0, 59, 0)),
662 /// Duration::seconds(1));
663 /// assert_eq!(since(from_hmsm(3, 0, 59, 1_500), from_hmsm(3, 0, 59, 0)),
664 /// Duration::milliseconds(1500));
665 /// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(3, 0, 0, 0)),
666 /// Duration::seconds(60));
667 /// assert_eq!(since(from_hmsm(3, 0, 0, 0), from_hmsm(2, 59, 59, 1_000)),
668 /// Duration::seconds(1));
669 /// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(2, 59, 59, 1_000)),
670 /// Duration::seconds(61));
671 /// # }
672 /// ~~~~
673 pub fn signed_duration_since(self, rhs: NaiveTime) -> OldDuration {
674 // | | :leap| | | | | | | :leap| |
675 // | | : | | | | | | | : | |
676 // ----+----+-----*---+----+----+----+----+----+----+-------*-+----+----
677 // | `rhs` | | `self`
678 // |======================================>| |
679 // | | `self.secs - rhs.secs` |`self.frac`
680 // |====>| | |======>|
681 // `rhs.frac`|========================================>|
682 // | | | `self - rhs` | |
683
684 use std::cmp::Ordering;
685
686 let secs = i64::from(self.secs) - i64::from(rhs.secs);
687 let frac = i64::from(self.frac) - i64::from(rhs.frac);
688
689 // `secs` may contain a leap second yet to be counted
690 let adjust = match self.secs.cmp(&rhs.secs) {
691 Ordering::Greater => if rhs.frac >= 1_000_000_000 { 1 } else { 0 },
692 Ordering::Equal => 0,
693 Ordering::Less => if self.frac >= 1_000_000_000 { -1 } else { 0 },
694 };
695
696 OldDuration::seconds(secs + adjust) + OldDuration::nanoseconds(frac)
697 }
698
699 /// Formats the time with the specified formatting items.
700 /// Otherwise it is same to the ordinary [`format`](#method.format) method.
701 ///
702 /// The `Iterator` of items should be `Clone`able,
703 /// since the resulting `DelayedFormat` value may be formatted multiple times.
704 ///
705 /// # Example
706 ///
707 /// ~~~~
708 /// use chrono::NaiveTime;
709 /// use chrono::format::strftime::StrftimeItems;
710 ///
711 /// let fmt = StrftimeItems::new("%H:%M:%S");
712 /// let t = NaiveTime::from_hms(23, 56, 4);
713 /// assert_eq!(t.format_with_items(fmt.clone()).to_string(), "23:56:04");
714 /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04");
715 /// ~~~~
716 ///
717 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
718 ///
719 /// ~~~~
720 /// # use chrono::NaiveTime;
721 /// # use chrono::format::strftime::StrftimeItems;
722 /// # let fmt = StrftimeItems::new("%H:%M:%S").clone();
723 /// # let t = NaiveTime::from_hms(23, 56, 4);
724 /// assert_eq!(format!("{}", t.format_with_items(fmt)), "23:56:04");
725 /// ~~~~
726 #[inline]
727 pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
728 where I: Iterator<Item=Item<'a>> + Clone {
729 DelayedFormat::new(None, Some(*self), items)
730 }
731
732 /// Formats the time with the specified format string.
733 /// See the [`format::strftime` module](../format/strftime/index.html)
734 /// on the supported escape sequences.
735 ///
736 /// This returns a `DelayedFormat`,
737 /// which gets converted to a string only when actual formatting happens.
738 /// You may use the `to_string` method to get a `String`,
739 /// or just feed it into `print!` and other formatting macros.
740 /// (In this way it avoids the redundant memory allocation.)
741 ///
742 /// A wrong format string does *not* issue an error immediately.
743 /// Rather, converting or formatting the `DelayedFormat` fails.
744 /// You are recommended to immediately use `DelayedFormat` for this reason.
745 ///
746 /// # Example
747 ///
748 /// ~~~~
749 /// use chrono::NaiveTime;
750 ///
751 /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
752 /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04");
753 /// assert_eq!(t.format("%H:%M:%S%.6f").to_string(), "23:56:04.012345");
754 /// assert_eq!(t.format("%-I:%M %p").to_string(), "11:56 PM");
755 /// ~~~~
756 ///
757 /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
758 ///
759 /// ~~~~
760 /// # use chrono::NaiveTime;
761 /// # let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
762 /// assert_eq!(format!("{}", t.format("%H:%M:%S")), "23:56:04");
763 /// assert_eq!(format!("{}", t.format("%H:%M:%S%.6f")), "23:56:04.012345");
764 /// assert_eq!(format!("{}", t.format("%-I:%M %p")), "11:56 PM");
765 /// ~~~~
766 #[inline]
767 pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
768 self.format_with_items(StrftimeItems::new(fmt))
769 }
770
771 /// Returns a triple of the hour, minute and second numbers.
772 fn hms(&self) -> (u32, u32, u32) {
773 let (mins, sec) = div_mod_floor(self.secs, 60);
774 let (hour, min) = div_mod_floor(mins, 60);
775 (hour, min, sec)
776 }
777 }
778
779 impl Timelike for NaiveTime {
780 /// Returns the hour number from 0 to 23.
781 ///
782 /// # Example
783 ///
784 /// ~~~~
785 /// use chrono::{NaiveTime, Timelike};
786 ///
787 /// assert_eq!(NaiveTime::from_hms(0, 0, 0).hour(), 0);
788 /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).hour(), 23);
789 /// ~~~~
790 #[inline]
791 fn hour(&self) -> u32 {
792 self.hms().0
793 }
794
795 /// Returns the minute number from 0 to 59.
796 ///
797 /// # Example
798 ///
799 /// ~~~~
800 /// use chrono::{NaiveTime, Timelike};
801 ///
802 /// assert_eq!(NaiveTime::from_hms(0, 0, 0).minute(), 0);
803 /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).minute(), 56);
804 /// ~~~~
805 #[inline]
806 fn minute(&self) -> u32 {
807 self.hms().1
808 }
809
810 /// Returns the second number from 0 to 59.
811 ///
812 /// # Example
813 ///
814 /// ~~~~
815 /// use chrono::{NaiveTime, Timelike};
816 ///
817 /// assert_eq!(NaiveTime::from_hms(0, 0, 0).second(), 0);
818 /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).second(), 4);
819 /// ~~~~
820 ///
821 /// This method never returns 60 even when it is a leap second.
822 /// ([Why?](#leap-second-handling))
823 /// Use the proper [formatting method](#method.format) to get a human-readable representation.
824 ///
825 /// ~~~~
826 /// # use chrono::{NaiveTime, Timelike};
827 /// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000);
828 /// assert_eq!(leap.second(), 59);
829 /// assert_eq!(leap.format("%H:%M:%S").to_string(), "23:59:60");
830 /// ~~~~
831 #[inline]
832 fn second(&self) -> u32 {
833 self.hms().2
834 }
835
836 /// Returns the number of nanoseconds since the whole non-leap second.
837 /// The range from 1,000,000,000 to 1,999,999,999 represents
838 /// the [leap second](#leap-second-handling).
839 ///
840 /// # Example
841 ///
842 /// ~~~~
843 /// use chrono::{NaiveTime, Timelike};
844 ///
845 /// assert_eq!(NaiveTime::from_hms(0, 0, 0).nanosecond(), 0);
846 /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).nanosecond(), 12_345_678);
847 /// ~~~~
848 ///
849 /// Leap seconds may have seemingly out-of-range return values.
850 /// You can reduce the range with `time.nanosecond() % 1_000_000_000`, or
851 /// use the proper [formatting method](#method.format) to get a human-readable representation.
852 ///
853 /// ~~~~
854 /// # use chrono::{NaiveTime, Timelike};
855 /// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000);
856 /// assert_eq!(leap.nanosecond(), 1_000_000_000);
857 /// assert_eq!(leap.format("%H:%M:%S%.9f").to_string(), "23:59:60.000000000");
858 /// ~~~~
859 #[inline]
860 fn nanosecond(&self) -> u32 {
861 self.frac
862 }
863
864 /// Makes a new `NaiveTime` with the hour number changed.
865 ///
866 /// Returns `None` when the resulting `NaiveTime` would be invalid.
867 ///
868 /// # Example
869 ///
870 /// ~~~~
871 /// use chrono::{NaiveTime, Timelike};
872 ///
873 /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
874 /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678)));
875 /// assert_eq!(dt.with_hour(24), None);
876 /// ~~~~
877 #[inline]
878 fn with_hour(&self, hour: u32) -> Option<NaiveTime> {
879 if hour >= 24 { return None; }
880 let secs = hour * 3600 + self.secs % 3600;
881 Some(NaiveTime { secs: secs, ..*self })
882 }
883
884 /// Makes a new `NaiveTime` with the minute number changed.
885 ///
886 /// Returns `None` when the resulting `NaiveTime` would be invalid.
887 ///
888 /// # Example
889 ///
890 /// ~~~~
891 /// use chrono::{NaiveTime, Timelike};
892 ///
893 /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
894 /// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano(23, 45, 4, 12_345_678)));
895 /// assert_eq!(dt.with_minute(60), None);
896 /// ~~~~
897 #[inline]
898 fn with_minute(&self, min: u32) -> Option<NaiveTime> {
899 if min >= 60 { return None; }
900 let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60;
901 Some(NaiveTime { secs: secs, ..*self })
902 }
903
904 /// Makes a new `NaiveTime` with the second number changed.
905 ///
906 /// Returns `None` when the resulting `NaiveTime` would be invalid.
907 /// As with the [`second`](#method.second) method,
908 /// the input range is restricted to 0 through 59.
909 ///
910 /// # Example
911 ///
912 /// ~~~~
913 /// use chrono::{NaiveTime, Timelike};
914 ///
915 /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
916 /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678)));
917 /// assert_eq!(dt.with_second(60), None);
918 /// ~~~~
919 #[inline]
920 fn with_second(&self, sec: u32) -> Option<NaiveTime> {
921 if sec >= 60 { return None; }
922 let secs = self.secs / 60 * 60 + sec;
923 Some(NaiveTime { secs: secs, ..*self })
924 }
925
926 /// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed.
927 ///
928 /// Returns `None` when the resulting `NaiveTime` would be invalid.
929 /// As with the [`nanosecond`](#method.nanosecond) method,
930 /// the input range can exceed 1,000,000,000 for leap seconds.
931 ///
932 /// # Example
933 ///
934 /// ~~~~
935 /// use chrono::{NaiveTime, Timelike};
936 ///
937 /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
938 /// assert_eq!(dt.with_nanosecond(333_333_333),
939 /// Some(NaiveTime::from_hms_nano(23, 56, 4, 333_333_333)));
940 /// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
941 /// ~~~~
942 ///
943 /// Leap seconds can theoretically follow *any* whole second.
944 /// The following would be a proper leap second at the time zone offset of UTC-00:03:57
945 /// (there are several historical examples comparable to this "non-sense" offset),
946 /// and therefore is allowed.
947 ///
948 /// ~~~~
949 /// # use chrono::{NaiveTime, Timelike};
950 /// # let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
951 /// assert_eq!(dt.with_nanosecond(1_333_333_333),
952 /// Some(NaiveTime::from_hms_nano(23, 56, 4, 1_333_333_333)));
953 /// ~~~~
954 #[inline]
955 fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> {
956 if nano >= 2_000_000_000 { return None; }
957 Some(NaiveTime { frac: nano, ..*self })
958 }
959
960 /// Returns the number of non-leap seconds past the last midnight.
961 ///
962 /// # Example
963 ///
964 /// ~~~~
965 /// use chrono::{NaiveTime, Timelike};
966 ///
967 /// assert_eq!(NaiveTime::from_hms(1, 2, 3).num_seconds_from_midnight(),
968 /// 3723);
969 /// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).num_seconds_from_midnight(),
970 /// 86164);
971 /// assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).num_seconds_from_midnight(),
972 /// 86399);
973 /// ~~~~
974 #[inline]
975 fn num_seconds_from_midnight(&self) -> u32 {
976 self.secs // do not repeat the calculation!
977 }
978 }
979
980 /// `NaiveTime` can be used as a key to the hash maps (in principle).
981 ///
982 /// Practically this also takes account of fractional seconds, so it is not recommended.
983 /// (For the obvious reason this also distinguishes leap seconds from non-leap seconds.)
984 #[cfg_attr(feature = "cargo-clippy", allow(derive_hash_xor_eq))]
985 impl hash::Hash for NaiveTime {
986 fn hash<H: hash::Hasher>(&self, state: &mut H) {
987 self.secs.hash(state);
988 self.frac.hash(state);
989 }
990 }
991
992 /// An addition of `Duration` to `NaiveTime` wraps around and never overflows or underflows.
993 /// In particular the addition ignores integral number of days.
994 ///
995 /// As a part of Chrono's [leap second handling](#leap-second-handling),
996 /// the addition assumes that **there is no leap second ever**,
997 /// except when the `NaiveTime` itself represents a leap second
998 /// in which case the assumption becomes that **there is exactly a single leap second ever**.
999 ///
1000 /// # Example
1001 ///
1002 /// ~~~~
1003 /// # extern crate chrono; extern crate time; fn main() {
1004 /// use chrono::NaiveTime;
1005 /// use time::Duration;
1006 ///
1007 /// let from_hmsm = NaiveTime::from_hms_milli;
1008 ///
1009 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::zero(), from_hmsm(3, 5, 7, 0));
1010 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(1), from_hmsm(3, 5, 8, 0));
1011 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-1), from_hmsm(3, 5, 6, 0));
1012 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(60 + 4), from_hmsm(3, 6, 11, 0));
1013 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(7*60*60 - 6*60), from_hmsm(9, 59, 7, 0));
1014 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::milliseconds(80), from_hmsm(3, 5, 7, 80));
1015 /// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(280), from_hmsm(3, 5, 8, 230));
1016 /// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(-980), from_hmsm(3, 5, 6, 970));
1017 /// # }
1018 /// ~~~~
1019 ///
1020 /// The addition wraps around.
1021 ///
1022 /// ~~~~
1023 /// # extern crate chrono; extern crate time; fn main() {
1024 /// # use chrono::NaiveTime;
1025 /// # use time::Duration;
1026 /// # let from_hmsm = NaiveTime::from_hms_milli;
1027 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(22*60*60), from_hmsm(1, 5, 7, 0));
1028 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-8*60*60), from_hmsm(19, 5, 7, 0));
1029 /// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::days(800), from_hmsm(3, 5, 7, 0));
1030 /// # }
1031 /// ~~~~
1032 ///
1033 /// Leap seconds are handled, but the addition assumes that it is the only leap second happened.
1034 ///
1035 /// ~~~~
1036 /// # extern crate chrono; extern crate time; fn main() {
1037 /// # use chrono::NaiveTime;
1038 /// # use time::Duration;
1039 /// # let from_hmsm = NaiveTime::from_hms_milli;
1040 /// let leap = from_hmsm(3, 5, 59, 1_300);
1041 /// assert_eq!(leap + Duration::zero(), from_hmsm(3, 5, 59, 1_300));
1042 /// assert_eq!(leap + Duration::milliseconds(-500), from_hmsm(3, 5, 59, 800));
1043 /// assert_eq!(leap + Duration::milliseconds(500), from_hmsm(3, 5, 59, 1_800));
1044 /// assert_eq!(leap + Duration::milliseconds(800), from_hmsm(3, 6, 0, 100));
1045 /// assert_eq!(leap + Duration::seconds(10), from_hmsm(3, 6, 9, 300));
1046 /// assert_eq!(leap + Duration::seconds(-10), from_hmsm(3, 5, 50, 300));
1047 /// assert_eq!(leap + Duration::days(1), from_hmsm(3, 5, 59, 300));
1048 /// # }
1049 /// ~~~~
1050 impl Add<OldDuration> for NaiveTime {
1051 type Output = NaiveTime;
1052
1053 #[inline]
1054 fn add(self, rhs: OldDuration) -> NaiveTime {
1055 self.overflowing_add_signed(rhs).0
1056 }
1057 }
1058
1059 impl AddAssign<OldDuration> for NaiveTime {
1060 #[inline]
1061 fn add_assign(&mut self, rhs: OldDuration) {
1062 *self = self.add(rhs);
1063 }
1064 }
1065
1066 /// A subtraction of `Duration` from `NaiveTime` wraps around and never overflows or underflows.
1067 /// In particular the addition ignores integral number of days.
1068 /// It is same to the addition with a negated `Duration`.
1069 ///
1070 /// As a part of Chrono's [leap second handling](#leap-second-handling),
1071 /// the addition assumes that **there is no leap second ever**,
1072 /// except when the `NaiveTime` itself represents a leap second
1073 /// in which case the assumption becomes that **there is exactly a single leap second ever**.
1074 ///
1075 /// # Example
1076 ///
1077 /// ~~~~
1078 /// # extern crate chrono; extern crate time; fn main() {
1079 /// use chrono::NaiveTime;
1080 /// use time::Duration;
1081 ///
1082 /// let from_hmsm = NaiveTime::from_hms_milli;
1083 ///
1084 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::zero(), from_hmsm(3, 5, 7, 0));
1085 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(1), from_hmsm(3, 5, 6, 0));
1086 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(60 + 5), from_hmsm(3, 4, 2, 0));
1087 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(2*60*60 + 6*60), from_hmsm(0, 59, 7, 0));
1088 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::milliseconds(80), from_hmsm(3, 5, 6, 920));
1089 /// assert_eq!(from_hmsm(3, 5, 7, 950) - Duration::milliseconds(280), from_hmsm(3, 5, 7, 670));
1090 /// # }
1091 /// ~~~~
1092 ///
1093 /// The subtraction wraps around.
1094 ///
1095 /// ~~~~
1096 /// # extern crate chrono; extern crate time; fn main() {
1097 /// # use chrono::NaiveTime;
1098 /// # use time::Duration;
1099 /// # let from_hmsm = NaiveTime::from_hms_milli;
1100 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(8*60*60), from_hmsm(19, 5, 7, 0));
1101 /// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::days(800), from_hmsm(3, 5, 7, 0));
1102 /// # }
1103 /// ~~~~
1104 ///
1105 /// Leap seconds are handled, but the subtraction assumes that it is the only leap second happened.
1106 ///
1107 /// ~~~~
1108 /// # extern crate chrono; extern crate time; fn main() {
1109 /// # use chrono::NaiveTime;
1110 /// # use time::Duration;
1111 /// # let from_hmsm = NaiveTime::from_hms_milli;
1112 /// let leap = from_hmsm(3, 5, 59, 1_300);
1113 /// assert_eq!(leap - Duration::zero(), from_hmsm(3, 5, 59, 1_300));
1114 /// assert_eq!(leap - Duration::milliseconds(200), from_hmsm(3, 5, 59, 1_100));
1115 /// assert_eq!(leap - Duration::milliseconds(500), from_hmsm(3, 5, 59, 800));
1116 /// assert_eq!(leap - Duration::seconds(60), from_hmsm(3, 5, 0, 300));
1117 /// assert_eq!(leap - Duration::days(1), from_hmsm(3, 6, 0, 300));
1118 /// # }
1119 /// ~~~~
1120 impl Sub<OldDuration> for NaiveTime {
1121 type Output = NaiveTime;
1122
1123 #[inline]
1124 fn sub(self, rhs: OldDuration) -> NaiveTime {
1125 self.overflowing_sub_signed(rhs).0
1126 }
1127 }
1128
1129 impl SubAssign<OldDuration> for NaiveTime {
1130 #[inline]
1131 fn sub_assign(&mut self, rhs: OldDuration) {
1132 *self = self.sub(rhs);
1133 }
1134 }
1135
1136 /// Subtracts another `NaiveTime` from the current time.
1137 /// Returns a `Duration` within +/- 1 day.
1138 /// This does not overflow or underflow at all.
1139 ///
1140 /// As a part of Chrono's [leap second handling](#leap-second-handling),
1141 /// the subtraction assumes that **there is no leap second ever**,
1142 /// except when any of the `NaiveTime`s themselves represents a leap second
1143 /// in which case the assumption becomes that
1144 /// **there are exactly one (or two) leap second(s) ever**.
1145 ///
1146 /// The implementation is a wrapper around
1147 /// [`NaiveTime::signed_duration_since`](#method.signed_duration_since).
1148 ///
1149 /// # Example
1150 ///
1151 /// ~~~~
1152 /// # extern crate chrono; extern crate time; fn main() {
1153 /// use chrono::NaiveTime;
1154 /// use time::Duration;
1155 ///
1156 /// let from_hmsm = NaiveTime::from_hms_milli;
1157 ///
1158 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 900), Duration::zero());
1159 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 875), Duration::milliseconds(25));
1160 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 6, 925), Duration::milliseconds(975));
1161 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 0, 900), Duration::seconds(7));
1162 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 0, 7, 900), Duration::seconds(5 * 60));
1163 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(0, 5, 7, 900), Duration::seconds(3 * 3600));
1164 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(4, 5, 7, 900), Duration::seconds(-3600));
1165 /// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(2, 4, 6, 800),
1166 /// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100));
1167 /// # }
1168 /// ~~~~
1169 ///
1170 /// Leap seconds are handled, but the subtraction assumes that
1171 /// there were no other leap seconds happened.
1172 ///
1173 /// ~~~~
1174 /// # extern crate chrono; extern crate time; fn main() {
1175 /// # use chrono::NaiveTime;
1176 /// # use time::Duration;
1177 /// # let from_hmsm = NaiveTime::from_hms_milli;
1178 /// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 59, 0), Duration::seconds(1));
1179 /// assert_eq!(from_hmsm(3, 0, 59, 1_500) - from_hmsm(3, 0, 59, 0),
1180 /// Duration::milliseconds(1500));
1181 /// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 0, 0), Duration::seconds(60));
1182 /// assert_eq!(from_hmsm(3, 0, 0, 0) - from_hmsm(2, 59, 59, 1_000), Duration::seconds(1));
1183 /// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(2, 59, 59, 1_000),
1184 /// Duration::seconds(61));
1185 /// # }
1186 /// ~~~~
1187 impl Sub<NaiveTime> for NaiveTime {
1188 type Output = OldDuration;
1189
1190 #[inline]
1191 fn sub(self, rhs: NaiveTime) -> OldDuration {
1192 self.signed_duration_since(rhs)
1193 }
1194 }
1195
1196 /// The `Debug` output of the naive time `t` is same to
1197 /// [`t.format("%H:%M:%S%.f")`](../format/strftime/index.html).
1198 ///
1199 /// The string printed can be readily parsed via the `parse` method on `str`.
1200 ///
1201 /// It should be noted that, for leap seconds not on the minute boundary,
1202 /// it may print a representation not distinguishable from non-leap seconds.
1203 /// This doesn't matter in practice, since such leap seconds never happened.
1204 /// (By the time of the first leap second on 1972-06-30,
1205 /// every time zone offset around the world has standardized to the 5-minute alignment.)
1206 ///
1207 /// # Example
1208 ///
1209 /// ~~~~
1210 /// use chrono::NaiveTime;
1211 ///
1212 /// assert_eq!(format!("{:?}", NaiveTime::from_hms(23, 56, 4)), "23:56:04");
1213 /// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012");
1214 /// assert_eq!(format!("{:?}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234");
1215 /// assert_eq!(format!("{:?}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456");
1216 /// ~~~~
1217 ///
1218 /// Leap seconds may also be used.
1219 ///
1220 /// ~~~~
1221 /// # use chrono::NaiveTime;
1222 /// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500");
1223 /// ~~~~
1224 impl fmt::Debug for NaiveTime {
1225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1226 let (hour, min, sec) = self.hms();
1227 let (sec, nano) = if self.frac >= 1_000_000_000 {
1228 (sec + 1, self.frac - 1_000_000_000)
1229 } else {
1230 (sec, self.frac)
1231 };
1232
1233 try!(write!(f, "{:02}:{:02}:{:02}", hour, min, sec));
1234 if nano == 0 {
1235 Ok(())
1236 } else if nano % 1_000_000 == 0 {
1237 write!(f, ".{:03}", nano / 1_000_000)
1238 } else if nano % 1_000 == 0 {
1239 write!(f, ".{:06}", nano / 1_000)
1240 } else {
1241 write!(f, ".{:09}", nano)
1242 }
1243 }
1244 }
1245
1246 /// The `Display` output of the naive time `t` is same to
1247 /// [`t.format("%H:%M:%S%.f")`](../format/strftime/index.html).
1248 ///
1249 /// The string printed can be readily parsed via the `parse` method on `str`.
1250 ///
1251 /// It should be noted that, for leap seconds not on the minute boundary,
1252 /// it may print a representation not distinguishable from non-leap seconds.
1253 /// This doesn't matter in practice, since such leap seconds never happened.
1254 /// (By the time of the first leap second on 1972-06-30,
1255 /// every time zone offset around the world has standardized to the 5-minute alignment.)
1256 ///
1257 /// # Example
1258 ///
1259 /// ~~~~
1260 /// use chrono::NaiveTime;
1261 ///
1262 /// assert_eq!(format!("{}", NaiveTime::from_hms(23, 56, 4)), "23:56:04");
1263 /// assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012");
1264 /// assert_eq!(format!("{}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234");
1265 /// assert_eq!(format!("{}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456");
1266 /// ~~~~
1267 ///
1268 /// Leap seconds may also be used.
1269 ///
1270 /// ~~~~
1271 /// # use chrono::NaiveTime;
1272 /// assert_eq!(format!("{}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500");
1273 /// ~~~~
1274 impl fmt::Display for NaiveTime {
1275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) }
1276 }
1277
1278 /// Parsing a `str` into a `NaiveTime` uses the same format,
1279 /// [`%H:%M:%S%.f`](../format/strftime/index.html), as in `Debug` and `Display`.
1280 ///
1281 /// # Example
1282 ///
1283 /// ~~~~
1284 /// use chrono::NaiveTime;
1285 ///
1286 /// let t = NaiveTime::from_hms(23, 56, 4);
1287 /// assert_eq!("23:56:04".parse::<NaiveTime>(), Ok(t));
1288 ///
1289 /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
1290 /// assert_eq!("23:56:4.012345678".parse::<NaiveTime>(), Ok(t));
1291 ///
1292 /// let t = NaiveTime::from_hms_nano(23, 59, 59, 1_234_567_890); // leap second
1293 /// assert_eq!("23:59:60.23456789".parse::<NaiveTime>(), Ok(t));
1294 ///
1295 /// assert!("foo".parse::<NaiveTime>().is_err());
1296 /// ~~~~
1297 impl str::FromStr for NaiveTime {
1298 type Err = ParseError;
1299
1300 fn from_str(s: &str) -> ParseResult<NaiveTime> {
1301 const ITEMS: &'static [Item<'static>] = &[
1302 Item::Space(""), Item::Numeric(Numeric::Hour, Pad::Zero),
1303 Item::Space(""), Item::Literal(":"),
1304 Item::Space(""), Item::Numeric(Numeric::Minute, Pad::Zero),
1305 Item::Space(""), Item::Literal(":"),
1306 Item::Space(""), Item::Numeric(Numeric::Second, Pad::Zero),
1307 Item::Fixed(Fixed::Nanosecond), Item::Space(""),
1308 ];
1309
1310 let mut parsed = Parsed::new();
1311 try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
1312 parsed.to_naive_time()
1313 }
1314 }
1315
1316 #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1317 fn test_encodable_json<F, E>(to_string: F)
1318 where F: Fn(&NaiveTime) -> Result<String, E>, E: ::std::fmt::Debug
1319 {
1320 assert_eq!(to_string(&NaiveTime::from_hms(0, 0, 0)).ok(),
1321 Some(r#""00:00:00""#.into()));
1322 assert_eq!(to_string(&NaiveTime::from_hms_milli(0, 0, 0, 950)).ok(),
1323 Some(r#""00:00:00.950""#.into()));
1324 assert_eq!(to_string(&NaiveTime::from_hms_milli(0, 0, 59, 1_000)).ok(),
1325 Some(r#""00:00:60""#.into()));
1326 assert_eq!(to_string(&NaiveTime::from_hms(0, 1, 2)).ok(),
1327 Some(r#""00:01:02""#.into()));
1328 assert_eq!(to_string(&NaiveTime::from_hms_nano(3, 5, 7, 98765432)).ok(),
1329 Some(r#""03:05:07.098765432""#.into()));
1330 assert_eq!(to_string(&NaiveTime::from_hms(7, 8, 9)).ok(),
1331 Some(r#""07:08:09""#.into()));
1332 assert_eq!(to_string(&NaiveTime::from_hms_micro(12, 34, 56, 789)).ok(),
1333 Some(r#""12:34:56.000789""#.into()));
1334 assert_eq!(to_string(&NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)).ok(),
1335 Some(r#""23:59:60.999999999""#.into()));
1336 }
1337
1338 #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1339 fn test_decodable_json<F, E>(from_str: F)
1340 where F: Fn(&str) -> Result<NaiveTime, E>, E: ::std::fmt::Debug
1341 {
1342 assert_eq!(from_str(r#""00:00:00""#).ok(),
1343 Some(NaiveTime::from_hms(0, 0, 0)));
1344 assert_eq!(from_str(r#""0:0:0""#).ok(),
1345 Some(NaiveTime::from_hms(0, 0, 0)));
1346 assert_eq!(from_str(r#""00:00:00.950""#).ok(),
1347 Some(NaiveTime::from_hms_milli(0, 0, 0, 950)));
1348 assert_eq!(from_str(r#""0:0:0.95""#).ok(),
1349 Some(NaiveTime::from_hms_milli(0, 0, 0, 950)));
1350 assert_eq!(from_str(r#""00:00:60""#).ok(),
1351 Some(NaiveTime::from_hms_milli(0, 0, 59, 1_000)));
1352 assert_eq!(from_str(r#""00:01:02""#).ok(),
1353 Some(NaiveTime::from_hms(0, 1, 2)));
1354 assert_eq!(from_str(r#""03:05:07.098765432""#).ok(),
1355 Some(NaiveTime::from_hms_nano(3, 5, 7, 98765432)));
1356 assert_eq!(from_str(r#""07:08:09""#).ok(),
1357 Some(NaiveTime::from_hms(7, 8, 9)));
1358 assert_eq!(from_str(r#""12:34:56.000789""#).ok(),
1359 Some(NaiveTime::from_hms_micro(12, 34, 56, 789)));
1360 assert_eq!(from_str(r#""23:59:60.999999999""#).ok(),
1361 Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)));
1362 assert_eq!(from_str(r#""23:59:60.9999999999997""#).ok(), // excess digits are ignored
1363 Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)));
1364
1365 // bad formats
1366 assert!(from_str(r#""""#).is_err());
1367 assert!(from_str(r#""000000""#).is_err());
1368 assert!(from_str(r#""00:00:61""#).is_err());
1369 assert!(from_str(r#""00:60:00""#).is_err());
1370 assert!(from_str(r#""24:00:00""#).is_err());
1371 assert!(from_str(r#""23:59:59,1""#).is_err());
1372 assert!(from_str(r#""012:34:56""#).is_err());
1373 assert!(from_str(r#""hh:mm:ss""#).is_err());
1374 assert!(from_str(r#"0"#).is_err());
1375 assert!(from_str(r#"86399"#).is_err());
1376 assert!(from_str(r#"{}"#).is_err());
1377 // pre-0.3.0 rustc-serialize format is now invalid
1378 assert!(from_str(r#"{"secs":0,"frac":0}"#).is_err());
1379 assert!(from_str(r#"null"#).is_err());
1380 }
1381
1382 #[cfg(feature = "rustc-serialize")]
1383 mod rustc_serialize {
1384 use super::NaiveTime;
1385 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
1386
1387 impl Encodable for NaiveTime {
1388 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1389 format!("{:?}", self).encode(s)
1390 }
1391 }
1392
1393 impl Decodable for NaiveTime {
1394 fn decode<D: Decoder>(d: &mut D) -> Result<NaiveTime, D::Error> {
1395 d.read_str()?.parse().map_err(|_| d.error("invalid time"))
1396 }
1397 }
1398
1399 #[cfg(test)] use rustc_serialize::json;
1400
1401 #[test]
1402 fn test_encodable() {
1403 super::test_encodable_json(json::encode);
1404 }
1405
1406 #[test]
1407 fn test_decodable() {
1408 super::test_decodable_json(json::decode);
1409 }
1410 }
1411
1412 #[cfg(feature = "serde")]
1413 mod serde {
1414 use std::fmt;
1415 use super::NaiveTime;
1416 use serdelib::{ser, de};
1417
1418 // TODO not very optimized for space (binary formats would want something better)
1419 // TODO round-trip for general leap seconds (not just those with second = 60)
1420
1421 impl ser::Serialize for NaiveTime {
1422 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1423 where S: ser::Serializer
1424 {
1425 serializer.collect_str(&self)
1426 }
1427 }
1428
1429 struct NaiveTimeVisitor;
1430
1431 impl<'de> de::Visitor<'de> for NaiveTimeVisitor {
1432 type Value = NaiveTime;
1433
1434 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
1435 {
1436 write!(formatter, "a formatted time string")
1437 }
1438
1439 fn visit_str<E>(self, value: &str) -> Result<NaiveTime, E>
1440 where E: de::Error
1441 {
1442 value.parse().map_err(|err| E::custom(format!("{}", err)))
1443 }
1444 }
1445
1446 impl<'de> de::Deserialize<'de> for NaiveTime {
1447 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1448 where D: de::Deserializer<'de>
1449 {
1450 deserializer.deserialize_str(NaiveTimeVisitor)
1451 }
1452 }
1453
1454 #[cfg(test)] extern crate serde_json;
1455 #[cfg(test)] extern crate bincode;
1456
1457 #[test]
1458 fn test_serde_serialize() {
1459 super::test_encodable_json(self::serde_json::to_string);
1460 }
1461
1462 #[test]
1463 fn test_serde_deserialize() {
1464 super::test_decodable_json(|input| self::serde_json::from_str(&input));
1465 }
1466
1467 #[test]
1468 fn test_serde_bincode() {
1469 // Bincode is relevant to test separately from JSON because
1470 // it is not self-describing.
1471 use self::bincode::{Infinite, serialize, deserialize};
1472
1473 let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432);
1474 let encoded = serialize(&t, Infinite).unwrap();
1475 let decoded: NaiveTime = deserialize(&encoded).unwrap();
1476 assert_eq!(t, decoded);
1477 }
1478 }
1479
1480 #[cfg(test)]
1481 mod tests {
1482 use super::NaiveTime;
1483 use Timelike;
1484 use std::u32;
1485 use oldtime::Duration;
1486
1487 #[test]
1488 fn test_time_from_hms_milli() {
1489 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 0),
1490 Some(NaiveTime::from_hms_nano(3, 5, 7, 0)));
1491 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 777),
1492 Some(NaiveTime::from_hms_nano(3, 5, 7, 777_000_000)));
1493 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 1_999),
1494 Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_000_000)));
1495 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 2_000), None);
1496 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 5_000), None); // overflow check
1497 assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, u32::MAX), None);
1498 }
1499
1500 #[test]
1501 fn test_time_from_hms_micro() {
1502 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 0),
1503 Some(NaiveTime::from_hms_nano(3, 5, 7, 0)));
1504 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 333),
1505 Some(NaiveTime::from_hms_nano(3, 5, 7, 333_000)));
1506 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 777_777),
1507 Some(NaiveTime::from_hms_nano(3, 5, 7, 777_777_000)));
1508 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 1_999_999),
1509 Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_999_000)));
1510 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 2_000_000), None);
1511 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 5_000_000), None); // overflow check
1512 assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, u32::MAX), None);
1513 }
1514
1515 #[test]
1516 fn test_time_hms() {
1517 assert_eq!(NaiveTime::from_hms(3, 5, 7).hour(), 3);
1518 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(0),
1519 Some(NaiveTime::from_hms(0, 5, 7)));
1520 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(23),
1521 Some(NaiveTime::from_hms(23, 5, 7)));
1522 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(24), None);
1523 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(u32::MAX), None);
1524
1525 assert_eq!(NaiveTime::from_hms(3, 5, 7).minute(), 5);
1526 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(0),
1527 Some(NaiveTime::from_hms(3, 0, 7)));
1528 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(59),
1529 Some(NaiveTime::from_hms(3, 59, 7)));
1530 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(60), None);
1531 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(u32::MAX), None);
1532
1533 assert_eq!(NaiveTime::from_hms(3, 5, 7).second(), 7);
1534 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(0),
1535 Some(NaiveTime::from_hms(3, 5, 0)));
1536 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(59),
1537 Some(NaiveTime::from_hms(3, 5, 59)));
1538 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(60), None);
1539 assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(u32::MAX), None);
1540 }
1541
1542 #[test]
1543 fn test_time_add() {
1544 macro_rules! check {
1545 ($lhs:expr, $rhs:expr, $sum:expr) => ({
1546 assert_eq!($lhs + $rhs, $sum);
1547 //assert_eq!($rhs + $lhs, $sum);
1548 })
1549 }
1550
1551 let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
1552
1553 check!(hmsm(3, 5, 7, 900), Duration::zero(), hmsm(3, 5, 7, 900));
1554 check!(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0));
1555 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-1800), hmsm(3, 5, 6, 500));
1556 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-800), hmsm(3, 5, 7, 500));
1557 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-100), hmsm(3, 5, 7, 1_200));
1558 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(100), hmsm(3, 5, 7, 1_400));
1559 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100));
1560 check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(1800), hmsm(3, 5, 9, 100));
1561 check!(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap
1562 check!(hmsm(3, 5, 7, 900), Duration::seconds(-86399), hmsm(3, 5, 8, 900));
1563 check!(hmsm(3, 5, 7, 900), Duration::days(12345), hmsm(3, 5, 7, 900));
1564 check!(hmsm(3, 5, 7, 1_300), Duration::days(1), hmsm(3, 5, 7, 300));
1565 check!(hmsm(3, 5, 7, 1_300), Duration::days(-1), hmsm(3, 5, 8, 300));
1566
1567 // regression tests for #37
1568 check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-990), hmsm(23, 59, 59, 10));
1569 check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-9990), hmsm(23, 59, 50, 10));
1570 }
1571
1572 #[test]
1573 fn test_time_overflowing_add() {
1574 let hmsm = NaiveTime::from_hms_milli;
1575
1576 assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(11)),
1577 (hmsm(14, 4, 5, 678), 0));
1578 assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(23)),
1579 (hmsm(2, 4, 5, 678), 86_400));
1580 assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(-7)),
1581 (hmsm(20, 4, 5, 678), -86_400));
1582
1583 // overflowing_add_signed with leap seconds may be counter-intuitive
1584 assert_eq!(hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(1)),
1585 (hmsm(3, 4, 5, 678), 86_400));
1586 assert_eq!(hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(-1)),
1587 (hmsm(3, 4, 6, 678), -86_400));
1588 }
1589
1590 #[test]
1591 fn test_time_addassignment() {
1592 let hms = NaiveTime::from_hms;
1593 let mut time = hms(12, 12, 12);
1594 time += Duration::hours(10);
1595 assert_eq!(time, hms(22, 12, 12));
1596 time += Duration::hours(10);
1597 assert_eq!(time, hms(8, 12, 12));
1598 }
1599
1600 #[test]
1601 fn test_time_subassignment() {
1602 let hms = NaiveTime::from_hms;
1603 let mut time = hms(12, 12, 12);
1604 time -= Duration::hours(10);
1605 assert_eq!(time, hms(2, 12, 12));
1606 time -= Duration::hours(10);
1607 assert_eq!(time, hms(16, 12, 12));
1608 }
1609
1610 #[test]
1611 fn test_time_sub() {
1612 macro_rules! check {
1613 ($lhs:expr, $rhs:expr, $diff:expr) => ({
1614 // `time1 - time2 = duration` is equivalent to `time2 - time1 = -duration`
1615 assert_eq!($lhs.signed_duration_since($rhs), $diff);
1616 assert_eq!($rhs.signed_duration_since($lhs), -$diff);
1617 })
1618 }
1619
1620 let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
1621
1622 check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Duration::zero());
1623 check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300));
1624 check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1));
1625 check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 300),
1626 Duration::seconds(3600 + 60) + Duration::milliseconds(900));
1627
1628 // treats the leap second as if it coincides with the prior non-leap second,
1629 // as required by `time1 - time2 = duration` and `time2 - time1 = -duration` equivalence.
1630 check!(hmsm(3, 5, 7, 200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(400));
1631 check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(1400));
1632 check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 800), Duration::milliseconds(1400));
1633
1634 // additional equality: `time1 + duration = time2` is equivalent to
1635 // `time2 - time1 = duration` IF AND ONLY IF `time2` represents a non-leap second.
1636 assert_eq!(hmsm(3, 5, 6, 800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200));
1637 assert_eq!(hmsm(3, 5, 6, 1_800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200));
1638 }
1639
1640 #[test]
1641 fn test_time_fmt() {
1642 assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 999)), "23:59:59.999");
1643 assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_000)), "23:59:60");
1644 assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_001)), "23:59:60.001");
1645 assert_eq!(format!("{}", NaiveTime::from_hms_micro(0, 0, 0, 43210)), "00:00:00.043210");
1646 assert_eq!(format!("{}", NaiveTime::from_hms_nano(0, 0, 0, 6543210)), "00:00:00.006543210");
1647
1648 // the format specifier should have no effect on `NaiveTime`
1649 assert_eq!(format!("{:30}", NaiveTime::from_hms_milli(3, 5, 7, 9)), "03:05:07.009");
1650 }
1651
1652 #[test]
1653 fn test_date_from_str() {
1654 // valid cases
1655 let valid = [
1656 "0:0:0",
1657 "0:0:0.0000000",
1658 "0:0:0.0000003",
1659 " 4 : 3 : 2.1 ",
1660 " 09:08:07 ",
1661 " 9:8:07 ",
1662 "23:59:60.373929310237",
1663 ];
1664 for &s in &valid {
1665 let d = match s.parse::<NaiveTime>() {
1666 Ok(d) => d,
1667 Err(e) => panic!("parsing `{}` has failed: {}", s, e)
1668 };
1669 let s_ = format!("{:?}", d);
1670 // `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same
1671 let d_ = match s_.parse::<NaiveTime>() {
1672 Ok(d) => d,
1673 Err(e) => panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}",
1674 s, d, e)
1675 };
1676 assert!(d == d_, "`{}` is parsed into `{:?}`, but reparsed result \
1677 `{:?}` does not match", s, d, d_);
1678 }
1679
1680 // some invalid cases
1681 // since `ParseErrorKind` is private, all we can do is to check if there was an error
1682 assert!("".parse::<NaiveTime>().is_err());
1683 assert!("x".parse::<NaiveTime>().is_err());
1684 assert!("15".parse::<NaiveTime>().is_err());
1685 assert!("15:8".parse::<NaiveTime>().is_err());
1686 assert!("15:8:x".parse::<NaiveTime>().is_err());
1687 assert!("15:8:9x".parse::<NaiveTime>().is_err());
1688 assert!("23:59:61".parse::<NaiveTime>().is_err());
1689 assert!("12:34:56.x".parse::<NaiveTime>().is_err());
1690 assert!("12:34:56. 0".parse::<NaiveTime>().is_err());
1691 }
1692
1693 #[test]
1694 fn test_time_parse_from_str() {
1695 let hms = |h,m,s| NaiveTime::from_hms(h,m,s);
1696 assert_eq!(NaiveTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
1697 Ok(hms(12, 34, 56))); // ignore date and offset
1698 assert_eq!(NaiveTime::parse_from_str("PM 12:59", "%P %H:%M"),
1699 Ok(hms(12, 59, 0)));
1700 assert!(NaiveTime::parse_from_str("12:3456", "%H:%M:%S").is_err());
1701 }
1702
1703 #[test]
1704 fn test_time_format() {
1705 let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432);
1706 assert_eq!(t.format("%H,%k,%I,%l,%P,%p").to_string(), "03, 3,03, 3,am,AM");
1707 assert_eq!(t.format("%M").to_string(), "05");
1708 assert_eq!(t.format("%S,%f,%.f").to_string(), "07,098765432,.098765432");
1709 assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".098,.098765,.098765432");
1710 assert_eq!(t.format("%R").to_string(), "03:05");
1711 assert_eq!(t.format("%T,%X").to_string(), "03:05:07,03:05:07");
1712 assert_eq!(t.format("%r").to_string(), "03:05:07 AM");
1713 assert_eq!(t.format("%t%n%%%n%t").to_string(), "\t\n%\n\t");
1714
1715 let t = NaiveTime::from_hms_micro(3, 5, 7, 432100);
1716 assert_eq!(t.format("%S,%f,%.f").to_string(), "07,432100000,.432100");
1717 assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".432,.432100,.432100000");
1718
1719 let t = NaiveTime::from_hms_milli(3, 5, 7, 210);
1720 assert_eq!(t.format("%S,%f,%.f").to_string(), "07,210000000,.210");
1721 assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".210,.210000,.210000000");
1722
1723 let t = NaiveTime::from_hms(3, 5, 7);
1724 assert_eq!(t.format("%S,%f,%.f").to_string(), "07,000000000,");
1725 assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".000,.000000,.000000000");
1726
1727 // corner cases
1728 assert_eq!(NaiveTime::from_hms(13, 57, 9).format("%r").to_string(), "01:57:09 PM");
1729 assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).format("%X").to_string(),
1730 "23:59:60");
1731 }
1732 }
1733