2017-02-05 21:15:57 +00:00
|
|
|
// This is a part of Chrono.
|
2014-07-29 07:14:46 +00:00
|
|
|
// See README.md and LICENSE.txt for details.
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
//! ISO 8601 time without timezone.
|
2014-07-29 07:14:46 +00:00
|
|
|
|
2019-09-07 10:12:49 +00:00
|
|
|
use core::{str, fmt, hash};
|
|
|
|
use core::ops::{Add, Sub, AddAssign, SubAssign};
|
2017-02-05 23:17:01 +00:00
|
|
|
use oldtime::Duration as OldDuration;
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
use Timelike;
|
2014-11-24 05:49:13 +00:00
|
|
|
use div::div_mod_floor;
|
2015-02-18 14:27:12 +00:00
|
|
|
use format::{Item, Numeric, Pad, Fixed};
|
2019-09-09 11:41:44 +00:00
|
|
|
use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems};
|
|
|
|
#[cfg(any(feature = "alloc", feature = "std", test))]
|
|
|
|
use format::DelayedFormat;
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
/// ISO 8601 time without timezone.
|
|
|
|
/// Allows for the nanosecond precision and optional leap second representation.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
2017-06-21 05:03:49 +00:00
|
|
|
/// # Leap Second Handling
|
|
|
|
///
|
|
|
|
/// Since 1960s, the manmade atomic clock has been so accurate that
|
|
|
|
/// it is much more accurate than Earth's own motion.
|
|
|
|
/// It became desirable to define the civil time in terms of the atomic clock,
|
|
|
|
/// but that risks the desynchronization of the civil time from Earth.
|
|
|
|
/// To account for this, the designers of the Coordinated Universal Time (UTC)
|
|
|
|
/// made that the UTC should be kept within 0.9 seconds of the observed Earth-bound time.
|
|
|
|
/// When the mean solar day is longer than the ideal (86,400 seconds),
|
|
|
|
/// the error slowly accumulates and it is necessary to add a **leap second**
|
|
|
|
/// to slow the UTC down a bit.
|
|
|
|
/// (We may also remove a second to speed the UTC up a bit, but it never happened.)
|
|
|
|
/// The leap second, if any, follows 23:59:59 of June 30 or December 31 in the UTC.
|
|
|
|
///
|
|
|
|
/// Fast forward to the 21st century,
|
|
|
|
/// we have seen 26 leap seconds from January 1972 to December 2015.
|
|
|
|
/// Yes, 26 seconds. Probably you can read this paragraph within 26 seconds.
|
|
|
|
/// But those 26 seconds, and possibly more in the future, are never predictable,
|
|
|
|
/// and whether to add a leap second or not is known only before 6 months.
|
|
|
|
/// Internet-based clocks (via NTP) do account for known leap seconds,
|
|
|
|
/// but the system API normally doesn't (and often can't, with no network connection)
|
|
|
|
/// and there is no reliable way to retrieve leap second information.
|
|
|
|
///
|
|
|
|
/// Chrono does not try to accurately implement leap seconds; it is impossible.
|
|
|
|
/// Rather, **it allows for leap seconds but behaves as if there are *no other* leap seconds.**
|
|
|
|
/// Various operations will ignore any possible leap second(s)
|
|
|
|
/// except when any of the operands were actually leap seconds.
|
|
|
|
///
|
|
|
|
/// If you cannot tolerate this behavior,
|
|
|
|
/// you must use a separate `TimeZone` for the International Atomic Time (TAI).
|
|
|
|
/// TAI is like UTC but has no leap seconds, and thus slightly differs from UTC.
|
2017-06-21 17:54:26 +00:00
|
|
|
/// Chrono does not yet provide such implementation, but it is planned.
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
|
|
|
/// ## Representing Leap Seconds
|
|
|
|
///
|
|
|
|
/// The leap second is indicated via fractional seconds more than 1 second.
|
|
|
|
/// This makes possible to treat a leap second as the prior non-leap second
|
|
|
|
/// if you don't care about sub-second accuracy.
|
|
|
|
/// You should use the proper formatting to get the raw leap second.
|
|
|
|
///
|
|
|
|
/// All methods accepting fractional seconds will accept such values.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-06-21 15:33:17 +00:00
|
|
|
/// use chrono::{NaiveDate, NaiveTime, Utc, TimeZone};
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_milli(8, 59, 59, 1_000);
|
|
|
|
///
|
|
|
|
/// let dt1 = NaiveDate::from_ymd(2015, 7, 1).and_hms_micro(8, 59, 59, 1_000_000);
|
|
|
|
///
|
2017-06-21 15:33:17 +00:00
|
|
|
/// let dt2 = Utc.ymd(2015, 6, 30).and_hms_nano(23, 59, 59, 1_000_000_000);
|
2017-06-21 05:03:49 +00:00
|
|
|
/// # let _ = (t, dt1, dt2);
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Note that the leap second can happen anytime given an appropriate time zone;
|
|
|
|
/// 2015-07-01 01:23:60 would be a proper leap second if UTC+01:24 had existed.
|
|
|
|
/// Practically speaking, though, by the time of the first leap second on 1972-06-30,
|
|
|
|
/// every time zone offset around the world has standardized to the 5-minute alignment.
|
|
|
|
///
|
|
|
|
/// ## Date And Time Arithmetics
|
|
|
|
///
|
|
|
|
/// As a concrete example, let's assume that `03:00:60` and `04:00:60` are leap seconds.
|
2017-06-21 15:40:48 +00:00
|
|
|
/// In reality, of course, leap seconds are separated by at least 6 months.
|
|
|
|
/// We will also use some intuitive concise notations for the explanation.
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// `Time + Duration`
|
|
|
|
/// (short for [`NaiveTime::overflowing_add_signed`](#method.overflowing_add_signed)):
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
|
|
|
/// - `03:00:00 + 1s = 03:00:01`.
|
|
|
|
/// - `03:00:59 + 60s = 03:02:00`.
|
|
|
|
/// - `03:00:59 + 1s = 03:01:00`.
|
|
|
|
/// - `03:00:60 + 1s = 03:01:00`.
|
|
|
|
/// Note that the sum is identical to the previous.
|
|
|
|
/// - `03:00:60 + 60s = 03:01:59`.
|
|
|
|
/// - `03:00:60 + 61s = 03:02:00`.
|
|
|
|
/// - `03:00:60.1 + 0.8s = 03:00:60.9`.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// `Time - Duration`
|
|
|
|
/// (short for [`NaiveTime::overflowing_sub_signed`](#method.overflowing_sub_signed)):
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
|
|
|
/// - `03:00:00 - 1s = 02:59:59`.
|
|
|
|
/// - `03:01:00 - 1s = 03:00:59`.
|
|
|
|
/// - `03:01:00 - 60s = 03:00:00`.
|
|
|
|
/// - `03:00:60 - 60s = 03:00:00`.
|
|
|
|
/// Note that the result is identical to the previous.
|
|
|
|
/// - `03:00:60.7 - 0.4s = 03:00:60.3`.
|
|
|
|
/// - `03:00:60.7 - 0.9s = 03:00:59.8`.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// `Time - Time`
|
|
|
|
/// (short for [`NaiveTime::signed_duration_since`](#method.signed_duration_since)):
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
|
|
|
/// - `04:00:00 - 03:00:00 = 3600s`.
|
|
|
|
/// - `03:01:00 - 03:00:00 = 60s`.
|
|
|
|
/// - `03:00:60 - 03:00:00 = 60s`.
|
|
|
|
/// Note that the difference is identical to the previous.
|
|
|
|
/// - `03:00:60.6 - 03:00:59.4 = 1.2s`.
|
|
|
|
/// - `03:01:00 - 03:00:59.8 = 0.2s`.
|
|
|
|
/// - `03:01:00 - 03:00:60.5 = 0.5s`.
|
|
|
|
/// Note that the difference is larger than the previous,
|
|
|
|
/// even though the leap second clearly follows the previous whole second.
|
|
|
|
/// - `04:00:60.9 - 03:00:60.1 =
|
|
|
|
/// (04:00:60.9 - 04:00:00) + (04:00:00 - 03:01:00) + (03:01:00 - 03:00:60.1) =
|
|
|
|
/// 60.9s + 3540s + 0.9s = 3601.8s`.
|
|
|
|
///
|
|
|
|
/// In general,
|
|
|
|
///
|
|
|
|
/// - `Time + Duration` unconditionally equals to `Duration + Time`.
|
|
|
|
///
|
|
|
|
/// - `Time - Duration` unconditionally equals to `Time + (-Duration)`.
|
|
|
|
///
|
|
|
|
/// - `Time1 - Time2` unconditionally equals to `-(Time2 - Time1)`.
|
|
|
|
///
|
|
|
|
/// - Associativity does not generally hold, because
|
|
|
|
/// `(Time + Duration1) - Duration2` no longer equals to `Time + (Duration1 - Duration2)`
|
|
|
|
/// for two positive durations.
|
|
|
|
///
|
|
|
|
/// - As a special case, `(Time + Duration) - Duration` also does not equal to `Time`.
|
|
|
|
///
|
|
|
|
/// - If you can assume that all durations have the same sign, however,
|
|
|
|
/// then the associativity holds:
|
|
|
|
/// `(Time + Duration1) + Duration2` equals to `Time + (Duration1 + Duration2)`
|
|
|
|
/// for two positive durations.
|
|
|
|
///
|
|
|
|
/// ## Reading And Writing Leap Seconds
|
|
|
|
///
|
|
|
|
/// The "typical" leap seconds on the minute boundary are
|
|
|
|
/// correctly handled both in the formatting and parsing.
|
|
|
|
/// The leap second in the human-readable representation
|
|
|
|
/// will be represented as the second part being 60, as required by ISO 8601.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-06-21 15:33:17 +00:00
|
|
|
/// use chrono::{Utc, TimeZone};
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
2017-06-21 15:33:17 +00:00
|
|
|
/// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 59, 59, 1_000);
|
2017-06-21 05:03:49 +00:00
|
|
|
/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60Z");
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// There are hypothetical leap seconds not on the minute boundary
|
|
|
|
/// nevertheless supported by Chrono.
|
|
|
|
/// They are allowed for the sake of completeness and consistency;
|
|
|
|
/// there were several "exotic" time zone offsets with fractional minutes prior to UTC after all.
|
|
|
|
/// For such cases the human-readable representation is ambiguous
|
|
|
|
/// and would be read back to the next non-leap second.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-06-21 15:33:17 +00:00
|
|
|
/// use chrono::{DateTime, Utc, TimeZone};
|
2017-06-21 05:03:49 +00:00
|
|
|
///
|
2017-06-21 15:33:17 +00:00
|
|
|
/// let dt = Utc.ymd(2015, 6, 30).and_hms_milli(23, 56, 4, 1_000);
|
2017-06-21 05:03:49 +00:00
|
|
|
/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z");
|
|
|
|
///
|
2017-06-21 15:33:17 +00:00
|
|
|
/// let dt = Utc.ymd(2015, 6, 30).and_hms(23, 56, 5);
|
2017-06-21 05:03:49 +00:00
|
|
|
/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:56:05Z");
|
|
|
|
/// assert_eq!(DateTime::parse_from_rfc3339("2015-06-30T23:56:05Z").unwrap(), dt);
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Since Chrono alone cannot determine any existence of leap seconds,
|
|
|
|
/// **there is absolutely no guarantee that the leap second read has actually happened**.
|
2015-01-09 18:27:24 +00:00
|
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
|
2014-07-29 07:14:46 +00:00
|
|
|
pub struct NaiveTime {
|
|
|
|
secs: u32,
|
|
|
|
frac: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NaiveTime {
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute and second.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// No [leap second](#leap-second-handling) is allowed here;
|
2015-09-11 17:41:38 +00:00
|
|
|
/// use `NaiveTime::from_hms_*` methods with a subsecond parameter instead.
|
|
|
|
///
|
|
|
|
/// Panics on invalid hour, minute and/or second.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms(23, 56, 4);
|
|
|
|
/// assert_eq!(t.hour(), 23);
|
|
|
|
/// assert_eq!(t.minute(), 56);
|
|
|
|
/// assert_eq!(t.second(), 4);
|
|
|
|
/// assert_eq!(t.nanosecond(), 0);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_hms_opt(hour, min, sec).expect("invalid time")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute and second.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// No [leap second](#leap-second-handling) is allowed here;
|
2015-09-11 17:41:38 +00:00
|
|
|
/// use `NaiveTime::from_hms_*_opt` methods with a subsecond parameter instead.
|
|
|
|
///
|
2014-07-29 07:14:46 +00:00
|
|
|
/// Returns `None` on invalid hour, minute and/or second.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hms_opt = NaiveTime::from_hms_opt;
|
|
|
|
///
|
|
|
|
/// assert!(from_hms_opt(0, 0, 0).is_some());
|
|
|
|
/// assert!(from_hms_opt(23, 59, 59).is_some());
|
|
|
|
/// assert!(from_hms_opt(24, 0, 0).is_none());
|
|
|
|
/// assert!(from_hms_opt(23, 60, 0).is_none());
|
|
|
|
/// assert!(from_hms_opt(23, 59, 60).is_none());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> {
|
|
|
|
NaiveTime::from_hms_nano_opt(hour, min, sec, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and millisecond.
|
|
|
|
///
|
2015-09-11 17:41:38 +00:00
|
|
|
/// The millisecond part can exceed 1,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// Panics on invalid hour, minute, second and/or millisecond.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_milli(23, 56, 4, 12);
|
|
|
|
/// assert_eq!(t.hour(), 23);
|
|
|
|
/// assert_eq!(t.minute(), 56);
|
|
|
|
/// assert_eq!(t.second(), 4);
|
|
|
|
/// assert_eq!(t.nanosecond(), 12_000_000);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_milli(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and millisecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// The millisecond part can exceed 1,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2014-07-29 07:14:46 +00:00
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or millisecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hmsm_opt = NaiveTime::from_hms_milli_opt;
|
|
|
|
///
|
|
|
|
/// assert!(from_hmsm_opt(0, 0, 0, 0).is_some());
|
|
|
|
/// assert!(from_hmsm_opt(23, 59, 59, 999).is_some());
|
|
|
|
/// assert!(from_hmsm_opt(23, 59, 59, 1_999).is_some()); // a leap second after 23:59:59
|
|
|
|
/// assert!(from_hmsm_opt(24, 0, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsm_opt(23, 60, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsm_opt(23, 59, 60, 0).is_none());
|
|
|
|
/// assert!(from_hmsm_opt(23, 59, 59, 2_000).is_none());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> {
|
2014-11-19 01:59:32 +00:00
|
|
|
milli.checked_mul(1_000_000)
|
2014-07-29 07:14:46 +00:00
|
|
|
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and microsecond.
|
|
|
|
///
|
2015-09-11 17:41:38 +00:00
|
|
|
/// The microsecond part can exceed 1,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// Panics on invalid hour, minute, second and/or microsecond.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_micro(23, 56, 4, 12_345);
|
|
|
|
/// assert_eq!(t.hour(), 23);
|
|
|
|
/// assert_eq!(t.minute(), 56);
|
|
|
|
/// assert_eq!(t.second(), 4);
|
|
|
|
/// assert_eq!(t.nanosecond(), 12_345_000);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and microsecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// The microsecond part can exceed 1,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2014-07-29 07:14:46 +00:00
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or microsecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hmsu_opt = NaiveTime::from_hms_micro_opt;
|
|
|
|
///
|
|
|
|
/// assert!(from_hmsu_opt(0, 0, 0, 0).is_some());
|
|
|
|
/// assert!(from_hmsu_opt(23, 59, 59, 999_999).is_some());
|
|
|
|
/// assert!(from_hmsu_opt(23, 59, 59, 1_999_999).is_some()); // a leap second after 23:59:59
|
|
|
|
/// assert!(from_hmsu_opt(24, 0, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsu_opt(23, 60, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsu_opt(23, 59, 60, 0).is_none());
|
|
|
|
/// assert!(from_hmsu_opt(23, 59, 59, 2_000_000).is_none());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> {
|
2014-11-19 01:59:32 +00:00
|
|
|
micro.checked_mul(1_000)
|
2014-07-29 07:14:46 +00:00
|
|
|
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
|
|
|
|
///
|
2015-09-11 17:41:38 +00:00
|
|
|
/// The nanosecond part can exceed 1,000,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// Panics on invalid hour, minute, second and/or nanosecond.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(t.hour(), 23);
|
|
|
|
/// assert_eq!(t.minute(), 56);
|
|
|
|
/// assert_eq!(t.second(), 4);
|
|
|
|
/// assert_eq!(t.nanosecond(), 12_345_678);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_hms_nano(hour: u32, min: u32, sec: u32, nano: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// The nanosecond part can exceed 1,000,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2014-07-29 07:14:46 +00:00
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or nanosecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hmsn_opt = NaiveTime::from_hms_nano_opt;
|
|
|
|
///
|
|
|
|
/// assert!(from_hmsn_opt(0, 0, 0, 0).is_some());
|
|
|
|
/// assert!(from_hmsn_opt(23, 59, 59, 999_999_999).is_some());
|
|
|
|
/// assert!(from_hmsn_opt(23, 59, 59, 1_999_999_999).is_some()); // a leap second after 23:59:59
|
|
|
|
/// assert!(from_hmsn_opt(24, 0, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsn_opt(23, 60, 0, 0).is_none());
|
|
|
|
/// assert!(from_hmsn_opt(23, 59, 60, 0).is_none());
|
|
|
|
/// assert!(from_hmsn_opt(23, 59, 59, 2_000_000_000).is_none());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2014-07-31 01:09:54 +00:00
|
|
|
#[inline]
|
2014-07-29 07:14:46 +00:00
|
|
|
pub fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> {
|
|
|
|
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; }
|
|
|
|
let secs = hour * 3600 + min * 60 + sec;
|
|
|
|
Some(NaiveTime { secs: secs, frac: nano })
|
|
|
|
}
|
|
|
|
|
2014-07-31 01:09:54 +00:00
|
|
|
/// Makes a new `NaiveTime` from the number of seconds since midnight and nanosecond.
|
|
|
|
///
|
2015-09-11 17:41:38 +00:00
|
|
|
/// The nanosecond part can exceed 1,000,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// Panics on invalid number of seconds and/or nanosecond.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_num_seconds_from_midnight(86164, 12_345_678);
|
|
|
|
/// assert_eq!(t.hour(), 23);
|
|
|
|
/// assert_eq!(t.minute(), 56);
|
|
|
|
/// assert_eq!(t.second(), 4);
|
|
|
|
/// assert_eq!(t.nanosecond(), 12_345_678);
|
|
|
|
/// ~~~~
|
2014-07-31 01:09:54 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_num_seconds_from_midnight_opt(secs, nano).expect("invalid time")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` from the number of seconds since midnight and nanosecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// The nanosecond part can exceed 1,000,000,000
|
2017-06-21 15:40:48 +00:00
|
|
|
/// in order to represent the [leap second](#leap-second-handling).
|
2014-07-31 01:09:54 +00:00
|
|
|
///
|
|
|
|
/// Returns `None` on invalid number of seconds and/or nanosecond.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_nsecs_opt = NaiveTime::from_num_seconds_from_midnight_opt;
|
|
|
|
///
|
|
|
|
/// assert!(from_nsecs_opt(0, 0).is_some());
|
|
|
|
/// assert!(from_nsecs_opt(86399, 999_999_999).is_some());
|
|
|
|
/// assert!(from_nsecs_opt(86399, 1_999_999_999).is_some()); // a leap second after 23:59:59
|
2017-10-08 21:38:41 +00:00
|
|
|
/// assert!(from_nsecs_opt(86_400, 0).is_none());
|
2016-08-07 18:34:00 +00:00
|
|
|
/// assert!(from_nsecs_opt(86399, 2_000_000_000).is_none());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2014-07-31 01:09:54 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime> {
|
2017-10-08 21:38:41 +00:00
|
|
|
if secs >= 86_400 || nano >= 2_000_000_000 { return None; }
|
2014-07-31 01:09:54 +00:00
|
|
|
Some(NaiveTime { secs: secs, frac: nano })
|
|
|
|
}
|
|
|
|
|
2015-02-04 17:16:35 +00:00
|
|
|
/// Parses a string with the specified format string and returns a new `NaiveTime`.
|
2017-06-21 12:58:42 +00:00
|
|
|
/// See the [`format::strftime` module](../format/strftime/index.html)
|
2015-09-06 12:30:09 +00:00
|
|
|
/// on the supported escape sequences.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let parse_from_str = NaiveTime::parse_from_str;
|
|
|
|
///
|
|
|
|
/// assert_eq!(parse_from_str("23:56:04", "%H:%M:%S"),
|
2015-09-11 17:41:38 +00:00
|
|
|
/// Ok(NaiveTime::from_hms(23, 56, 4)));
|
2016-08-07 18:34:00 +00:00
|
|
|
/// assert_eq!(parse_from_str("pm012345.6789", "%p%I%M%S%.f"),
|
2015-09-11 17:41:38 +00:00
|
|
|
/// Ok(NaiveTime::from_hms_micro(13, 23, 45, 678_900)));
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Date and offset is ignored for the purpose of parsing.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let parse_from_str = NaiveTime::parse_from_str;
|
|
|
|
/// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
|
2015-09-11 17:41:38 +00:00
|
|
|
/// Ok(NaiveTime::from_hms(12, 34, 56)));
|
|
|
|
/// ~~~~
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// [Leap seconds](#leap-second-handling) are correctly handled by
|
2015-09-11 17:41:38 +00:00
|
|
|
/// treating any time of the form `hh:mm:60` as a leap second.
|
|
|
|
/// (This equally applies to the formatting, so the round trip is possible.)
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let parse_from_str = NaiveTime::parse_from_str;
|
|
|
|
/// assert_eq!(parse_from_str("08:59:60.123", "%H:%M:%S%.f"),
|
2015-09-11 17:41:38 +00:00
|
|
|
/// Ok(NaiveTime::from_hms_milli(8, 59, 59, 1_123)));
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Missing seconds are assumed to be zero,
|
|
|
|
/// but out-of-bound times or insufficient fields are errors otherwise.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let parse_from_str = NaiveTime::parse_from_str;
|
|
|
|
/// assert_eq!(parse_from_str("7:15", "%H:%M"),
|
2015-09-11 17:41:38 +00:00
|
|
|
/// Ok(NaiveTime::from_hms(7, 15, 0)));
|
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err());
|
|
|
|
/// assert!(parse_from_str("12", "%H").is_err());
|
|
|
|
/// assert!(parse_from_str("17:60", "%H:%M").is_err());
|
|
|
|
/// assert!(parse_from_str("24:00:00", "%H:%M:%S").is_err());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// All parsed fields should be consistent to each other, otherwise it's an error.
|
|
|
|
/// Here `%H` is for 24-hour clocks, unlike `%I`,
|
|
|
|
/// and thus can be independently determined without AM/PM.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let parse_from_str = NaiveTime::parse_from_str;
|
|
|
|
/// assert!(parse_from_str("13:07 AM", "%H:%M %p").is_err());
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2015-02-15 12:26:11 +00:00
|
|
|
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime> {
|
2015-02-04 17:16:35 +00:00
|
|
|
let mut parsed = Parsed::new();
|
|
|
|
try!(parse(&mut parsed, s, StrftimeItems::new(fmt)));
|
|
|
|
parsed.to_naive_time()
|
|
|
|
}
|
|
|
|
|
2016-08-16 15:40:36 +00:00
|
|
|
/// Adds given `Duration` to the current time,
|
|
|
|
/// and also returns the number of *seconds*
|
|
|
|
/// in the integral number of days ignored from the addition.
|
|
|
|
/// (We cannot return `Duration` because it is subject to overflow or underflow.)
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
2016-08-16 15:40:36 +00:00
|
|
|
///
|
|
|
|
/// let from_hms = NaiveTime::from_hms;
|
|
|
|
///
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(11)),
|
2016-08-16 15:40:36 +00:00
|
|
|
/// (from_hms(14, 4, 5), 0));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(23)),
|
2017-10-08 21:38:41 +00:00
|
|
|
/// (from_hms(2, 4, 5), 86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(-7)),
|
2017-10-08 21:38:41 +00:00
|
|
|
/// (from_hms(20, 4, 5), -86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-16 15:40:36 +00:00
|
|
|
/// ~~~~
|
2017-06-24 17:42:59 +00:00
|
|
|
#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
|
2017-02-05 23:17:01 +00:00
|
|
|
pub fn overflowing_add_signed(&self, mut rhs: OldDuration) -> (NaiveTime, i64) {
|
2016-08-16 15:40:36 +00:00
|
|
|
let mut secs = self.secs;
|
|
|
|
let mut frac = self.frac;
|
|
|
|
|
|
|
|
// check if `self` is a leap second and adding `rhs` would escape that leap second.
|
|
|
|
// if it's the case, update `self` and `rhs` to involve no leap second;
|
|
|
|
// otherwise the addition immediately finishes.
|
|
|
|
if frac >= 1_000_000_000 {
|
|
|
|
let rfrac = 2_000_000_000 - frac;
|
2017-10-08 22:08:40 +00:00
|
|
|
if rhs >= OldDuration::nanoseconds(i64::from(rfrac)) {
|
|
|
|
rhs = rhs - OldDuration::nanoseconds(i64::from(rfrac));
|
2016-08-16 15:40:36 +00:00
|
|
|
secs += 1;
|
|
|
|
frac = 0;
|
2017-10-08 22:08:40 +00:00
|
|
|
} else if rhs < OldDuration::nanoseconds(-i64::from(frac)) {
|
|
|
|
rhs = rhs + OldDuration::nanoseconds(i64::from(frac));
|
2016-08-16 15:40:36 +00:00
|
|
|
frac = 0;
|
|
|
|
} else {
|
2017-10-08 22:08:40 +00:00
|
|
|
frac = (i64::from(frac) + rhs.num_nanoseconds().unwrap()) as u32;
|
2016-08-16 15:40:36 +00:00
|
|
|
debug_assert!(frac < 2_000_000_000);
|
|
|
|
return (NaiveTime { secs: secs, frac: frac }, 0);
|
|
|
|
}
|
|
|
|
}
|
2017-10-08 21:38:41 +00:00
|
|
|
debug_assert!(secs <= 86_400);
|
2016-08-16 15:40:36 +00:00
|
|
|
debug_assert!(frac < 1_000_000_000);
|
|
|
|
|
|
|
|
let rhssecs = rhs.num_seconds();
|
2017-02-05 23:17:01 +00:00
|
|
|
let rhsfrac = (rhs - OldDuration::seconds(rhssecs)).num_nanoseconds().unwrap();
|
2017-06-23 19:41:16 +00:00
|
|
|
debug_assert_eq!(OldDuration::seconds(rhssecs) + OldDuration::nanoseconds(rhsfrac), rhs);
|
2017-10-08 21:38:41 +00:00
|
|
|
let rhssecsinday = rhssecs % 86_400;
|
2016-08-16 15:40:36 +00:00
|
|
|
let mut morerhssecs = rhssecs - rhssecsinday;
|
|
|
|
let rhssecs = rhssecsinday as i32;
|
|
|
|
let rhsfrac = rhsfrac as i32;
|
2017-10-08 21:38:41 +00:00
|
|
|
debug_assert!(-86_400 < rhssecs && rhssecs < 86_400);
|
|
|
|
debug_assert_eq!(morerhssecs % 86_400, 0);
|
2016-08-16 15:40:36 +00:00
|
|
|
debug_assert!(-1_000_000_000 < rhsfrac && rhsfrac < 1_000_000_000);
|
|
|
|
|
|
|
|
let mut secs = secs as i32 + rhssecs;
|
|
|
|
let mut frac = frac as i32 + rhsfrac;
|
2017-10-08 21:38:41 +00:00
|
|
|
debug_assert!(-86_400 < secs && secs < 2 * 86_400);
|
2016-08-16 15:40:36 +00:00
|
|
|
debug_assert!(-1_000_000_000 < frac && frac < 2_000_000_000);
|
|
|
|
|
|
|
|
if frac < 0 {
|
|
|
|
frac += 1_000_000_000;
|
|
|
|
secs -= 1;
|
|
|
|
} else if frac >= 1_000_000_000 {
|
|
|
|
frac -= 1_000_000_000;
|
|
|
|
secs += 1;
|
|
|
|
}
|
2017-10-08 21:38:41 +00:00
|
|
|
debug_assert!(-86_400 <= secs && secs < 2 * 86_400);
|
2016-08-16 15:40:36 +00:00
|
|
|
debug_assert!(0 <= frac && frac < 1_000_000_000);
|
|
|
|
|
|
|
|
if secs < 0 {
|
2017-10-08 21:38:41 +00:00
|
|
|
secs += 86_400;
|
|
|
|
morerhssecs -= 86_400;
|
|
|
|
} else if secs >= 86_400 {
|
|
|
|
secs -= 86_400;
|
|
|
|
morerhssecs += 86_400;
|
2016-08-16 15:40:36 +00:00
|
|
|
}
|
2017-10-08 21:38:41 +00:00
|
|
|
debug_assert!(0 <= secs && secs < 86_400);
|
2016-08-16 15:40:36 +00:00
|
|
|
|
|
|
|
(NaiveTime { secs: secs as u32, frac: frac as u32 }, morerhssecs)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Subtracts given `Duration` from the current time,
|
|
|
|
/// and also returns the number of *seconds*
|
|
|
|
/// in the integral number of days ignored from the subtraction.
|
|
|
|
/// (We cannot return `Duration` because it is subject to overflow or underflow.)
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
2016-08-16 15:40:36 +00:00
|
|
|
///
|
|
|
|
/// let from_hms = NaiveTime::from_hms;
|
|
|
|
///
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(2)),
|
2016-08-16 15:40:36 +00:00
|
|
|
/// (from_hms(1, 4, 5), 0));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(17)),
|
2017-10-08 21:38:41 +00:00
|
|
|
/// (from_hms(10, 4, 5), 86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(-22)),
|
2017-10-08 21:38:41 +00:00
|
|
|
/// (from_hms(1, 4, 5), -86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-16 15:40:36 +00:00
|
|
|
/// ~~~~
|
|
|
|
#[inline]
|
2017-02-05 23:17:01 +00:00
|
|
|
pub fn overflowing_sub_signed(&self, rhs: OldDuration) -> (NaiveTime, i64) {
|
|
|
|
let (time, rhs) = self.overflowing_add_signed(-rhs);
|
2016-08-16 15:40:36 +00:00
|
|
|
(time, -rhs) // safe to negate, rhs is within +/- (2^63 / 1000)
|
|
|
|
}
|
|
|
|
|
2017-02-05 23:17:01 +00:00
|
|
|
/// Subtracts another `NaiveTime` from the current time.
|
|
|
|
/// Returns a `Duration` within +/- 1 day.
|
|
|
|
/// This does not overflow or underflow at all.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// As a part of Chrono's [leap second handling](#leap-second-handling),
|
2017-02-05 23:17:01 +00:00
|
|
|
/// the subtraction assumes that **there is no leap second ever**,
|
|
|
|
/// except when any of the `NaiveTime`s themselves represents a leap second
|
|
|
|
/// in which case the assumption becomes that
|
|
|
|
/// **there are exactly one (or two) leap second(s) ever**.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
|
|
|
///
|
|
|
|
/// let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// let since = NaiveTime::signed_duration_since;
|
|
|
|
///
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 7, 900)),
|
|
|
|
/// Duration::zero());
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 7, 875)),
|
|
|
|
/// Duration::milliseconds(25));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 6, 925)),
|
|
|
|
/// Duration::milliseconds(975));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 0, 900)),
|
|
|
|
/// Duration::seconds(7));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 0, 7, 900)),
|
|
|
|
/// Duration::seconds(5 * 60));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(0, 5, 7, 900)),
|
|
|
|
/// Duration::seconds(3 * 3600));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(4, 5, 7, 900)),
|
|
|
|
/// Duration::seconds(-3600));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(2, 4, 6, 800)),
|
|
|
|
/// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100));
|
|
|
|
/// # }
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds are handled, but the subtraction assumes that
|
|
|
|
/// there were no other leap seconds happened.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// # let since = NaiveTime::signed_duration_since;
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(3, 0, 59, 0)),
|
|
|
|
/// Duration::seconds(1));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_500), from_hmsm(3, 0, 59, 0)),
|
|
|
|
/// Duration::milliseconds(1500));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(3, 0, 0, 0)),
|
|
|
|
/// Duration::seconds(60));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 0, 0, 0), from_hmsm(2, 59, 59, 1_000)),
|
|
|
|
/// Duration::seconds(1));
|
|
|
|
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(2, 59, 59, 1_000)),
|
|
|
|
/// Duration::seconds(61));
|
|
|
|
/// # }
|
|
|
|
/// ~~~~
|
|
|
|
pub fn signed_duration_since(self, rhs: NaiveTime) -> OldDuration {
|
|
|
|
// | | :leap| | | | | | | :leap| |
|
|
|
|
// | | : | | | | | | | : | |
|
|
|
|
// ----+----+-----*---+----+----+----+----+----+----+-------*-+----+----
|
|
|
|
// | `rhs` | | `self`
|
|
|
|
// |======================================>| |
|
|
|
|
// | | `self.secs - rhs.secs` |`self.frac`
|
|
|
|
// |====>| | |======>|
|
|
|
|
// `rhs.frac`|========================================>|
|
|
|
|
// | | | `self - rhs` | |
|
|
|
|
|
2019-09-07 10:12:49 +00:00
|
|
|
use core::cmp::Ordering;
|
2017-02-05 23:17:01 +00:00
|
|
|
|
2017-10-08 22:08:40 +00:00
|
|
|
let secs = i64::from(self.secs) - i64::from(rhs.secs);
|
|
|
|
let frac = i64::from(self.frac) - i64::from(rhs.frac);
|
2017-02-05 23:17:01 +00:00
|
|
|
|
|
|
|
// `secs` may contain a leap second yet to be counted
|
|
|
|
let adjust = match self.secs.cmp(&rhs.secs) {
|
|
|
|
Ordering::Greater => if rhs.frac >= 1_000_000_000 { 1 } else { 0 },
|
|
|
|
Ordering::Equal => 0,
|
|
|
|
Ordering::Less => if self.frac >= 1_000_000_000 { -1 } else { 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
OldDuration::seconds(secs + adjust) + OldDuration::nanoseconds(frac)
|
|
|
|
}
|
|
|
|
|
2015-02-14 03:33:12 +00:00
|
|
|
/// Formats the time with the specified formatting items.
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Otherwise it is same to the ordinary [`format`](#method.format) method.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// The `Iterator` of items should be `Clone`able,
|
|
|
|
/// since the resulting `DelayedFormat` value may be formatted multiple times.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use chrono::format::strftime::StrftimeItems;
|
|
|
|
///
|
|
|
|
/// let fmt = StrftimeItems::new("%H:%M:%S");
|
|
|
|
/// let t = NaiveTime::from_hms(23, 56, 4);
|
|
|
|
/// assert_eq!(t.format_with_items(fmt.clone()).to_string(), "23:56:04");
|
2016-08-07 18:04:39 +00:00
|
|
|
/// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04");
|
2015-09-11 17:41:38 +00:00
|
|
|
/// ~~~~
|
2016-08-06 10:06:28 +00:00
|
|
|
///
|
|
|
|
/// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2016-08-07 18:04:39 +00:00
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use chrono::format::strftime::StrftimeItems;
|
|
|
|
/// # let fmt = StrftimeItems::new("%H:%M:%S").clone();
|
|
|
|
/// # let t = NaiveTime::from_hms(23, 56, 4);
|
|
|
|
/// assert_eq!(format!("{}", t.format_with_items(fmt)), "23:56:04");
|
2016-08-06 10:06:28 +00:00
|
|
|
/// ~~~~
|
2019-09-09 11:41:44 +00:00
|
|
|
#[cfg(any(feature = "alloc", feature = "std", test))]
|
2015-02-14 03:33:12 +00:00
|
|
|
#[inline]
|
2015-02-21 09:14:09 +00:00
|
|
|
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
2015-02-14 03:33:12 +00:00
|
|
|
where I: Iterator<Item=Item<'a>> + Clone {
|
2016-10-01 22:56:37 +00:00
|
|
|
DelayedFormat::new(None, Some(*self), items)
|
2015-02-14 03:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Formats the time with the specified format string.
|
2017-06-21 12:58:42 +00:00
|
|
|
/// See the [`format::strftime` module](../format/strftime/index.html)
|
2015-09-06 12:30:09 +00:00
|
|
|
/// on the supported escape sequences.
|
2015-09-11 17:41:38 +00:00
|
|
|
///
|
|
|
|
/// This returns a `DelayedFormat`,
|
|
|
|
/// which gets converted to a string only when actual formatting happens.
|
|
|
|
/// You may use the `to_string` method to get a `String`,
|
|
|
|
/// or just feed it into `print!` and other formatting macros.
|
|
|
|
/// (In this way it avoids the redundant memory allocation.)
|
|
|
|
///
|
|
|
|
/// A wrong format string does *not* issue an error immediately.
|
|
|
|
/// Rather, converting or formatting the `DelayedFormat` fails.
|
|
|
|
/// You are recommended to immediately use `DelayedFormat` for this reason.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04");
|
|
|
|
/// assert_eq!(t.format("%H:%M:%S%.6f").to_string(), "23:56:04.012345");
|
|
|
|
/// assert_eq!(t.format("%-I:%M %p").to_string(), "11:56 PM");
|
|
|
|
/// ~~~~
|
2016-08-06 10:06:28 +00:00
|
|
|
///
|
|
|
|
/// The resulting `DelayedFormat` can be formatted directly via the `Display` trait.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2016-08-07 18:04:39 +00:00
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
2016-08-06 10:06:28 +00:00
|
|
|
/// assert_eq!(format!("{}", t.format("%H:%M:%S")), "23:56:04");
|
|
|
|
/// assert_eq!(format!("{}", t.format("%H:%M:%S%.6f")), "23:56:04.012345");
|
|
|
|
/// assert_eq!(format!("{}", t.format("%-I:%M %p")), "11:56 PM");
|
|
|
|
/// ~~~~
|
2019-09-09 11:41:44 +00:00
|
|
|
#[cfg(any(feature = "alloc", feature = "std", test))]
|
2014-07-31 19:08:19 +00:00
|
|
|
#[inline]
|
2015-02-21 09:14:09 +00:00
|
|
|
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
|
2015-02-14 03:33:12 +00:00
|
|
|
self.format_with_items(StrftimeItems::new(fmt))
|
2014-07-31 19:08:19 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 07:14:46 +00:00
|
|
|
/// Returns a triple of the hour, minute and second numbers.
|
|
|
|
fn hms(&self) -> (u32, u32, u32) {
|
2014-11-24 05:49:13 +00:00
|
|
|
let (mins, sec) = div_mod_floor(self.secs, 60);
|
|
|
|
let (hour, min) = div_mod_floor(mins, 60);
|
2014-07-29 07:14:46 +00:00
|
|
|
(hour, min, sec)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Timelike for NaiveTime {
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Returns the hour number from 0 to 23.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// assert_eq!(NaiveTime::from_hms(0, 0, 0).hour(), 0);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).hour(), 23);
|
|
|
|
/// ~~~~
|
|
|
|
#[inline]
|
|
|
|
fn hour(&self) -> u32 {
|
|
|
|
self.hms().0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the minute number from 0 to 59.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// assert_eq!(NaiveTime::from_hms(0, 0, 0).minute(), 0);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).minute(), 56);
|
|
|
|
/// ~~~~
|
|
|
|
#[inline]
|
|
|
|
fn minute(&self) -> u32 {
|
|
|
|
self.hms().1
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the second number from 0 to 59.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// assert_eq!(NaiveTime::from_hms(0, 0, 0).second(), 0);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).second(), 4);
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// This method never returns 60 even when it is a leap second.
|
2017-06-21 15:40:48 +00:00
|
|
|
/// ([Why?](#leap-second-handling))
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Use the proper [formatting method](#method.format) to get a human-readable representation.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::{NaiveTime, Timelike};
|
|
|
|
/// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000);
|
|
|
|
/// assert_eq!(leap.second(), 59);
|
|
|
|
/// assert_eq!(leap.format("%H:%M:%S").to_string(), "23:59:60");
|
|
|
|
/// ~~~~
|
|
|
|
#[inline]
|
|
|
|
fn second(&self) -> u32 {
|
|
|
|
self.hms().2
|
|
|
|
}
|
2014-07-29 07:14:46 +00:00
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Returns the number of nanoseconds since the whole non-leap second.
|
|
|
|
/// The range from 1,000,000,000 to 1,999,999,999 represents
|
2017-06-21 05:03:49 +00:00
|
|
|
/// the [leap second](#leap-second-handling).
|
2016-07-31 16:02:32 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// assert_eq!(NaiveTime::from_hms(0, 0, 0).nanosecond(), 0);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).nanosecond(), 12_345_678);
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds may have seemingly out-of-range return values.
|
|
|
|
/// You can reduce the range with `time.nanosecond() % 1_000_000_000`, or
|
|
|
|
/// use the proper [formatting method](#method.format) to get a human-readable representation.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::{NaiveTime, Timelike};
|
|
|
|
/// let leap = NaiveTime::from_hms_milli(23, 59, 59, 1_000);
|
|
|
|
/// assert_eq!(leap.nanosecond(), 1_000_000_000);
|
|
|
|
/// assert_eq!(leap.format("%H:%M:%S%.9f").to_string(), "23:59:60.000000000");
|
|
|
|
/// ~~~~
|
|
|
|
#[inline]
|
|
|
|
fn nanosecond(&self) -> u32 {
|
|
|
|
self.frac
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes a new `NaiveTime` with the hour number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting `NaiveTime` would be invalid.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678)));
|
|
|
|
/// assert_eq!(dt.with_hour(24), None);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_hour(&self, hour: u32) -> Option<NaiveTime> {
|
|
|
|
if hour >= 24 { return None; }
|
|
|
|
let secs = hour * 3600 + self.secs % 3600;
|
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
|
|
|
}
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Makes a new `NaiveTime` with the minute number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting `NaiveTime` would be invalid.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(dt.with_minute(45), Some(NaiveTime::from_hms_nano(23, 45, 4, 12_345_678)));
|
|
|
|
/// assert_eq!(dt.with_minute(60), None);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_minute(&self, min: u32) -> Option<NaiveTime> {
|
|
|
|
if min >= 60 { return None; }
|
|
|
|
let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60;
|
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
|
|
|
}
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Makes a new `NaiveTime` with the second number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting `NaiveTime` would be invalid.
|
2016-07-31 18:23:46 +00:00
|
|
|
/// As with the [`second`](#method.second) method,
|
2016-07-31 16:02:32 +00:00
|
|
|
/// the input range is restricted to 0 through 59.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678)));
|
|
|
|
/// assert_eq!(dt.with_second(60), None);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_second(&self, sec: u32) -> Option<NaiveTime> {
|
|
|
|
if sec >= 60 { return None; }
|
|
|
|
let secs = self.secs / 60 * 60 + sec;
|
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
|
|
|
}
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting `NaiveTime` would be invalid.
|
2016-07-31 18:23:46 +00:00
|
|
|
/// As with the [`nanosecond`](#method.nanosecond) method,
|
2016-07-31 16:02:32 +00:00
|
|
|
/// the input range can exceed 1,000,000,000 for leap seconds.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(dt.with_nanosecond(333_333_333),
|
|
|
|
/// Some(NaiveTime::from_hms_nano(23, 56, 4, 333_333_333)));
|
|
|
|
/// assert_eq!(dt.with_nanosecond(2_000_000_000), None);
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds can theoretically follow *any* whole second.
|
|
|
|
/// The following would be a proper leap second at the time zone offset of UTC-00:03:57
|
|
|
|
/// (there are several historical examples comparable to this "non-sense" offset),
|
|
|
|
/// and therefore is allowed.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::{NaiveTime, Timelike};
|
|
|
|
/// # let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!(dt.with_nanosecond(1_333_333_333),
|
|
|
|
/// Some(NaiveTime::from_hms_nano(23, 56, 4, 1_333_333_333)));
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> {
|
|
|
|
if nano >= 2_000_000_000 { return None; }
|
|
|
|
Some(NaiveTime { frac: nano, ..*self })
|
|
|
|
}
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// Returns the number of non-leap seconds past the last midnight.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::{NaiveTime, Timelike};
|
|
|
|
///
|
|
|
|
/// assert_eq!(NaiveTime::from_hms(1, 2, 3).num_seconds_from_midnight(),
|
|
|
|
/// 3723);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).num_seconds_from_midnight(),
|
|
|
|
/// 86164);
|
|
|
|
/// assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).num_seconds_from_midnight(),
|
|
|
|
/// 86399);
|
|
|
|
/// ~~~~
|
2014-07-29 07:14:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn num_seconds_from_midnight(&self) -> u32 {
|
|
|
|
self.secs // do not repeat the calculation!
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-31 16:02:32 +00:00
|
|
|
/// `NaiveTime` can be used as a key to the hash maps (in principle).
|
|
|
|
///
|
|
|
|
/// Practically this also takes account of fractional seconds, so it is not recommended.
|
|
|
|
/// (For the obvious reason this also distinguishes leap seconds from non-leap seconds.)
|
2017-07-09 20:21:51 +00:00
|
|
|
#[cfg_attr(feature = "cargo-clippy", allow(derive_hash_xor_eq))]
|
2015-02-21 09:14:09 +00:00
|
|
|
impl hash::Hash for NaiveTime {
|
|
|
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
|
|
|
self.secs.hash(state);
|
|
|
|
self.frac.hash(state);
|
|
|
|
}
|
2015-01-09 18:27:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-06 10:06:28 +00:00
|
|
|
/// An addition of `Duration` to `NaiveTime` wraps around and never overflows or underflows.
|
|
|
|
/// In particular the addition ignores integral number of days.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// As a part of Chrono's [leap second handling](#leap-second-handling),
|
2016-08-06 10:06:28 +00:00
|
|
|
/// the addition assumes that **there is no leap second ever**,
|
|
|
|
/// except when the `NaiveTime` itself represents a leap second
|
2016-08-06 17:32:09 +00:00
|
|
|
/// in which case the assumption becomes that **there is exactly a single leap second ever**.
|
2016-08-06 10:06:28 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
2016-08-06 10:06:28 +00:00
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
///
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::zero(), from_hmsm(3, 5, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(1), from_hmsm(3, 5, 8, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-1), from_hmsm(3, 5, 6, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(60 + 4), from_hmsm(3, 6, 11, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(7*60*60 - 6*60), from_hmsm(9, 59, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::milliseconds(80), from_hmsm(3, 5, 7, 80));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(280), from_hmsm(3, 5, 8, 230));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 950) + Duration::milliseconds(-980), from_hmsm(3, 5, 6, 970));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 10:06:28 +00:00
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// The addition wraps around.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(22*60*60), from_hmsm(1, 5, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-8*60*60), from_hmsm(19, 5, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::days(800), from_hmsm(3, 5, 7, 0));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 10:06:28 +00:00
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds are handled, but the addition assumes that it is the only leap second happened.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// let leap = from_hmsm(3, 5, 59, 1_300);
|
|
|
|
/// assert_eq!(leap + Duration::zero(), from_hmsm(3, 5, 59, 1_300));
|
|
|
|
/// assert_eq!(leap + Duration::milliseconds(-500), from_hmsm(3, 5, 59, 800));
|
|
|
|
/// assert_eq!(leap + Duration::milliseconds(500), from_hmsm(3, 5, 59, 1_800));
|
|
|
|
/// assert_eq!(leap + Duration::milliseconds(800), from_hmsm(3, 6, 0, 100));
|
|
|
|
/// assert_eq!(leap + Duration::seconds(10), from_hmsm(3, 6, 9, 300));
|
|
|
|
/// assert_eq!(leap + Duration::seconds(-10), from_hmsm(3, 5, 50, 300));
|
|
|
|
/// assert_eq!(leap + Duration::days(1), from_hmsm(3, 5, 59, 300));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 10:06:28 +00:00
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
impl Add<OldDuration> for NaiveTime {
|
2015-01-05 09:31:15 +00:00
|
|
|
type Output = NaiveTime;
|
|
|
|
|
2016-08-16 15:40:36 +00:00
|
|
|
#[inline]
|
2017-02-05 23:17:01 +00:00
|
|
|
fn add(self, rhs: OldDuration) -> NaiveTime {
|
|
|
|
self.overflowing_add_signed(rhs).0
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-21 16:03:06 +00:00
|
|
|
impl AddAssign<OldDuration> for NaiveTime {
|
|
|
|
#[inline]
|
|
|
|
fn add_assign(&mut self, rhs: OldDuration) {
|
2016-10-02 13:38:06 +00:00
|
|
|
*self = self.add(rhs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-06 17:32:09 +00:00
|
|
|
/// A subtraction of `Duration` from `NaiveTime` wraps around and never overflows or underflows.
|
|
|
|
/// In particular the addition ignores integral number of days.
|
|
|
|
/// It is same to the addition with a negated `Duration`.
|
|
|
|
///
|
2017-06-21 15:40:48 +00:00
|
|
|
/// As a part of Chrono's [leap second handling](#leap-second-handling),
|
2016-08-06 17:32:09 +00:00
|
|
|
/// the addition assumes that **there is no leap second ever**,
|
|
|
|
/// except when the `NaiveTime` itself represents a leap second
|
|
|
|
/// in which case the assumption becomes that **there is exactly a single leap second ever**.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
2016-08-06 17:32:09 +00:00
|
|
|
///
|
2016-08-07 18:34:00 +00:00
|
|
|
/// let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
///
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::zero(), from_hmsm(3, 5, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(1), from_hmsm(3, 5, 6, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(60 + 5), from_hmsm(3, 4, 2, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(2*60*60 + 6*60), from_hmsm(0, 59, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::milliseconds(80), from_hmsm(3, 5, 6, 920));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 950) - Duration::milliseconds(280), from_hmsm(3, 5, 7, 670));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 17:32:09 +00:00
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// The subtraction wraps around.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(8*60*60), from_hmsm(19, 5, 7, 0));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::days(800), from_hmsm(3, 5, 7, 0));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 17:32:09 +00:00
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds are handled, but the subtraction assumes that it is the only leap second happened.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
2016-08-07 18:34:00 +00:00
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// let leap = from_hmsm(3, 5, 59, 1_300);
|
|
|
|
/// assert_eq!(leap - Duration::zero(), from_hmsm(3, 5, 59, 1_300));
|
|
|
|
/// assert_eq!(leap - Duration::milliseconds(200), from_hmsm(3, 5, 59, 1_100));
|
|
|
|
/// assert_eq!(leap - Duration::milliseconds(500), from_hmsm(3, 5, 59, 800));
|
|
|
|
/// assert_eq!(leap - Duration::seconds(60), from_hmsm(3, 5, 0, 300));
|
|
|
|
/// assert_eq!(leap - Duration::days(1), from_hmsm(3, 6, 0, 300));
|
2017-02-05 23:17:01 +00:00
|
|
|
/// # }
|
2016-08-06 17:32:09 +00:00
|
|
|
/// ~~~~
|
2017-02-05 23:17:01 +00:00
|
|
|
impl Sub<OldDuration> for NaiveTime {
|
2015-01-05 09:31:15 +00:00
|
|
|
type Output = NaiveTime;
|
|
|
|
|
2014-11-28 14:53:22 +00:00
|
|
|
#[inline]
|
2017-02-05 23:17:01 +00:00
|
|
|
fn sub(self, rhs: OldDuration) -> NaiveTime {
|
|
|
|
self.overflowing_sub_signed(rhs).0
|
2016-08-16 15:40:36 +00:00
|
|
|
}
|
2014-11-28 14:53:22 +00:00
|
|
|
}
|
|
|
|
|
2018-04-03 13:16:37 +00:00
|
|
|
impl SubAssign<OldDuration> for NaiveTime {
|
|
|
|
#[inline]
|
|
|
|
fn sub_assign(&mut self, rhs: OldDuration) {
|
|
|
|
*self = self.sub(rhs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-03 12:58:26 +00:00
|
|
|
/// Subtracts another `NaiveTime` from the current time.
|
|
|
|
/// Returns a `Duration` within +/- 1 day.
|
|
|
|
/// This does not overflow or underflow at all.
|
|
|
|
///
|
|
|
|
/// As a part of Chrono's [leap second handling](#leap-second-handling),
|
|
|
|
/// the subtraction assumes that **there is no leap second ever**,
|
|
|
|
/// except when any of the `NaiveTime`s themselves represents a leap second
|
|
|
|
/// in which case the assumption becomes that
|
|
|
|
/// **there are exactly one (or two) leap second(s) ever**.
|
|
|
|
///
|
|
|
|
/// The implementation is a wrapper around
|
|
|
|
/// [`NaiveTime::signed_duration_since`](#method.signed_duration_since).
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
/// use time::Duration;
|
|
|
|
///
|
|
|
|
/// let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
///
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 900), Duration::zero());
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 875), Duration::milliseconds(25));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 6, 925), Duration::milliseconds(975));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 0, 900), Duration::seconds(7));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 0, 7, 900), Duration::seconds(5 * 60));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(0, 5, 7, 900), Duration::seconds(3 * 3600));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(4, 5, 7, 900), Duration::seconds(-3600));
|
|
|
|
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(2, 4, 6, 800),
|
|
|
|
/// Duration::seconds(3600 + 60 + 1) + Duration::milliseconds(100));
|
|
|
|
/// # }
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds are handled, but the subtraction assumes that
|
|
|
|
/// there were no other leap seconds happened.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # extern crate chrono; extern crate time; fn main() {
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// # use time::Duration;
|
|
|
|
/// # let from_hmsm = NaiveTime::from_hms_milli;
|
|
|
|
/// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 59, 0), Duration::seconds(1));
|
|
|
|
/// assert_eq!(from_hmsm(3, 0, 59, 1_500) - from_hmsm(3, 0, 59, 0),
|
|
|
|
/// Duration::milliseconds(1500));
|
|
|
|
/// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 0, 0), Duration::seconds(60));
|
|
|
|
/// assert_eq!(from_hmsm(3, 0, 0, 0) - from_hmsm(2, 59, 59, 1_000), Duration::seconds(1));
|
|
|
|
/// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(2, 59, 59, 1_000),
|
|
|
|
/// Duration::seconds(61));
|
|
|
|
/// # }
|
|
|
|
/// ~~~~
|
2018-04-03 12:42:03 +00:00
|
|
|
impl Sub<NaiveTime> for NaiveTime {
|
|
|
|
type Output = OldDuration;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: NaiveTime) -> OldDuration {
|
|
|
|
self.signed_duration_since(rhs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-07 18:04:39 +00:00
|
|
|
/// The `Debug` output of the naive time `t` is same to
|
2017-06-21 12:58:42 +00:00
|
|
|
/// [`t.format("%H:%M:%S%.f")`](../format/strftime/index.html).
|
2016-08-07 18:04:39 +00:00
|
|
|
///
|
|
|
|
/// The string printed can be readily parsed via the `parse` method on `str`.
|
|
|
|
///
|
|
|
|
/// It should be noted that, for leap seconds not on the minute boundary,
|
|
|
|
/// it may print a representation not distinguishable from non-leap seconds.
|
|
|
|
/// This doesn't matter in practice, since such leap seconds never happened.
|
|
|
|
/// (By the time of the first leap second on 1972-06-30,
|
|
|
|
/// every time zone offset around the world has standardized to the 5-minute alignment.)
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
|
|
|
/// assert_eq!(format!("{:?}", NaiveTime::from_hms(23, 56, 4)), "23:56:04");
|
|
|
|
/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012");
|
|
|
|
/// assert_eq!(format!("{:?}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234");
|
|
|
|
/// assert_eq!(format!("{:?}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456");
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds may also be used.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500");
|
|
|
|
/// ~~~~
|
2015-01-24 08:45:12 +00:00
|
|
|
impl fmt::Debug for NaiveTime {
|
2014-07-29 07:14:46 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
let (hour, min, sec) = self.hms();
|
|
|
|
let (sec, nano) = if self.frac >= 1_000_000_000 {
|
|
|
|
(sec + 1, self.frac - 1_000_000_000)
|
|
|
|
} else {
|
|
|
|
(sec, self.frac)
|
|
|
|
};
|
|
|
|
|
|
|
|
try!(write!(f, "{:02}:{:02}:{:02}", hour, min, sec));
|
|
|
|
if nano == 0 {
|
|
|
|
Ok(())
|
|
|
|
} else if nano % 1_000_000 == 0 {
|
2014-07-31 02:03:32 +00:00
|
|
|
write!(f, ".{:03}", nano / 1_000_000)
|
2014-07-29 07:14:46 +00:00
|
|
|
} else if nano % 1_000 == 0 {
|
2014-07-31 02:03:32 +00:00
|
|
|
write!(f, ".{:06}", nano / 1_000)
|
2014-07-29 07:14:46 +00:00
|
|
|
} else {
|
2014-07-31 02:03:32 +00:00
|
|
|
write!(f, ".{:09}", nano)
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-07 18:04:39 +00:00
|
|
|
/// The `Display` output of the naive time `t` is same to
|
2017-06-21 12:58:42 +00:00
|
|
|
/// [`t.format("%H:%M:%S%.f")`](../format/strftime/index.html).
|
2016-08-07 18:04:39 +00:00
|
|
|
///
|
|
|
|
/// The string printed can be readily parsed via the `parse` method on `str`.
|
|
|
|
///
|
|
|
|
/// It should be noted that, for leap seconds not on the minute boundary,
|
|
|
|
/// it may print a representation not distinguishable from non-leap seconds.
|
|
|
|
/// This doesn't matter in practice, since such leap seconds never happened.
|
|
|
|
/// (By the time of the first leap second on 1972-06-30,
|
|
|
|
/// every time zone offset around the world has standardized to the 5-minute alignment.)
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
|
|
|
/// assert_eq!(format!("{}", NaiveTime::from_hms(23, 56, 4)), "23:56:04");
|
|
|
|
/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012");
|
|
|
|
/// assert_eq!(format!("{}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234");
|
|
|
|
/// assert_eq!(format!("{}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456");
|
|
|
|
/// ~~~~
|
|
|
|
///
|
|
|
|
/// Leap seconds may also be used.
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// # use chrono::NaiveTime;
|
|
|
|
/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500");
|
|
|
|
/// ~~~~
|
2015-01-24 08:45:12 +00:00
|
|
|
impl fmt::Display for NaiveTime {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) }
|
2015-01-09 18:27:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-07 18:04:39 +00:00
|
|
|
/// Parsing a `str` into a `NaiveTime` uses the same format,
|
2017-06-21 12:58:42 +00:00
|
|
|
/// [`%H:%M:%S%.f`](../format/strftime/index.html), as in `Debug` and `Display`.
|
2016-08-07 18:04:39 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~~
|
|
|
|
/// use chrono::NaiveTime;
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms(23, 56, 4);
|
|
|
|
/// assert_eq!("23:56:04".parse::<NaiveTime>(), Ok(t));
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678);
|
|
|
|
/// assert_eq!("23:56:4.012345678".parse::<NaiveTime>(), Ok(t));
|
|
|
|
///
|
|
|
|
/// let t = NaiveTime::from_hms_nano(23, 59, 59, 1_234_567_890); // leap second
|
|
|
|
/// assert_eq!("23:59:60.23456789".parse::<NaiveTime>(), Ok(t));
|
|
|
|
///
|
|
|
|
/// assert!("foo".parse::<NaiveTime>().is_err());
|
|
|
|
/// ~~~~
|
2015-02-18 14:27:12 +00:00
|
|
|
impl str::FromStr for NaiveTime {
|
|
|
|
type Err = ParseError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> ParseResult<NaiveTime> {
|
|
|
|
const ITEMS: &'static [Item<'static>] = &[
|
|
|
|
Item::Space(""), Item::Numeric(Numeric::Hour, Pad::Zero),
|
|
|
|
Item::Space(""), Item::Literal(":"),
|
|
|
|
Item::Space(""), Item::Numeric(Numeric::Minute, Pad::Zero),
|
|
|
|
Item::Space(""), Item::Literal(":"),
|
|
|
|
Item::Space(""), Item::Numeric(Numeric::Second, Pad::Zero),
|
|
|
|
Item::Fixed(Fixed::Nanosecond), Item::Space(""),
|
|
|
|
];
|
|
|
|
|
|
|
|
let mut parsed = Parsed::new();
|
|
|
|
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
|
|
|
parsed.to_naive_time()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-06 18:08:01 +00:00
|
|
|
#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
|
|
|
|
fn test_encodable_json<F, E>(to_string: F)
|
|
|
|
where F: Fn(&NaiveTime) -> Result<String, E>, E: ::std::fmt::Debug
|
|
|
|
{
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms(0, 0, 0)).ok(),
|
|
|
|
Some(r#""00:00:00""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms_milli(0, 0, 0, 950)).ok(),
|
|
|
|
Some(r#""00:00:00.950""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms_milli(0, 0, 59, 1_000)).ok(),
|
|
|
|
Some(r#""00:00:60""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms(0, 1, 2)).ok(),
|
|
|
|
Some(r#""00:01:02""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms_nano(3, 5, 7, 98765432)).ok(),
|
|
|
|
Some(r#""03:05:07.098765432""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms(7, 8, 9)).ok(),
|
|
|
|
Some(r#""07:08:09""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms_micro(12, 34, 56, 789)).ok(),
|
|
|
|
Some(r#""12:34:56.000789""#.into()));
|
|
|
|
assert_eq!(to_string(&NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)).ok(),
|
|
|
|
Some(r#""23:59:60.999999999""#.into()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
|
|
|
|
fn test_decodable_json<F, E>(from_str: F)
|
2017-04-23 21:17:37 +00:00
|
|
|
where F: Fn(&str) -> Result<NaiveTime, E>, E: ::std::fmt::Debug
|
2017-02-06 18:08:01 +00:00
|
|
|
{
|
|
|
|
assert_eq!(from_str(r#""00:00:00""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms(0, 0, 0)));
|
|
|
|
assert_eq!(from_str(r#""0:0:0""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms(0, 0, 0)));
|
|
|
|
assert_eq!(from_str(r#""00:00:00.950""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_milli(0, 0, 0, 950)));
|
|
|
|
assert_eq!(from_str(r#""0:0:0.95""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_milli(0, 0, 0, 950)));
|
|
|
|
assert_eq!(from_str(r#""00:00:60""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_milli(0, 0, 59, 1_000)));
|
|
|
|
assert_eq!(from_str(r#""00:01:02""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms(0, 1, 2)));
|
|
|
|
assert_eq!(from_str(r#""03:05:07.098765432""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 98765432)));
|
|
|
|
assert_eq!(from_str(r#""07:08:09""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms(7, 8, 9)));
|
|
|
|
assert_eq!(from_str(r#""12:34:56.000789""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_micro(12, 34, 56, 789)));
|
|
|
|
assert_eq!(from_str(r#""23:59:60.999999999""#).ok(),
|
|
|
|
Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)));
|
|
|
|
assert_eq!(from_str(r#""23:59:60.9999999999997""#).ok(), // excess digits are ignored
|
|
|
|
Some(NaiveTime::from_hms_nano(23, 59, 59, 1_999_999_999)));
|
|
|
|
|
|
|
|
// bad formats
|
|
|
|
assert!(from_str(r#""""#).is_err());
|
|
|
|
assert!(from_str(r#""000000""#).is_err());
|
|
|
|
assert!(from_str(r#""00:00:61""#).is_err());
|
|
|
|
assert!(from_str(r#""00:60:00""#).is_err());
|
|
|
|
assert!(from_str(r#""24:00:00""#).is_err());
|
|
|
|
assert!(from_str(r#""23:59:59,1""#).is_err());
|
|
|
|
assert!(from_str(r#""012:34:56""#).is_err());
|
|
|
|
assert!(from_str(r#""hh:mm:ss""#).is_err());
|
|
|
|
assert!(from_str(r#"0"#).is_err());
|
|
|
|
assert!(from_str(r#"86399"#).is_err());
|
|
|
|
assert!(from_str(r#"{}"#).is_err());
|
|
|
|
// pre-0.3.0 rustc-serialize format is now invalid
|
|
|
|
assert!(from_str(r#"{"secs":0,"frac":0}"#).is_err());
|
|
|
|
assert!(from_str(r#"null"#).is_err());
|
|
|
|
}
|
|
|
|
|
2016-08-03 18:22:12 +00:00
|
|
|
#[cfg(feature = "rustc-serialize")]
|
|
|
|
mod rustc_serialize {
|
|
|
|
use super::NaiveTime;
|
|
|
|
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
|
|
|
|
|
|
|
impl Encodable for NaiveTime {
|
|
|
|
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
2017-02-06 18:08:01 +00:00
|
|
|
format!("{:?}", self).encode(s)
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for NaiveTime {
|
|
|
|
fn decode<D: Decoder>(d: &mut D) -> Result<NaiveTime, D::Error> {
|
2017-02-06 18:08:01 +00:00
|
|
|
d.read_str()?.parse().map_err(|_| d.error("invalid time"))
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-06 18:08:01 +00:00
|
|
|
#[cfg(test)] use rustc_serialize::json;
|
|
|
|
|
2016-08-03 18:22:12 +00:00
|
|
|
#[test]
|
|
|
|
fn test_encodable() {
|
2017-02-06 18:08:01 +00:00
|
|
|
super::test_encodable_json(json::encode);
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_decodable() {
|
2017-02-06 18:08:01 +00:00
|
|
|
super::test_decodable_json(json::decode);
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 18:49:41 +00:00
|
|
|
#[cfg(feature = "serde")]
|
2015-11-09 14:26:36 +00:00
|
|
|
mod serde {
|
2019-09-07 10:12:49 +00:00
|
|
|
use core::fmt;
|
2019-09-16 00:45:49 +00:00
|
|
|
#[cfg(feature = "alloc")]
|
2019-09-07 10:12:49 +00:00
|
|
|
use alloc::format;
|
2015-11-09 14:26:36 +00:00
|
|
|
use super::NaiveTime;
|
2017-06-21 05:03:49 +00:00
|
|
|
use serdelib::{ser, de};
|
2015-11-09 14:26:36 +00:00
|
|
|
|
2016-08-03 18:22:12 +00:00
|
|
|
// TODO not very optimized for space (binary formats would want something better)
|
|
|
|
// TODO round-trip for general leap seconds (not just those with second = 60)
|
|
|
|
|
2015-11-09 14:26:36 +00:00
|
|
|
impl ser::Serialize for NaiveTime {
|
2017-01-28 05:19:12 +00:00
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
2015-11-09 14:26:36 +00:00
|
|
|
where S: ser::Serializer
|
|
|
|
{
|
2017-04-21 11:31:50 +00:00
|
|
|
serializer.collect_str(&self)
|
2015-11-09 14:26:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-03 18:22:12 +00:00
|
|
|
|
2015-11-09 14:26:36 +00:00
|
|
|
struct NaiveTimeVisitor;
|
2016-08-03 18:22:12 +00:00
|
|
|
|
2017-04-21 11:12:26 +00:00
|
|
|
impl<'de> de::Visitor<'de> for NaiveTimeVisitor {
|
2015-11-09 14:26:36 +00:00
|
|
|
type Value = NaiveTime;
|
|
|
|
|
2019-09-07 10:12:49 +00:00
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
|
2017-01-28 05:19:12 +00:00
|
|
|
{
|
|
|
|
write!(formatter, "a formatted time string")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_str<E>(self, value: &str) -> Result<NaiveTime, E>
|
2015-11-09 14:26:36 +00:00
|
|
|
where E: de::Error
|
|
|
|
{
|
2016-03-03 07:54:47 +00:00
|
|
|
value.parse().map_err(|err| E::custom(format!("{}", err)))
|
2015-11-09 14:26:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-03 18:22:12 +00:00
|
|
|
|
2017-04-21 11:12:26 +00:00
|
|
|
impl<'de> de::Deserialize<'de> for NaiveTime {
|
2017-01-28 05:19:12 +00:00
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
2017-04-21 11:12:26 +00:00
|
|
|
where D: de::Deserializer<'de>
|
2015-11-09 14:26:36 +00:00
|
|
|
{
|
2016-08-16 06:54:11 +00:00
|
|
|
deserializer.deserialize_str(NaiveTimeVisitor)
|
2015-11-09 14:26:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-03 18:22:12 +00:00
|
|
|
|
|
|
|
#[cfg(test)] extern crate serde_json;
|
2016-08-16 22:08:08 +00:00
|
|
|
#[cfg(test)] extern crate bincode;
|
2016-08-03 18:22:12 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serde_serialize() {
|
2017-02-06 18:08:01 +00:00
|
|
|
super::test_encodable_json(self::serde_json::to_string);
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serde_deserialize() {
|
2017-04-21 11:12:26 +00:00
|
|
|
super::test_decodable_json(|input| self::serde_json::from_str(&input));
|
2016-08-03 18:22:12 +00:00
|
|
|
}
|
2016-08-16 22:08:08 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serde_bincode() {
|
|
|
|
// Bincode is relevant to test separately from JSON because
|
|
|
|
// it is not self-describing.
|
2017-04-18 15:34:10 +00:00
|
|
|
use self::bincode::{Infinite, serialize, deserialize};
|
2016-08-16 22:08:08 +00:00
|
|
|
|
|
|
|
let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432);
|
2017-04-18 15:34:10 +00:00
|
|
|
let encoded = serialize(&t, Infinite).unwrap();
|
2016-08-16 22:08:08 +00:00
|
|
|
let decoded: NaiveTime = deserialize(&encoded).unwrap();
|
|
|
|
assert_eq!(t, decoded);
|
|
|
|
}
|
2015-11-09 14:26:36 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 07:14:46 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::NaiveTime;
|
|
|
|
use Timelike;
|
|
|
|
use std::u32;
|
2017-02-05 23:17:01 +00:00
|
|
|
use oldtime::Duration;
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_from_hms_milli() {
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 0),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 0)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 777),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 777_000_000)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 1_999),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_000_000)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 2_000), None);
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, 5_000), None); // overflow check
|
|
|
|
assert_eq!(NaiveTime::from_hms_milli_opt(3, 5, 7, u32::MAX), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_from_hms_micro() {
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 0),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 0)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 333),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 333_000)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 777_777),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 777_777_000)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 1_999_999),
|
|
|
|
Some(NaiveTime::from_hms_nano(3, 5, 7, 1_999_999_000)));
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 2_000_000), None);
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, 5_000_000), None); // overflow check
|
|
|
|
assert_eq!(NaiveTime::from_hms_micro_opt(3, 5, 7, u32::MAX), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_hms() {
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).hour(), 3);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(0),
|
|
|
|
Some(NaiveTime::from_hms(0, 5, 7)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(23),
|
|
|
|
Some(NaiveTime::from_hms(23, 5, 7)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(24), None);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_hour(u32::MAX), None);
|
|
|
|
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).minute(), 5);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(0),
|
|
|
|
Some(NaiveTime::from_hms(3, 0, 7)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(59),
|
|
|
|
Some(NaiveTime::from_hms(3, 59, 7)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(60), None);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_minute(u32::MAX), None);
|
|
|
|
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).second(), 7);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(0),
|
|
|
|
Some(NaiveTime::from_hms(3, 5, 0)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(59),
|
|
|
|
Some(NaiveTime::from_hms(3, 5, 59)));
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(60), None);
|
|
|
|
assert_eq!(NaiveTime::from_hms(3, 5, 7).with_second(u32::MAX), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_add() {
|
2016-08-06 17:32:09 +00:00
|
|
|
macro_rules! check {
|
|
|
|
($lhs:expr, $rhs:expr, $sum:expr) => ({
|
|
|
|
assert_eq!($lhs + $rhs, $sum);
|
|
|
|
//assert_eq!($rhs + $lhs, $sum);
|
|
|
|
})
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 11:50:03 +00:00
|
|
|
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
|
2014-07-29 07:14:46 +00:00
|
|
|
|
2016-08-06 17:32:09 +00:00
|
|
|
check!(hmsm(3, 5, 7, 900), Duration::zero(), hmsm(3, 5, 7, 900));
|
|
|
|
check!(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0));
|
2016-08-16 15:40:36 +00:00
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-1800), hmsm(3, 5, 6, 500));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-800), hmsm(3, 5, 7, 500));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(-100), hmsm(3, 5, 7, 1_200));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(100), hmsm(3, 5, 7, 1_400));
|
2016-08-06 17:32:09 +00:00
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::milliseconds(1800), hmsm(3, 5, 9, 100));
|
|
|
|
check!(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap
|
|
|
|
check!(hmsm(3, 5, 7, 900), Duration::seconds(-86399), hmsm(3, 5, 8, 900));
|
|
|
|
check!(hmsm(3, 5, 7, 900), Duration::days(12345), hmsm(3, 5, 7, 900));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::days(1), hmsm(3, 5, 7, 300));
|
|
|
|
check!(hmsm(3, 5, 7, 1_300), Duration::days(-1), hmsm(3, 5, 8, 300));
|
2015-05-14 17:06:34 +00:00
|
|
|
|
|
|
|
// regression tests for #37
|
2016-08-06 17:32:09 +00:00
|
|
|
check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-990), hmsm(23, 59, 59, 10));
|
|
|
|
check!(hmsm(0, 0, 0, 0), Duration::milliseconds(-9990), hmsm(23, 59, 50, 10));
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
|
2016-08-16 15:40:36 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_overflowing_add() {
|
|
|
|
let hmsm = NaiveTime::from_hms_milli;
|
|
|
|
|
2017-02-05 23:17:01 +00:00
|
|
|
assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(11)),
|
2016-08-16 15:40:36 +00:00
|
|
|
(hmsm(14, 4, 5, 678), 0));
|
2017-02-05 23:17:01 +00:00
|
|
|
assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(23)),
|
2017-10-08 21:38:41 +00:00
|
|
|
(hmsm(2, 4, 5, 678), 86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
assert_eq!(hmsm(3, 4, 5, 678).overflowing_add_signed(Duration::hours(-7)),
|
2017-10-08 21:38:41 +00:00
|
|
|
(hmsm(20, 4, 5, 678), -86_400));
|
2016-08-16 15:40:36 +00:00
|
|
|
|
2017-02-05 23:17:01 +00:00
|
|
|
// overflowing_add_signed with leap seconds may be counter-intuitive
|
|
|
|
assert_eq!(hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(1)),
|
2017-10-08 21:38:41 +00:00
|
|
|
(hmsm(3, 4, 5, 678), 86_400));
|
2017-02-05 23:17:01 +00:00
|
|
|
assert_eq!(hmsm(3, 4, 5, 1_678).overflowing_add_signed(Duration::days(-1)),
|
2017-10-08 21:38:41 +00:00
|
|
|
(hmsm(3, 4, 6, 678), -86_400));
|
2016-08-16 15:40:36 +00:00
|
|
|
}
|
|
|
|
|
2016-10-02 13:38:06 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_addassignment() {
|
|
|
|
let hms = NaiveTime::from_hms;
|
|
|
|
let mut time = hms(12, 12, 12);
|
|
|
|
time += Duration::hours(10);
|
|
|
|
assert_eq!(time, hms(22, 12, 12));
|
|
|
|
time += Duration::hours(10);
|
|
|
|
assert_eq!(time, hms(8, 12, 12));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_subassignment() {
|
|
|
|
let hms = NaiveTime::from_hms;
|
|
|
|
let mut time = hms(12, 12, 12);
|
|
|
|
time -= Duration::hours(10);
|
|
|
|
assert_eq!(time, hms(2, 12, 12));
|
|
|
|
time -= Duration::hours(10);
|
|
|
|
assert_eq!(time, hms(16, 12, 12));
|
|
|
|
}
|
|
|
|
|
2014-07-29 07:14:46 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_sub() {
|
2016-08-06 17:32:09 +00:00
|
|
|
macro_rules! check {
|
|
|
|
($lhs:expr, $rhs:expr, $diff:expr) => ({
|
|
|
|
// `time1 - time2 = duration` is equivalent to `time2 - time1 = -duration`
|
2017-02-05 23:17:01 +00:00
|
|
|
assert_eq!($lhs.signed_duration_since($rhs), $diff);
|
|
|
|
assert_eq!($rhs.signed_duration_since($lhs), -$diff);
|
2016-08-06 17:32:09 +00:00
|
|
|
})
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 11:50:03 +00:00
|
|
|
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
|
2014-07-29 07:14:46 +00:00
|
|
|
|
2016-08-06 17:32:09 +00:00
|
|
|
check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Duration::zero());
|
|
|
|
check!(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300));
|
|
|
|
check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1));
|
|
|
|
check!(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 300),
|
|
|
|
Duration::seconds(3600 + 60) + Duration::milliseconds(900));
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
// treats the leap second as if it coincides with the prior non-leap second,
|
|
|
|
// as required by `time1 - time2 = duration` and `time2 - time1 = -duration` equivalence.
|
2016-08-06 17:32:09 +00:00
|
|
|
check!(hmsm(3, 5, 7, 200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(400));
|
|
|
|
check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 1_800), Duration::milliseconds(1400));
|
|
|
|
check!(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 800), Duration::milliseconds(1400));
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
// additional equality: `time1 + duration = time2` is equivalent to
|
|
|
|
// `time2 - time1 = duration` IF AND ONLY IF `time2` represents a non-leap second.
|
|
|
|
assert_eq!(hmsm(3, 5, 6, 800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200));
|
|
|
|
assert_eq!(hmsm(3, 5, 6, 1_800) + Duration::milliseconds(400), hmsm(3, 5, 7, 200));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_fmt() {
|
2015-01-09 18:27:24 +00:00
|
|
|
assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 999)), "23:59:59.999");
|
|
|
|
assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_000)), "23:59:60");
|
|
|
|
assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 59, 59, 1_001)), "23:59:60.001");
|
|
|
|
assert_eq!(format!("{}", NaiveTime::from_hms_micro(0, 0, 0, 43210)), "00:00:00.043210");
|
|
|
|
assert_eq!(format!("{}", NaiveTime::from_hms_nano(0, 0, 0, 6543210)), "00:00:00.006543210");
|
2014-07-29 07:14:46 +00:00
|
|
|
|
|
|
|
// the format specifier should have no effect on `NaiveTime`
|
2015-01-09 18:27:24 +00:00
|
|
|
assert_eq!(format!("{:30}", NaiveTime::from_hms_milli(3, 5, 7, 9)), "03:05:07.009");
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
2014-07-31 19:08:19 +00:00
|
|
|
|
2015-02-18 14:27:12 +00:00
|
|
|
#[test]
|
|
|
|
fn test_date_from_str() {
|
|
|
|
// valid cases
|
|
|
|
let valid = [
|
|
|
|
"0:0:0",
|
|
|
|
"0:0:0.0000000",
|
|
|
|
"0:0:0.0000003",
|
|
|
|
" 4 : 3 : 2.1 ",
|
|
|
|
" 09:08:07 ",
|
|
|
|
" 9:8:07 ",
|
|
|
|
"23:59:60.373929310237",
|
|
|
|
];
|
|
|
|
for &s in &valid {
|
|
|
|
let d = match s.parse::<NaiveTime>() {
|
|
|
|
Ok(d) => d,
|
|
|
|
Err(e) => panic!("parsing `{}` has failed: {}", s, e)
|
|
|
|
};
|
|
|
|
let s_ = format!("{:?}", d);
|
|
|
|
// `s` and `s_` may differ, but `s.parse()` and `s_.parse()` must be same
|
|
|
|
let d_ = match s_.parse::<NaiveTime>() {
|
|
|
|
Ok(d) => d,
|
|
|
|
Err(e) => panic!("`{}` is parsed into `{:?}`, but reparsing that has failed: {}",
|
|
|
|
s, d, e)
|
|
|
|
};
|
|
|
|
assert!(d == d_, "`{}` is parsed into `{:?}`, but reparsed result \
|
|
|
|
`{:?}` does not match", s, d, d_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// some invalid cases
|
|
|
|
// since `ParseErrorKind` is private, all we can do is to check if there was an error
|
|
|
|
assert!("".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("x".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("15".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("15:8".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("15:8:x".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("15:8:9x".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("23:59:61".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("12:34:56.x".parse::<NaiveTime>().is_err());
|
|
|
|
assert!("12:34:56. 0".parse::<NaiveTime>().is_err());
|
|
|
|
}
|
|
|
|
|
2015-02-04 17:16:35 +00:00
|
|
|
#[test]
|
2015-02-15 12:26:11 +00:00
|
|
|
fn test_time_parse_from_str() {
|
2015-03-02 11:50:03 +00:00
|
|
|
let hms = |h,m,s| NaiveTime::from_hms(h,m,s);
|
2015-02-15 12:26:11 +00:00
|
|
|
assert_eq!(NaiveTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
|
2015-02-04 17:16:35 +00:00
|
|
|
Ok(hms(12, 34, 56))); // ignore date and offset
|
2015-02-15 12:26:11 +00:00
|
|
|
assert_eq!(NaiveTime::parse_from_str("PM 12:59", "%P %H:%M"),
|
2015-02-04 17:16:35 +00:00
|
|
|
Ok(hms(12, 59, 0)));
|
2015-02-15 12:26:11 +00:00
|
|
|
assert!(NaiveTime::parse_from_str("12:3456", "%H:%M:%S").is_err());
|
2015-02-04 17:16:35 +00:00
|
|
|
}
|
|
|
|
|
2014-07-31 19:08:19 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_format() {
|
|
|
|
let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432);
|
2015-01-09 18:27:24 +00:00
|
|
|
assert_eq!(t.format("%H,%k,%I,%l,%P,%p").to_string(), "03, 3,03, 3,am,AM");
|
|
|
|
assert_eq!(t.format("%M").to_string(), "05");
|
2016-04-21 15:47:01 +00:00
|
|
|
assert_eq!(t.format("%S,%f,%.f").to_string(), "07,098765432,.098765432");
|
|
|
|
assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".098,.098765,.098765432");
|
2015-01-09 18:27:24 +00:00
|
|
|
assert_eq!(t.format("%R").to_string(), "03:05");
|
|
|
|
assert_eq!(t.format("%T,%X").to_string(), "03:05:07,03:05:07");
|
|
|
|
assert_eq!(t.format("%r").to_string(), "03:05:07 AM");
|
|
|
|
assert_eq!(t.format("%t%n%%%n%t").to_string(), "\t\n%\n\t");
|
2014-07-31 19:08:19 +00:00
|
|
|
|
2016-04-21 15:47:01 +00:00
|
|
|
let t = NaiveTime::from_hms_micro(3, 5, 7, 432100);
|
|
|
|
assert_eq!(t.format("%S,%f,%.f").to_string(), "07,432100000,.432100");
|
|
|
|
assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".432,.432100,.432100000");
|
|
|
|
|
|
|
|
let t = NaiveTime::from_hms_milli(3, 5, 7, 210);
|
|
|
|
assert_eq!(t.format("%S,%f,%.f").to_string(), "07,210000000,.210");
|
|
|
|
assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".210,.210000,.210000000");
|
|
|
|
|
|
|
|
let t = NaiveTime::from_hms(3, 5, 7);
|
|
|
|
assert_eq!(t.format("%S,%f,%.f").to_string(), "07,000000000,");
|
|
|
|
assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".000,.000000,.000000000");
|
|
|
|
|
2014-07-31 19:08:19 +00:00
|
|
|
// corner cases
|
2015-01-09 18:27:24 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms(13, 57, 9).format("%r").to_string(), "01:57:09 PM");
|
2015-01-26 12:14:50 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).format("%X").to_string(),
|
|
|
|
"23:59:60");
|
2014-07-31 19:08:19 +00:00
|
|
|
}
|
2014-07-29 07:14:46 +00:00
|
|
|
}
|
|
|
|
|