// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
//! Simple time handling. //! //! # Usage //! //! This crate is [on crates.io](https://crates.io/crates/time) and can be //! used by adding `time` to the dependencies in your project's `Cargo.toml`. //! //! ```toml //! [dependencies] //! time = "0.1" //! ``` //! //! And this in your crate root: //! //! ```rust //! extern crate time; //! ``` //! //! This crate uses the same syntax for format strings as the //! [`strftime()`](http://man7.org/linux/man-pages/man3/strftime.3.html) //! function from the C standard library.
/// A record specifying a time value in seconds and nanoseconds, where /// nanoseconds represent the offset from the given second. /// /// For example a timespec of 1.2 seconds after the beginning of the epoch would /// be represented as {sec: 1, nsec: 200000000}. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pubstruct Timespec { pub sec: i64, pub nsec: i32 } /* *Timespecassumesthatpre-epochTimespecshavenegativesecandpositive *nsecfields.Darwin'sandLinux'sstructtimespecfunctionshandlepre- *epochtimestampsusinga"twostepsback,onestepforward"representation, *thoughthemanpagesdonotactuallydocumentthis.Forexample,thetime *-1.2secondsbeforetheepochisrepresentedby`Timespec{sec:-2_i64, *nsec:800_000_000}`.
*/ impl Timespec { pubfn new(sec: i64, nsec: i32) -> Timespec {
assert!(nsec >= 0 && nsec < NSEC_PER_SEC);
Timespec { sec: sec, nsec: nsec }
}
}
impl Add<Duration> for Timespec { type Output = Timespec;
fn add(self, other: Duration) -> Timespec { let d_sec = other.num_seconds(); // It is safe to unwrap the nanoseconds, because there cannot be // more than one second left, which fits in i64 and in i32. let d_nsec = (other - Duration::seconds(d_sec))
.num_nanoseconds().unwrap() as i32; letmut sec = self.sec + d_sec; letmut nsec = self.nsec + d_nsec; if nsec >= NSEC_PER_SEC {
nsec -= NSEC_PER_SEC;
sec += 1;
} elseif nsec < 0 {
nsec += NSEC_PER_SEC;
sec -= 1;
}
Timespec::new(sec, nsec)
}
}
impl Sub<Duration> for Timespec { type Output = Timespec;
fn sub(self, other: Duration) -> Timespec { let d_sec = other.num_seconds(); // It is safe to unwrap the nanoseconds, because there cannot be // more than one second left, which fits in i64 and in i32. let d_nsec = (other - Duration::seconds(d_sec))
.num_nanoseconds().unwrap() as i32; letmut sec = self.sec - d_sec; letmut nsec = self.nsec - d_nsec; if nsec >= NSEC_PER_SEC {
nsec -= NSEC_PER_SEC;
sec += 1;
} elseif nsec < 0 {
nsec += NSEC_PER_SEC;
sec -= 1;
}
Timespec::new(sec, nsec)
}
}
impl Sub<Timespec> for Timespec { type Output = Duration;
fn sub(self, other: Timespec) -> Duration { let sec = self.sec - other.sec; let nsec = self.nsec - other.nsec;
Duration::seconds(sec) + Duration::nanoseconds(nsec as i64)
}
}
/// An opaque structure representing a moment in time. /// /// The only operation that can be performed on a `PreciseTime` is the /// calculation of the `Duration` of time that lies between them. /// /// # Examples /// /// Repeatedly call a function for 1 second: /// /// ```rust /// use time::{Duration, PreciseTime}; /// # fn do_some_work() {} /// /// let start = PreciseTime::now(); /// /// while start.to(PreciseTime::now()) < Duration::seconds(1) { /// do_some_work(); /// } /// ``` #[derive(Copy, Clone)] pubstruct PreciseTime(u64);
impl PreciseTime { /// Returns a `PreciseTime` representing the current moment in time. pubfn now() -> PreciseTime {
PreciseTime(precise_time_ns())
}
/// Returns a `Duration` representing the span of time from the value of /// `self` to the value of `later`. /// /// # Notes /// /// If `later` represents a time before `self`, the result of this method /// is unspecified. /// /// If `later` represents a time more than 293 years after `self`, the /// result of this method is unspecified. #[inline] pubfn to(&self, later: PreciseTime) -> Duration { // NB: even if later is less than self due to overflow, this will work // since the subtraction will underflow properly as well. // // We could deal with the overflow when casting to an i64, but all that // gets us is the ability to handle intervals of up to 584 years, which // seems not very useful :)
Duration::nanoseconds((later.0 - self.0) as i64)
}
}
/// A structure representing a moment in time. /// /// `SteadyTime`s are generated by a "steady" clock, that is, a clock which /// never experiences discontinuous jumps and for which time always flows at /// the same rate. /// /// # Examples /// /// Repeatedly call a function for 1 second: /// /// ```rust /// # use time::{Duration, SteadyTime}; /// # fn do_some_work() {} /// let start = SteadyTime::now(); /// /// while SteadyTime::now() - start < Duration::seconds(1) { /// do_some_work(); /// } /// ``` #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)] pubstruct SteadyTime(sys::SteadyTime);
impl SteadyTime { /// Returns a `SteadyTime` representing the current moment in time. pubfn now() -> SteadyTime {
SteadyTime(sys::SteadyTime::now())
}
}
/// Holds a calendar date and time broken down into its components (year, month, /// day, and so on), also called a broken-down time value. // FIXME: use c_int instead of i32? #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pubstruct Tm { /// Seconds after the minute - [0, 60] pub tm_sec: i32,
/// Minutes after the hour - [0, 59] pub tm_min: i32,
/// Hours after midnight - [0, 23] pub tm_hour: i32,
/// Day of the month - [1, 31] pub tm_mday: i32,
/// Months since January - [0, 11] pub tm_mon: i32,
/// Years since 1900 pub tm_year: i32,
/// Days since Sunday - [0, 6]. 0 = Sunday, 1 = Monday, ..., 6 = Saturday. pub tm_wday: i32,
/// Days since January 1 - [0, 365] pub tm_yday: i32,
/// Daylight Saving Time flag. /// /// This value is positive if Daylight Saving Time is in effect, zero if /// Daylight Saving Time is not in effect, and negative if this information /// is not available. pub tm_isdst: i32,
/// Identifies the time zone that was used to compute this broken-down time /// value, including any adjustment for Daylight Saving Time. This is the /// number of seconds east of UTC. For example, for U.S. Pacific Daylight /// Time, the value is `-7*60*60 = -25200`. pub tm_utcoff: i32,
/// Nanoseconds after the second - [0, 10<sup>9</sup> - 1] pub tm_nsec: i32,
}
impl Add<Duration> for Tm { type Output = Tm;
/// The resulting Tm is in UTC. // FIXME: The resulting Tm should have the same timezone as `self`; // however, we need a function such as `at_tm(clock: Timespec, offset: i32)` // for this. fn add(self, other: Duration) -> Tm {
at_utc(self.to_timespec() + other)
}
}
impl Sub<Duration> for Tm { type Output = Tm;
/// The resulting Tm is in UTC. // FIXME: The resulting Tm should have the same timezone as `self`; // however, we need a function such as `at_tm(clock: Timespec, offset: i32)` // for this. fn sub(self, other: Duration) -> Tm {
at_utc(self.to_timespec() - other)
}
}
/// Returns the specified time in UTC pubfn at_utc(clock: Timespec) -> Tm { let Timespec { sec, nsec } = clock; letmut tm = empty_tm();
sys::time_to_utc_tm(sec, &mut tm);
tm.tm_nsec = nsec;
tm
}
/// Returns the current time in UTC pubfn now_utc() -> Tm {
at_utc(get_time())
}
/// Returns the specified time in the local timezone pubfn at(clock: Timespec) -> Tm { let Timespec { sec, nsec } = clock; letmut tm = empty_tm();
sys::time_to_local_tm(sec, &mut tm);
tm.tm_nsec = nsec;
tm
}
/// Returns the current time in the local timezone pubfn now() -> Tm {
at(get_time())
}
impl Tm { /// Convert time to the seconds from January 1, 1970 pubfn to_timespec(&self) -> Timespec { let sec = matchself.tm_utcoff { 0 => sys::utc_tm_to_time(self),
_ => sys::local_tm_to_time(self)
};
Timespec::new(sec, self.tm_nsec)
}
/// Convert time to the local timezone pubfn to_local(&self) -> Tm {
at(self.to_timespec())
}
/// Convert time to the UTC pubfn to_utc(&self) -> Tm { matchself.tm_utcoff { 0 => *self,
_ => at_utc(self.to_timespec())
}
}
/// Formats the time according to the format string. pubfn strftime<'a>(&'a self, format: &'a str) -> Result<TmFmt<'a>, ParseError> {
validate_format(TmFmt {
tm: self,
format: Fmt::Str(format),
})
}
/// Formats the time according to the format string. pubfn strftime(format: &str, tm: &Tm) -> Result<String, ParseError> {
tm.strftime(format).map(|fmt| fmt.to_string())
}
#[allow(deprecated)] // `Once::new` is const starting in Rust 1.32 use std::sync::ONCE_INIT; use std::sync::{Once, Mutex, MutexGuard, LockResult}; use std::i32; use std::mem;
fn set_time_zone_la_or_london(london: bool) -> TzReset { // Lock manages current timezone because some tests require LA some // London staticmut LOCK: *mut Mutex<()> = 0as *mut _; #[allow(deprecated)] // `Once::new` is const starting in Rust 1.32 static INIT: Once = ONCE_INIT;
fn test_oneway(s : &str, format : &str) -> bool { match strptime(s, format) {
Ok(_) => { // oneway tests are used when reformatting the parsed Tm // back into a string can generate a different string // from the original (i.e. leading zeroes) true
},
Err(e) => panic!("{:?}, s={:?}, format={:?}", e, s, format)
}
}
let days = [ "Sunday".to_string(), "Monday".to_string(), "Tuesday".to_string(), "Wednesday".to_string(), "Thursday".to_string(), "Friday".to_string(), "Saturday".to_string()
]; for day in days.iter() {
assert!(test(&day, "%A"));
}
let days = [ "Sun".to_string(), "Mon".to_string(), "Tue".to_string(), "Wed".to_string(), "Thu".to_string(), "Fri".to_string(), "Sat".to_string()
]; for day in days.iter() {
assert!(test(&day, "%a"));
}
let months = [ "January".to_string(), "February".to_string(), "March".to_string(), "April".to_string(), "May".to_string(), "June".to_string(), "July".to_string(), "August".to_string(), "September".to_string(), "October".to_string(), "November".to_string(), "December".to_string()
]; for day in months.iter() {
assert!(test(&day, "%B"));
}
let months = [ "Jan".to_string(), "Feb".to_string(), "Mar".to_string(), "Apr".to_string(), "May".to_string(), "Jun".to_string(), "Jul".to_string(), "Aug".to_string(), "Sep".to_string(), "Oct".to_string(), "Nov".to_string(), "Dec".to_string()
]; for day in months.iter() {
assert!(test(&day, "%b"));
}
let invalid_specifiers = ["%E", "%J", "%K", "%L", "%N", "%O", "%o", "%Q", "%q"]; for &sp in invalid_specifiers.iter() {
assert_eq!(local.strftime(sp).unwrap_err(),
InvalidFormatSpecifier(sp[1..].chars().next().unwrap()));
}
assert_eq!(local.strftime("%").unwrap_err(), MissingFormatConverter);
assert_eq!(local.strftime("%A %").unwrap_err(), MissingFormatConverter);
assert_eq!(local.asctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
assert_eq!(local.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
assert_eq!(local.rfc822z().to_string(), "Fri, 13 Feb 2009 15:31:30 -0800".to_string());
assert_eq!(local.rfc3339().to_string(), "2009-02-13T15:31:30-08:00".to_string());
assert_eq!(utc.asctime().to_string(), "Fri Feb 13 23:31:30 2009".to_string());
assert_eq!(utc.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
assert_eq!(utc.rfc822().to_string(), "Fri, 13 Feb 2009 23:31:30 GMT".to_string());
assert_eq!(utc.rfc822z().to_string(), "Fri, 13 Feb 2009 23:31:30 -0000".to_string());
assert_eq!(utc.rfc3339().to_string(), "2009-02-13T23:31:30Z".to_string());
}
#[test] fn test_timespec_eq_ord() { let a = &Timespec::new(-2, 1); let b = &Timespec::new(-1, 2); let c = &Timespec::new(1, 2); let d = &Timespec::new(2, 1); let e = &Timespec::new(2, 1);
#[test] fn test_timespec_add() { let a = Timespec::new(1, 2); let b = Duration::seconds(2) + Duration::nanoseconds(3); let c = a + b;
assert_eq!(c.sec, 3);
assert_eq!(c.nsec, 5);
let p = Timespec::new(1, super::NSEC_PER_SEC - 2); let q = Duration::seconds(2) + Duration::nanoseconds(2); let r = p + q;
assert_eq!(r.sec, 4);
assert_eq!(r.nsec, 0);
let u = Timespec::new(1, super::NSEC_PER_SEC - 2); let v = Duration::seconds(2) + Duration::nanoseconds(3); let w = u + v;
assert_eq!(w.sec, 4);
assert_eq!(w.nsec, 1);
let k = Timespec::new(1, 0); let l = Duration::nanoseconds(-1); let m = k + l;
assert_eq!(m.sec, 0);
assert_eq!(m.nsec, 999_999_999);
}
#[test] fn test_timespec_sub() { let a = Timespec::new(2, 3); let b = Timespec::new(1, 2); let c = a - b;
assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 + 1));
let p = Timespec::new(2, 0); let q = Timespec::new(1, 2); let r = p - q;
assert_eq!(r.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 - 2));
let u = Timespec::new(1, 2); let v = Timespec::new(2, 3); let w = u - v;
assert_eq!(w.num_nanoseconds(), Some(-super::NSEC_PER_SEC as i64 - 1));
}
#[test] fn test_time_sub() { let a = ::now(); let b = at(a.to_timespec() + Duration::seconds(5)); let c = b - a;
assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 * 5));
}
#[test] fn test_steadytime_sub() { let a = SteadyTime::now(); let b = a + Duration::seconds(1);
assert_eq!(b - a, Duration::seconds(1));
assert_eq!(a - b, Duration::seconds(-1));
}
#[test] fn test_date_before_1970() { let early = strptime("1901-01-06", "%F").unwrap(); let late = strptime("2000-01-01", "%F").unwrap();
assert!(early < late);
}
#[test] fn test_dst() { let _reset = set_time_zone_london_dst(); let utc_in_feb = strptime("2015-02-01Z", "%F%z").unwrap(); let utc_in_jun = strptime("2015-06-01Z", "%F%z").unwrap(); let utc_in_nov = strptime("2015-11-01Z", "%F%z").unwrap(); let local_in_feb = utc_in_feb.to_local(); let local_in_jun = utc_in_jun.to_local(); let local_in_nov = utc_in_nov.to_local();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.