// This is a part of rust-chrono. // Copyright (c) 2014-2015, Kang Seonghoon. // See README.md and LICENSE.txt for details. /*! * ISO 8601 time with timezone. */ use std::{fmt, hash}; use std::cmp::Ordering; use std::ops::{Add, Sub}; use Timelike; use offset::{Offset, OffsetState}; use duration::Duration; use naive::time::NaiveTime; use format::DelayedFormat; /// ISO 8601 time with timezone. #[derive(Clone)] pub struct Time { time: NaiveTime, offset: Off::State, } impl Time { /// Makes a new `Time` with given *UTC* time and offset. /// The local time should be constructed via the `Offset` trait. // // note: this constructor is purposedly not named to `new` to discourage the direct usage. #[inline] pub fn from_utc(time: NaiveTime, offset: Off::State) -> Time { Time { time: time, offset: offset } } /// Retrieves an associated offset. #[inline] pub fn offset<'a>(&'a self) -> &'a Off::State { &self.offset } /// Retrieves an associated offset. #[inline] pub fn timezone(&self) -> Off { Offset::from_state(&self.offset) } /// Changes the associated offset. /// This does not change the actual `Time` (but will change the string representation). #[inline] pub fn with_timezone(&self, tz: &Off2) -> Time { tz.from_utc_time(&self.time) } /// Returns a view to the naive UTC time. #[inline] pub fn naive_utc(&self) -> NaiveTime { self.time } /// Returns a view to the naive local time. #[inline] pub fn naive_local(&self) -> NaiveTime { self.time + self.offset.local_minus_utc() } } /// Maps the local time to other time with given conversion function. fn map_local(t: &Time, mut f: F) -> Option> where F: FnMut(NaiveTime) -> Option { f(t.naive_local()).and_then(|time| t.timezone().from_local_time(&time).single()) } impl Time where Off::State: fmt::Display { /// Formats the time in the specified format string. /// See the `format` module on the supported escape sequences. #[inline] pub fn format<'a>(&'a self, fmt: &'a str) -> DelayedFormat<'a> { DelayedFormat::new_with_offset(None, Some(self.naive_local()), &self.offset, fmt) } } impl Timelike for Time { #[inline] fn hour(&self) -> u32 { self.naive_local().hour() } #[inline] fn minute(&self) -> u32 { self.naive_local().minute() } #[inline] fn second(&self) -> u32 { self.naive_local().second() } #[inline] fn nanosecond(&self) -> u32 { self.naive_local().nanosecond() } #[inline] fn with_hour(&self, hour: u32) -> Option> { map_local(self, |time| time.with_hour(hour)) } #[inline] fn with_minute(&self, min: u32) -> Option> { map_local(self, |time| time.with_minute(min)) } #[inline] fn with_second(&self, sec: u32) -> Option> { map_local(self, |time| time.with_second(sec)) } #[inline] fn with_nanosecond(&self, nano: u32) -> Option> { map_local(self, |time| time.with_nanosecond(nano)) } #[inline] fn num_seconds_from_midnight(&self) -> u32 { self.naive_local().num_seconds_from_midnight() } } impl PartialEq> for Time { fn eq(&self, other: &Time) -> bool { self.time == other.time } } impl Eq for Time { } impl PartialOrd for Time { fn partial_cmp(&self, other: &Time) -> Option { self.time.partial_cmp(&other.time) } } impl Ord for Time { fn cmp(&self, other: &Time) -> Ordering { self.time.cmp(&other.time) } } impl hash::Hash for Time { fn hash(&self, state: &mut H) { self.time.hash(state) } } impl Add for Time { type Output = Time; fn add(self, rhs: Duration) -> Time { Time { time: self.time + rhs, offset: self.offset } } } impl Sub> for Time { type Output = Duration; fn sub(self, rhs: Time) -> Duration { self.time - rhs.time } } impl Sub for Time { type Output = Time; #[inline] fn sub(self, rhs: Duration) -> Time { self.add(-rhs) } } impl fmt::Debug for Time { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}{:?}", self.naive_local(), self.offset) } } impl fmt::Display for Time where Off::State: fmt::Display { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}{}", self.naive_local(), self.offset) } }