2014-04-01 17:14:57 +00:00
|
|
|
// This is a part of rust-chrono.
|
|
|
|
// Copyright (c) 2014, Kang Seonghoon.
|
|
|
|
// See README.md and LICENSE.txt for details.
|
|
|
|
|
2014-03-28 11:38:11 +00:00
|
|
|
/*!
|
|
|
|
* ISO 8601 time.
|
|
|
|
*/
|
|
|
|
|
2014-07-29 06:41:07 +00:00
|
|
|
use std::{fmt, hash};
|
2014-03-31 05:33:47 +00:00
|
|
|
use num::Integer;
|
2014-07-29 06:41:07 +00:00
|
|
|
use offset::Offset;
|
2014-03-29 15:12:50 +00:00
|
|
|
use duration::Duration;
|
2014-03-28 11:38:11 +00:00
|
|
|
|
2014-07-25 09:12:51 +00:00
|
|
|
/// The common set of methods for time component.
|
2014-03-28 12:56:38 +00:00
|
|
|
pub trait Timelike {
|
|
|
|
/// Returns the hour number from 0 to 23.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn hour(&self) -> u32;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Returns the hour number from 1 to 12 with a boolean flag,
|
|
|
|
/// which is false for AM and true for PM.
|
|
|
|
#[inline]
|
2014-07-19 17:00:33 +00:00
|
|
|
fn hour12(&self) -> (bool, u32) {
|
2014-03-28 12:56:38 +00:00
|
|
|
let hour = self.hour();
|
|
|
|
let mut hour12 = hour % 12;
|
|
|
|
if hour12 == 0 { hour12 = 12; }
|
|
|
|
(hour >= 12, hour12)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the minute number from 0 to 59.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn minute(&self) -> u32;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Returns the second number from 0 to 59.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn second(&self) -> u32;
|
2014-03-28 12:56:38 +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 the leap second.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn nanosecond(&self) -> u32;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Makes a new value with the hour number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting value would be invalid.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn with_hour(&self, hour: u32) -> Option<Self>;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Makes a new value with the minute number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting value would be invalid.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn with_minute(&self, min: u32) -> Option<Self>;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Makes a new value with the second number changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting value would be invalid.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn with_second(&self, sec: u32) -> Option<Self>;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Makes a new value with nanoseconds since the whole non-leap second changed.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the resulting value would be invalid.
|
2014-07-19 17:00:33 +00:00
|
|
|
fn with_nanosecond(&self, nano: u32) -> Option<Self>;
|
2014-03-28 12:56:38 +00:00
|
|
|
|
|
|
|
/// Returns the number of non-leap seconds past the last midnight.
|
|
|
|
#[inline]
|
2014-07-25 12:00:32 +00:00
|
|
|
fn num_seconds_from_midnight(&self) -> u32 {
|
2014-03-28 12:56:38 +00:00
|
|
|
self.hour() * 3600 + self.minute() * 60 + self.second()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ISO 8601 time without timezone.
|
|
|
|
/// Allows for the nanosecond precision and optional leap second representation.
|
2014-07-29 06:33:46 +00:00
|
|
|
#[deriving(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub struct NaiveTime {
|
2014-07-28 16:05:30 +00:00
|
|
|
secs: u32,
|
2014-04-01 16:30:52 +00:00
|
|
|
frac: u32,
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
impl NaiveTime {
|
|
|
|
/// Makes a new `NaiveTime` from hour, minute and second.
|
2014-07-19 17:51:57 +00:00
|
|
|
///
|
|
|
|
/// Fails on invalid hour, minute and/or second.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTime {
|
|
|
|
NaiveTime::from_hms_opt(hour, min, sec).expect("invalid time")
|
2014-07-19 17:51:57 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute and second.
|
2014-03-28 11:38:11 +00:00
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute and/or second.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> {
|
|
|
|
NaiveTime::from_hms_nano_opt(hour, min, sec, 0)
|
2014-07-19 17:51:57 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and millisecond.
|
2014-07-19 17:51:57 +00:00
|
|
|
/// The millisecond part can exceed 1,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Fails on invalid hour, minute, second and/or millisecond.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
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")
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and millisecond.
|
2014-03-28 11:38:11 +00:00
|
|
|
/// The millisecond part can exceed 1,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or millisecond.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> {
|
|
|
|
milli.checked_mul(&1_000_000)
|
|
|
|
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
|
2014-07-19 17:51:57 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and microsecond.
|
2014-07-19 17:51:57 +00:00
|
|
|
/// The microsecond part can exceed 1,000,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Fails on invalid hour, minute, second and/or microsecond.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
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")
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and microsecond.
|
2014-03-28 11:38:11 +00:00
|
|
|
/// The microsecond part can exceed 1,000,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or microsecond.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> {
|
|
|
|
micro.checked_mul(&1_000)
|
|
|
|
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
|
2014-07-19 17:51:57 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
|
2014-07-19 17:51:57 +00:00
|
|
|
/// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Fails on invalid hour, minute, second and/or nanosecond.
|
2014-07-28 16:05:30 +00:00
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
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")
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
/// Makes a new `NaiveTime` from hour, minute, second and nanosecond.
|
2014-03-28 11:38:11 +00:00
|
|
|
/// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second.
|
|
|
|
///
|
|
|
|
/// Returns `None` on invalid hour, minute, second and/or nanosecond.
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> {
|
2014-03-28 11:38:11 +00:00
|
|
|
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; }
|
2014-07-28 16:05:30 +00:00
|
|
|
let secs = hour * 3600 + min * 60 + sec;
|
2014-07-29 06:55:40 +00:00
|
|
|
Some(NaiveTime { secs: secs, frac: nano })
|
2014-07-28 16:05:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a triple of the hour, minute and second numbers.
|
|
|
|
fn hms(&self) -> (u32, u32, u32) {
|
|
|
|
let (mins, sec) = self.secs.div_mod_floor(&60);
|
|
|
|
let (hour, min) = mins.div_mod_floor(&60);
|
|
|
|
(hour, min, sec)
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
2014-03-28 12:56:38 +00:00
|
|
|
}
|
2014-03-28 11:38:11 +00:00
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
impl Timelike for NaiveTime {
|
2014-07-28 16:05:30 +00:00
|
|
|
#[inline] fn hour(&self) -> u32 { self.hms().val0() }
|
|
|
|
#[inline] fn minute(&self) -> u32 { self.hms().val1() }
|
|
|
|
#[inline] fn second(&self) -> u32 { self.hms().val2() }
|
|
|
|
#[inline] fn nanosecond(&self) -> u32 { self.frac }
|
2014-03-28 11:38:11 +00:00
|
|
|
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
fn with_hour(&self, hour: u32) -> Option<NaiveTime> {
|
2014-03-28 11:38:11 +00:00
|
|
|
if hour >= 24 { return None; }
|
2014-07-28 16:05:30 +00:00
|
|
|
let secs = hour * 3600 + self.secs % 3600;
|
2014-07-29 06:55:40 +00:00
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
fn with_minute(&self, min: u32) -> Option<NaiveTime> {
|
2014-03-28 11:38:11 +00:00
|
|
|
if min >= 60 { return None; }
|
2014-07-28 16:05:30 +00:00
|
|
|
let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60;
|
2014-07-29 06:55:40 +00:00
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
fn with_second(&self, sec: u32) -> Option<NaiveTime> {
|
2014-03-28 11:38:11 +00:00
|
|
|
if sec >= 60 { return None; }
|
2014-07-28 16:05:30 +00:00
|
|
|
let secs = self.secs / 60 * 60 + sec;
|
2014-07-29 06:55:40 +00:00
|
|
|
Some(NaiveTime { secs: secs, ..*self })
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
fn with_nanosecond(&self, nano: u32) -> Option<NaiveTime> {
|
2014-03-28 11:38:11 +00:00
|
|
|
if nano >= 2_000_000_000 { return None; }
|
2014-07-29 06:55:40 +00:00
|
|
|
Some(NaiveTime { frac: nano, ..*self })
|
2014-07-28 16:05:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn num_seconds_from_midnight(&self) -> u32 {
|
|
|
|
self.secs // do not repeat the calculation!
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
impl Add<Duration,NaiveTime> for NaiveTime {
|
|
|
|
fn add(&self, rhs: &Duration) -> NaiveTime {
|
2014-07-25 12:00:32 +00:00
|
|
|
let (_, rhssecs, rhsnanos) = rhs.to_tuple();
|
2014-07-28 16:05:30 +00:00
|
|
|
let mut secs = self.secs + rhssecs;
|
2014-07-25 12:00:32 +00:00
|
|
|
let mut nanos = self.frac + rhsnanos;
|
2014-03-29 15:12:50 +00:00
|
|
|
|
|
|
|
// always ignore leap seconds after the current whole second
|
|
|
|
let maxnanos = if self.frac >= 1_000_000_000 {2_000_000_000} else {1_000_000_000};
|
|
|
|
|
|
|
|
if nanos >= maxnanos {
|
|
|
|
nanos -= maxnanos;
|
|
|
|
secs += 1;
|
|
|
|
}
|
2014-07-29 06:55:40 +00:00
|
|
|
NaiveTime { secs: secs % 86400, frac: nanos }
|
2014-03-29 15:12:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
|
2014-07-29 06:55:40 +00:00
|
|
|
impl Add<NaiveTime,NaiveTime> for Duration {
|
2014-03-29 15:12:50 +00:00
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
fn add(&self, rhs: &NaiveTime) -> NaiveTime { rhs.add(self) }
|
2014-03-29 15:12:50 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
impl Sub<NaiveTime,Duration> for NaiveTime {
|
|
|
|
fn sub(&self, rhs: &NaiveTime) -> Duration {
|
2014-03-29 15:12:50 +00:00
|
|
|
// the number of whole non-leap seconds
|
2014-07-28 16:05:30 +00:00
|
|
|
let secs = self.secs as i32 - rhs.secs as i32 - 1;
|
2014-03-29 15:12:50 +00:00
|
|
|
|
|
|
|
// the fractional second from the rhs to the next non-leap second
|
|
|
|
let maxnanos = if rhs.frac >= 1_000_000_000 {2_000_000_000} else {1_000_000_000};
|
|
|
|
let nanos1 = maxnanos - rhs.frac;
|
|
|
|
|
|
|
|
// the fractional second from the last leap or non-leap second to the lhs
|
|
|
|
let lastfrac = if self.frac >= 1_000_000_000 {1_000_000_000} else {0};
|
|
|
|
let nanos2 = self.frac - lastfrac;
|
|
|
|
|
2014-07-19 17:00:33 +00:00
|
|
|
Duration::seconds(secs) + Duration::nanoseconds(nanos1 as i32 + nanos2 as i32)
|
2014-03-29 15:12:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
impl fmt::Show for NaiveTime {
|
2014-03-28 11:38:11 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2014-07-28 16:05:30 +00:00
|
|
|
let (hour, min, sec) = self.hms();
|
2014-03-28 11:38:11 +00:00
|
|
|
let (sec, nano) = if self.frac >= 1_000_000_000 {
|
2014-07-28 16:05:30 +00:00
|
|
|
(sec + 1, self.frac - 1_000_000_000)
|
2014-03-28 11:38:11 +00:00
|
|
|
} else {
|
2014-07-28 16:05:30 +00:00
|
|
|
(sec, self.frac)
|
2014-03-28 11:38:11 +00:00
|
|
|
};
|
|
|
|
|
2014-07-28 16:05:30 +00:00
|
|
|
try!(write!(f, "{:02}:{:02}:{:02}", hour, min, sec));
|
2014-03-28 11:38:11 +00:00
|
|
|
if nano == 0 {
|
|
|
|
Ok(())
|
|
|
|
} else if nano % 1_000_000 == 0 {
|
2014-05-23 14:45:12 +00:00
|
|
|
write!(f, ",{:03}", nano / 1_000_000)
|
2014-03-28 11:38:11 +00:00
|
|
|
} else if nano % 1_000 == 0 {
|
2014-05-23 14:45:12 +00:00
|
|
|
write!(f, ",{:06}", nano / 1_000)
|
2014-03-28 11:38:11 +00:00
|
|
|
} else {
|
2014-05-23 14:45:12 +00:00
|
|
|
write!(f, ",{:09}", nano)
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:41:07 +00:00
|
|
|
/// ISO 8601 time with timezone.
|
|
|
|
#[deriving(Clone)]
|
|
|
|
pub struct Time<Off> {
|
2014-07-29 06:55:40 +00:00
|
|
|
time: NaiveTime,
|
2014-07-29 06:41:07 +00:00
|
|
|
offset: Off,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> Time<Off> {
|
|
|
|
/// Makes a new `Time` with given *UTC* time and offset.
|
|
|
|
/// The local time should be constructed via the `Offset` trait.
|
|
|
|
#[inline]
|
2014-07-29 06:55:40 +00:00
|
|
|
pub fn from_utc(time: NaiveTime, offset: Off) -> Time<Off> {
|
2014-07-29 06:41:07 +00:00
|
|
|
Time { time: time, offset: offset }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a view to the local time.
|
2014-07-29 06:55:40 +00:00
|
|
|
fn local(&self) -> NaiveTime {
|
2014-07-29 06:41:07 +00:00
|
|
|
self.offset.to_local_time(&self.time)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> Timelike for Time<Off> {
|
|
|
|
#[inline] fn hour(&self) -> u32 { self.local().hour() }
|
|
|
|
#[inline] fn minute(&self) -> u32 { self.local().minute() }
|
|
|
|
#[inline] fn second(&self) -> u32 { self.local().second() }
|
|
|
|
#[inline] fn nanosecond(&self) -> u32 { self.local().nanosecond() }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn with_hour(&self, hour: u32) -> Option<Time<Off>> {
|
|
|
|
self.local().with_hour(hour)
|
|
|
|
.and_then(|time| self.offset.from_local_time(&time).single())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn with_minute(&self, min: u32) -> Option<Time<Off>> {
|
|
|
|
self.local().with_minute(min)
|
|
|
|
.and_then(|time| self.offset.from_local_time(&time).single())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn with_second(&self, sec: u32) -> Option<Time<Off>> {
|
|
|
|
self.local().with_second(sec)
|
|
|
|
.and_then(|time| self.offset.from_local_time(&time).single())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn with_nanosecond(&self, nano: u32) -> Option<Time<Off>> {
|
|
|
|
self.local().with_nanosecond(nano)
|
|
|
|
.and_then(|time| self.offset.from_local_time(&time).single())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn num_seconds_from_midnight(&self) -> u32 { self.local().num_seconds_from_midnight() }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> PartialEq for Time<Off> {
|
|
|
|
fn eq(&self, other: &Time<Off>) -> bool { self.time == other.time }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> Eq for Time<Off> {
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset, Off2:Offset> Equiv<Time<Off2>> for Time<Off> {
|
|
|
|
fn equiv(&self, other: &Time<Off2>) -> bool { self.time == other.time }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> PartialOrd for Time<Off> {
|
|
|
|
fn partial_cmp(&self, other: &Time<Off>) -> Option<Ordering> {
|
|
|
|
self.time.partial_cmp(&other.time)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> Ord for Time<Off> {
|
|
|
|
fn cmp(&self, other: &Time<Off>) -> Ordering { self.time.cmp(&other.time) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> hash::Hash for Time<Off> {
|
|
|
|
fn hash(&self, state: &mut hash::sip::SipState) { self.time.hash(state) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> Add<Duration,Time<Off>> for Time<Off> {
|
|
|
|
fn add(&self, rhs: &Duration) -> Time<Off> {
|
|
|
|
Time { time: self.time + *rhs, offset: self.offset.clone() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
|
|
|
|
impl<Off:Offset> Add<Time<Off>,Time<Off>> for Duration {
|
|
|
|
#[inline]
|
|
|
|
fn add(&self, rhs: &Time<Off>) -> Time<Off> { rhs.add(self) }
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
impl<Off:Offset, Off2:Offset> Sub<Time<Off2>,Duration> for Time<Off> {
|
|
|
|
fn sub(&self, rhs: &Time<Off2>) -> Duration {
|
|
|
|
self.time - rhs.time
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Off:Offset> fmt::Show for Time<Off> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}{}", self.local(), self.offset)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-28 11:38:11 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-07-29 06:55:40 +00:00
|
|
|
use super::{Timelike, NaiveTime};
|
2014-03-29 15:12:50 +00:00
|
|
|
use duration::Duration;
|
2014-07-19 17:51:57 +00:00
|
|
|
use std::u32;
|
2014-03-29 15:12:50 +00:00
|
|
|
|
2014-07-19 17:51:57 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_from_hms_milli() {
|
2014-07-29 06:55:40 +00:00
|
|
|
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);
|
2014-07-19 17:51:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_from_hms_micro() {
|
2014-07-29 06:55:40 +00:00
|
|
|
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);
|
2014-03-29 15:12:50 +00:00
|
|
|
}
|
|
|
|
|
2014-07-28 16:05:30 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_hms() {
|
2014-07-29 06:55:40 +00:00
|
|
|
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);
|
2014-07-28 16:05:30 +00:00
|
|
|
}
|
|
|
|
|
2014-03-29 15:12:50 +00:00
|
|
|
#[test]
|
|
|
|
fn test_time_add() {
|
2014-07-29 06:55:40 +00:00
|
|
|
fn check(lhs: NaiveTime, rhs: Duration, sum: NaiveTime) {
|
2014-03-29 15:12:50 +00:00
|
|
|
assert_eq!(lhs + rhs, sum);
|
|
|
|
//assert_eq!(rhs + lhs, sum);
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
|
2014-07-19 17:51:57 +00:00
|
|
|
|
2014-03-29 15:12:50 +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));
|
|
|
|
check(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_sub() {
|
2014-07-29 06:55:40 +00:00
|
|
|
fn check(lhs: NaiveTime, rhs: NaiveTime, diff: Duration) {
|
2014-03-29 15:12:50 +00:00
|
|
|
// `time1 - time2 = duration` is equivalent to `time2 - time1 = -duration`
|
|
|
|
assert_eq!(lhs - rhs, diff);
|
|
|
|
assert_eq!(rhs - lhs, -diff);
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
|
2014-07-19 17:51:57 +00:00
|
|
|
|
2014-03-29 15:12:50 +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));
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
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(400));
|
|
|
|
check(hmsm(3, 5, 7, 1_200), hmsm(3, 5, 6, 800), Duration::milliseconds(400));
|
|
|
|
|
|
|
|
// 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));
|
|
|
|
}
|
2014-03-28 11:38:11 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_time_fmt() {
|
2014-07-29 06:55:40 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 999).to_string(),
|
2014-07-19 17:51:57 +00:00
|
|
|
"23:59:59,999".to_string());
|
2014-07-29 06:55:40 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).to_string(),
|
2014-07-19 17:51:57 +00:00
|
|
|
"23:59:60".to_string());
|
2014-07-29 06:55:40 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_001).to_string(),
|
2014-07-19 17:51:57 +00:00
|
|
|
"23:59:60,001".to_string());
|
2014-07-29 06:55:40 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_micro(0, 0, 0, 43210).to_string(),
|
2014-05-29 17:18:27 +00:00
|
|
|
"00:00:00,043210".to_string());
|
2014-07-29 06:55:40 +00:00
|
|
|
assert_eq!(NaiveTime::from_hms_nano(0, 0, 0, 6543210).to_string(),
|
2014-05-29 17:18:27 +00:00
|
|
|
"00:00:00,006543210".to_string());
|
2014-07-25 07:20:39 +00:00
|
|
|
|
2014-07-29 06:55:40 +00:00
|
|
|
// the format specifier should have no effect on `NaiveTime`
|
|
|
|
assert_eq!(format!("{:30}", NaiveTime::from_hms_milli(3, 5, 7, 9)),
|
2014-07-25 07:20:39 +00:00
|
|
|
"03:05:07,009".to_string());
|
2014-03-28 11:38:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|