]> git.proxmox.com Git - rustc.git/blame - vendor/time/src/lib.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / time / src / lib.rs
CommitLineData
ff7c6d11
XL
1// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Simple time handling.
12//!
13//! # Usage
14//!
15//! This crate is [on crates.io](https://crates.io/crates/time) and can be
16//! used by adding `time` to the dependencies in your project's `Cargo.toml`.
17//!
18//! ```toml
19//! [dependencies]
20//! time = "0.1"
21//! ```
22//!
23//! And this in your crate root:
24//!
25//! ```rust
26//! extern crate time;
27//! ```
28//!
29//! This crate uses the same syntax for format strings as the
30//! [`strftime()`](http://man7.org/linux/man-pages/man3/strftime.3.html)
31//! function from the C standard library.
32
33#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
34 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
35 html_root_url = "https://doc.rust-lang.org/time/")]
f035d41b
XL
36#![allow(unknown_lints)]
37#![allow(ellipsis_inclusive_range_patterns)] // `..=` requires Rust 1.26
ff7c6d11
XL
38#![allow(trivial_numeric_casts)]
39#![cfg_attr(test, deny(warnings))]
40
ff7c6d11
XL
41#[cfg(unix)] extern crate libc;
42#[cfg(windows)] extern crate winapi;
43#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
44
1b1a35ee
XL
45#[cfg(target_os = "wasi")] extern crate wasi;
46
ff7c6d11
XL
47#[cfg(test)] #[macro_use] extern crate log;
48
49use std::cmp::Ordering;
50use std::error::Error;
51use std::fmt;
52use std::ops::{Add, Sub};
53
54pub use duration::{Duration, OutOfRangeError};
55
56use self::ParseError::{InvalidDay, InvalidDayOfMonth, InvalidDayOfWeek,
57 InvalidDayOfYear, InvalidFormatSpecifier, InvalidHour,
58 InvalidMinute, InvalidMonth, InvalidSecond, InvalidTime,
59 InvalidYear, InvalidZoneOffset, InvalidSecondsSinceEpoch,
60 MissingFormatConverter, UnexpectedCharacter};
61
62pub use parse::strptime;
63
64mod display;
65mod duration;
66mod parse;
67mod sys;
68
69static NSEC_PER_SEC: i32 = 1_000_000_000;
70
71/// A record specifying a time value in seconds and nanoseconds, where
72/// nanoseconds represent the offset from the given second.
73///
74/// For example a timespec of 1.2 seconds after the beginning of the epoch would
75/// be represented as {sec: 1, nsec: 200000000}.
76#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
77#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
78pub struct Timespec { pub sec: i64, pub nsec: i32 }
79/*
80 * Timespec assumes that pre-epoch Timespecs have negative sec and positive
81 * nsec fields. Darwin's and Linux's struct timespec functions handle pre-
82 * epoch timestamps using a "two steps back, one step forward" representation,
83 * though the man pages do not actually document this. For example, the time
84 * -1.2 seconds before the epoch is represented by `Timespec { sec: -2_i64,
85 * nsec: 800_000_000 }`.
86 */
87impl Timespec {
88 pub fn new(sec: i64, nsec: i32) -> Timespec {
89 assert!(nsec >= 0 && nsec < NSEC_PER_SEC);
90 Timespec { sec: sec, nsec: nsec }
91 }
92}
93
94impl Add<Duration> for Timespec {
95 type Output = Timespec;
96
97 fn add(self, other: Duration) -> Timespec {
98 let d_sec = other.num_seconds();
99 // It is safe to unwrap the nanoseconds, because there cannot be
100 // more than one second left, which fits in i64 and in i32.
101 let d_nsec = (other - Duration::seconds(d_sec))
102 .num_nanoseconds().unwrap() as i32;
103 let mut sec = self.sec + d_sec;
104 let mut nsec = self.nsec + d_nsec;
105 if nsec >= NSEC_PER_SEC {
106 nsec -= NSEC_PER_SEC;
107 sec += 1;
108 } else if nsec < 0 {
109 nsec += NSEC_PER_SEC;
110 sec -= 1;
111 }
112 Timespec::new(sec, nsec)
113 }
114}
115
116impl Sub<Duration> for Timespec {
117 type Output = Timespec;
118
119 fn sub(self, other: Duration) -> Timespec {
120 let d_sec = other.num_seconds();
121 // It is safe to unwrap the nanoseconds, because there cannot be
122 // more than one second left, which fits in i64 and in i32.
123 let d_nsec = (other - Duration::seconds(d_sec))
124 .num_nanoseconds().unwrap() as i32;
125 let mut sec = self.sec - d_sec;
126 let mut nsec = self.nsec - d_nsec;
127 if nsec >= NSEC_PER_SEC {
128 nsec -= NSEC_PER_SEC;
129 sec += 1;
130 } else if nsec < 0 {
131 nsec += NSEC_PER_SEC;
132 sec -= 1;
133 }
134 Timespec::new(sec, nsec)
135 }
136}
137
138impl Sub<Timespec> for Timespec {
139 type Output = Duration;
140
141 fn sub(self, other: Timespec) -> Duration {
142 let sec = self.sec - other.sec;
143 let nsec = self.nsec - other.nsec;
144 Duration::seconds(sec) + Duration::nanoseconds(nsec as i64)
145 }
146}
147
148/**
149 * Returns the current time as a `timespec` containing the seconds and
150 * nanoseconds since 1970-01-01T00:00:00Z.
151 */
152pub fn get_time() -> Timespec {
153 let (sec, nsec) = sys::get_time();
154 Timespec::new(sec, nsec)
155}
156
157
158/**
159 * Returns the current value of a high-resolution performance counter
160 * in nanoseconds since an unspecified epoch.
161 */
8faf50e0 162#[inline]
ff7c6d11
XL
163pub fn precise_time_ns() -> u64 {
164 sys::get_precise_ns()
165}
166
167
168/**
169 * Returns the current value of a high-resolution performance counter
170 * in seconds since an unspecified epoch.
171 */
172pub fn precise_time_s() -> f64 {
173 return (precise_time_ns() as f64) / 1000000000.;
174}
175
176/// An opaque structure representing a moment in time.
177///
178/// The only operation that can be performed on a `PreciseTime` is the
179/// calculation of the `Duration` of time that lies between them.
180///
181/// # Examples
182///
183/// Repeatedly call a function for 1 second:
184///
185/// ```rust
186/// use time::{Duration, PreciseTime};
187/// # fn do_some_work() {}
188///
189/// let start = PreciseTime::now();
190///
191/// while start.to(PreciseTime::now()) < Duration::seconds(1) {
192/// do_some_work();
193/// }
194/// ```
195#[derive(Copy, Clone)]
196pub struct PreciseTime(u64);
197
198impl PreciseTime {
199 /// Returns a `PreciseTime` representing the current moment in time.
200 pub fn now() -> PreciseTime {
201 PreciseTime(precise_time_ns())
202 }
203
204 /// Returns a `Duration` representing the span of time from the value of
205 /// `self` to the value of `later`.
206 ///
207 /// # Notes
208 ///
209 /// If `later` represents a time before `self`, the result of this method
210 /// is unspecified.
211 ///
212 /// If `later` represents a time more than 293 years after `self`, the
213 /// result of this method is unspecified.
214 #[inline]
215 pub fn to(&self, later: PreciseTime) -> Duration {
216 // NB: even if later is less than self due to overflow, this will work
217 // since the subtraction will underflow properly as well.
218 //
219 // We could deal with the overflow when casting to an i64, but all that
220 // gets us is the ability to handle intervals of up to 584 years, which
221 // seems not very useful :)
222 Duration::nanoseconds((later.0 - self.0) as i64)
223 }
224}
225
226/// A structure representing a moment in time.
227///
228/// `SteadyTime`s are generated by a "steady" clock, that is, a clock which
229/// never experiences discontinuous jumps and for which time always flows at
230/// the same rate.
231///
232/// # Examples
233///
234/// Repeatedly call a function for 1 second:
235///
236/// ```rust
237/// # use time::{Duration, SteadyTime};
238/// # fn do_some_work() {}
239/// let start = SteadyTime::now();
240///
241/// while SteadyTime::now() - start < Duration::seconds(1) {
242/// do_some_work();
243/// }
244/// ```
245#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
246pub struct SteadyTime(sys::SteadyTime);
247
248impl SteadyTime {
249 /// Returns a `SteadyTime` representing the current moment in time.
250 pub fn now() -> SteadyTime {
251 SteadyTime(sys::SteadyTime::now())
252 }
253}
254
255impl fmt::Display for SteadyTime {
256 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
257 // TODO: needs a display customization
258 fmt::Debug::fmt(self, fmt)
259 }
260}
261
262impl Sub for SteadyTime {
263 type Output = Duration;
264
265 fn sub(self, other: SteadyTime) -> Duration {
266 self.0 - other.0
267 }
268}
269
270impl Sub<Duration> for SteadyTime {
271 type Output = SteadyTime;
272
273 fn sub(self, other: Duration) -> SteadyTime {
274 SteadyTime(self.0 - other)
275 }
276}
277
278impl Add<Duration> for SteadyTime {
279 type Output = SteadyTime;
280
281 fn add(self, other: Duration) -> SteadyTime {
282 SteadyTime(self.0 + other)
283 }
284}
285
60c5eb7d 286#[cfg(not(any(windows, target_env = "sgx")))]
ff7c6d11
XL
287pub fn tzset() {
288 extern { fn tzset(); }
289 unsafe { tzset() }
290}
291
292
60c5eb7d 293#[cfg(any(windows, target_env = "sgx"))]
ff7c6d11
XL
294pub fn tzset() {}
295
296/// Holds a calendar date and time broken down into its components (year, month,
297/// day, and so on), also called a broken-down time value.
298// FIXME: use c_int instead of i32?
299#[repr(C)]
300#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
301#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
302pub struct Tm {
303 /// Seconds after the minute - [0, 60]
304 pub tm_sec: i32,
305
306 /// Minutes after the hour - [0, 59]
307 pub tm_min: i32,
308
309 /// Hours after midnight - [0, 23]
310 pub tm_hour: i32,
311
312 /// Day of the month - [1, 31]
313 pub tm_mday: i32,
314
315 /// Months since January - [0, 11]
316 pub tm_mon: i32,
317
318 /// Years since 1900
319 pub tm_year: i32,
320
321 /// Days since Sunday - [0, 6]. 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
322 pub tm_wday: i32,
323
324 /// Days since January 1 - [0, 365]
325 pub tm_yday: i32,
326
327 /// Daylight Saving Time flag.
328 ///
329 /// This value is positive if Daylight Saving Time is in effect, zero if
330 /// Daylight Saving Time is not in effect, and negative if this information
331 /// is not available.
332 pub tm_isdst: i32,
333
334 /// Identifies the time zone that was used to compute this broken-down time
335 /// value, including any adjustment for Daylight Saving Time. This is the
336 /// number of seconds east of UTC. For example, for U.S. Pacific Daylight
337 /// Time, the value is `-7*60*60 = -25200`.
338 pub tm_utcoff: i32,
339
340 /// Nanoseconds after the second - [0, 10<sup>9</sup> - 1]
341 pub tm_nsec: i32,
342}
343
344impl Add<Duration> for Tm {
345 type Output = Tm;
346
347 /// The resulting Tm is in UTC.
348 // FIXME: The resulting Tm should have the same timezone as `self`;
349 // however, we need a function such as `at_tm(clock: Timespec, offset: i32)`
350 // for this.
351 fn add(self, other: Duration) -> Tm {
352 at_utc(self.to_timespec() + other)
353 }
354}
355
356impl Sub<Duration> for Tm {
357 type Output = Tm;
358
359 /// The resulting Tm is in UTC.
360 // FIXME: The resulting Tm should have the same timezone as `self`;
361 // however, we need a function such as `at_tm(clock: Timespec, offset: i32)`
362 // for this.
363 fn sub(self, other: Duration) -> Tm {
364 at_utc(self.to_timespec() - other)
365 }
366}
367
368impl Sub<Tm> for Tm {
369 type Output = Duration;
370
371 fn sub(self, other: Tm) -> Duration {
372 self.to_timespec() - other.to_timespec()
373 }
374}
375
376impl PartialOrd for Tm {
377 fn partial_cmp(&self, other: &Tm) -> Option<Ordering> {
378 self.to_timespec().partial_cmp(&other.to_timespec())
379 }
380}
381
382impl Ord for Tm {
383 fn cmp(&self, other: &Tm) -> Ordering {
384 self.to_timespec().cmp(&other.to_timespec())
385 }
386}
387
388pub fn empty_tm() -> Tm {
389 Tm {
390 tm_sec: 0,
391 tm_min: 0,
392 tm_hour: 0,
393 tm_mday: 0,
394 tm_mon: 0,
395 tm_year: 0,
396 tm_wday: 0,
397 tm_yday: 0,
398 tm_isdst: 0,
399 tm_utcoff: 0,
400 tm_nsec: 0,
401 }
402}
403
404/// Returns the specified time in UTC
405pub fn at_utc(clock: Timespec) -> Tm {
406 let Timespec { sec, nsec } = clock;
407 let mut tm = empty_tm();
408 sys::time_to_utc_tm(sec, &mut tm);
409 tm.tm_nsec = nsec;
410 tm
411}
412
413/// Returns the current time in UTC
414pub fn now_utc() -> Tm {
415 at_utc(get_time())
416}
417
418/// Returns the specified time in the local timezone
419pub fn at(clock: Timespec) -> Tm {
420 let Timespec { sec, nsec } = clock;
421 let mut tm = empty_tm();
422 sys::time_to_local_tm(sec, &mut tm);
423 tm.tm_nsec = nsec;
424 tm
425}
426
427/// Returns the current time in the local timezone
428pub fn now() -> Tm {
429 at(get_time())
430}
431
432impl Tm {
433 /// Convert time to the seconds from January 1, 1970
434 pub fn to_timespec(&self) -> Timespec {
435 let sec = match self.tm_utcoff {
436 0 => sys::utc_tm_to_time(self),
437 _ => sys::local_tm_to_time(self)
438 };
439
440 Timespec::new(sec, self.tm_nsec)
441 }
442
443 /// Convert time to the local timezone
444 pub fn to_local(&self) -> Tm {
445 at(self.to_timespec())
446 }
447
448 /// Convert time to the UTC
449 pub fn to_utc(&self) -> Tm {
450 match self.tm_utcoff {
451 0 => *self,
452 _ => at_utc(self.to_timespec())
453 }
454 }
455
456 /**
457 * Returns a TmFmt that outputs according to the `asctime` format in ISO
458 * C, in the local timezone.
459 *
460 * Example: "Thu Jan 1 00:00:00 1970"
461 */
462 pub fn ctime(&self) -> TmFmt {
463 TmFmt {
464 tm: self,
465 format: Fmt::Ctime,
466 }
467 }
468
469 /**
470 * Returns a TmFmt that outputs according to the `asctime` format in ISO
471 * C.
472 *
473 * Example: "Thu Jan 1 00:00:00 1970"
474 */
475 pub fn asctime(&self) -> TmFmt {
476 TmFmt {
477 tm: self,
478 format: Fmt::Str("%c"),
479 }
480 }
481
482 /// Formats the time according to the format string.
483 pub fn strftime<'a>(&'a self, format: &'a str) -> Result<TmFmt<'a>, ParseError> {
484 validate_format(TmFmt {
485 tm: self,
486 format: Fmt::Str(format),
487 })
488 }
489
490 /**
491 * Returns a TmFmt that outputs according to RFC 822.
492 *
493 * local: "Thu, 22 Mar 2012 07:53:18 PST"
494 * utc: "Thu, 22 Mar 2012 14:53:18 GMT"
495 */
496 pub fn rfc822(&self) -> TmFmt {
497 let fmt = if self.tm_utcoff == 0 {
498 "%a, %d %b %Y %T GMT"
499 } else {
500 "%a, %d %b %Y %T %Z"
501 };
502 TmFmt {
503 tm: self,
504 format: Fmt::Str(fmt),
505 }
506 }
507
508 /**
509 * Returns a TmFmt that outputs according to RFC 822 with Zulu time.
510 *
511 * local: "Thu, 22 Mar 2012 07:53:18 -0700"
512 * utc: "Thu, 22 Mar 2012 14:53:18 -0000"
513 */
514 pub fn rfc822z(&self) -> TmFmt {
515 TmFmt {
516 tm: self,
517 format: Fmt::Str("%a, %d %b %Y %T %z"),
518 }
519 }
520
521 /**
522 * Returns a TmFmt that outputs according to RFC 3339. RFC 3339 is
523 * compatible with ISO 8601.
524 *
525 * local: "2012-02-22T07:53:18-07:00"
526 * utc: "2012-02-22T14:53:18Z"
527 */
528 pub fn rfc3339<'a>(&'a self) -> TmFmt {
529 TmFmt {
530 tm: self,
531 format: Fmt::Rfc3339,
532 }
533 }
534}
535
536#[derive(Copy, PartialEq, Debug, Clone)]
537pub enum ParseError {
538 InvalidSecond,
539 InvalidMinute,
540 InvalidHour,
541 InvalidDay,
542 InvalidMonth,
543 InvalidYear,
544 InvalidDayOfWeek,
545 InvalidDayOfMonth,
546 InvalidDayOfYear,
547 InvalidZoneOffset,
548 InvalidTime,
549 InvalidSecondsSinceEpoch,
550 MissingFormatConverter,
551 InvalidFormatSpecifier(char),
552 UnexpectedCharacter(char, char),
553}
554
555impl fmt::Display for ParseError {
556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f035d41b 557 #[allow(deprecated)]
ff7c6d11
XL
558 match *self {
559 InvalidFormatSpecifier(ch) => {
560 write!(f, "{}: %{}", self.description(), ch)
561 }
562 UnexpectedCharacter(a, b) => {
563 write!(f, "expected: `{}`, found: `{}`", a, b)
564 }
565 _ => write!(f, "{}", self.description())
566 }
567 }
568}
569
570impl Error for ParseError {
571 fn description(&self) -> &str {
572 match *self {
573 InvalidSecond => "Invalid second.",
574 InvalidMinute => "Invalid minute.",
575 InvalidHour => "Invalid hour.",
576 InvalidDay => "Invalid day.",
577 InvalidMonth => "Invalid month.",
578 InvalidYear => "Invalid year.",
579 InvalidDayOfWeek => "Invalid day of the week.",
580 InvalidDayOfMonth => "Invalid day of the month.",
581 InvalidDayOfYear => "Invalid day of the year.",
582 InvalidZoneOffset => "Invalid zone offset.",
583 InvalidTime => "Invalid time.",
584 InvalidSecondsSinceEpoch => "Invalid seconds since epoch.",
585 MissingFormatConverter => "missing format converter after `%`",
586 InvalidFormatSpecifier(..) => "invalid format specifier",
587 UnexpectedCharacter(..) => "Unexpected character.",
588 }
589 }
590}
591
592/// A wrapper around a `Tm` and format string that implements Display.
593#[derive(Debug)]
594pub struct TmFmt<'a> {
595 tm: &'a Tm,
596 format: Fmt<'a>
597}
598
599#[derive(Debug)]
600enum Fmt<'a> {
601 Str(&'a str),
602 Rfc3339,
603 Ctime,
604}
605
606fn validate_format<'a>(fmt: TmFmt<'a>) -> Result<TmFmt<'a>, ParseError> {
607
608 match (fmt.tm.tm_wday, fmt.tm.tm_mon) {
609 (0...6, 0...11) => (),
610 (_wday, 0...11) => return Err(InvalidDayOfWeek),
611 (0...6, _mon) => return Err(InvalidMonth),
612 _ => return Err(InvalidDay)
613 }
614 match fmt.format {
615 Fmt::Str(ref s) => {
616 let mut chars = s.chars();
617 loop {
618 match chars.next() {
619 Some('%') => {
620 match chars.next() {
621 Some('A') | Some('a') | Some('B') | Some('b') |
622 Some('C') | Some('c') | Some('D') | Some('d') |
623 Some('e') | Some('F') | Some('f') | Some('G') |
624 Some('g') | Some('H') | Some('h') | Some('I') |
625 Some('j') | Some('k') | Some('l') | Some('M') |
626 Some('m') | Some('n') | Some('P') | Some('p') |
627 Some('R') | Some('r') | Some('S') | Some('s') |
628 Some('T') | Some('t') | Some('U') | Some('u') |
629 Some('V') | Some('v') | Some('W') | Some('w') |
630 Some('X') | Some('x') | Some('Y') | Some('y') |
631 Some('Z') | Some('z') | Some('+') | Some('%') => (),
632
633 Some(c) => return Err(InvalidFormatSpecifier(c)),
634 None => return Err(MissingFormatConverter),
635 }
636 },
637 None => break,
638 _ => ()
639 }
640 }
641 },
642 _ => ()
643 }
644 Ok(fmt)
645}
646
647/// Formats the time according to the format string.
648pub fn strftime(format: &str, tm: &Tm) -> Result<String, ParseError> {
649 tm.strftime(format).map(|fmt| fmt.to_string())
650}
651
652#[cfg(test)]
653mod tests {
654 use super::{Timespec, get_time, precise_time_ns, precise_time_s,
655 at_utc, at, strptime, PreciseTime, SteadyTime, ParseError, Duration};
656 use super::ParseError::{InvalidTime, InvalidYear, MissingFormatConverter,
657 InvalidFormatSpecifier};
658
f035d41b
XL
659 #[allow(deprecated)] // `Once::new` is const starting in Rust 1.32
660 use std::sync::ONCE_INIT;
661 use std::sync::{Once, Mutex, MutexGuard, LockResult};
662 use std::i32;
ff7c6d11
XL
663 use std::mem;
664
665 struct TzReset {
666 _tzreset: ::sys::TzReset,
667 _lock: LockResult<MutexGuard<'static, ()>>,
668 }
669
670 fn set_time_zone_la_or_london(london: bool) -> TzReset {
671 // Lock manages current timezone because some tests require LA some
672 // London
673 static mut LOCK: *mut Mutex<()> = 0 as *mut _;
f035d41b 674 #[allow(deprecated)] // `Once::new` is const starting in Rust 1.32
ff7c6d11
XL
675 static INIT: Once = ONCE_INIT;
676
677 unsafe {
678 INIT.call_once(|| {
679 LOCK = mem::transmute(Box::new(Mutex::new(())));
680 });
681
682 let timezone_lock = (*LOCK).lock();
683 let reset_func = if london {
684 ::sys::set_london_with_dst_time_zone()
685 } else {
686 ::sys::set_los_angeles_time_zone()
687 };
688 TzReset {
689 _lock: timezone_lock,
690 _tzreset: reset_func,
691 }
692 }
693 }
694
695 fn set_time_zone() -> TzReset {
696 set_time_zone_la_or_london(false)
697 }
698
699 fn set_time_zone_london_dst() -> TzReset {
700 set_time_zone_la_or_london(true)
701 }
702
703 #[test]
704 fn test_get_time() {
f035d41b
XL
705 static SOME_RECENT_DATE: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
706 static SOME_FUTURE_DATE: i64 = i32::MAX as i64; // Y2038
ff7c6d11
XL
707
708 let tv1 = get_time();
709 debug!("tv1={} sec + {} nsec", tv1.sec, tv1.nsec);
710
711 assert!(tv1.sec > SOME_RECENT_DATE);
712 assert!(tv1.nsec < 1000000000i32);
713
714 let tv2 = get_time();
715 debug!("tv2={} sec + {} nsec", tv2.sec, tv2.nsec);
716
717 assert!(tv2.sec >= tv1.sec);
718 assert!(tv2.sec < SOME_FUTURE_DATE);
719 assert!(tv2.nsec < 1000000000i32);
720 if tv2.sec == tv1.sec {
721 assert!(tv2.nsec >= tv1.nsec);
722 }
723 }
724
725 #[test]
726 fn test_precise_time() {
727 let s0 = precise_time_s();
728 debug!("s0={} sec", s0);
729 assert!(s0 > 0.);
730
731 let ns0 = precise_time_ns();
732 let ns1 = precise_time_ns();
733 debug!("ns0={} ns", ns0);
734 debug!("ns1={} ns", ns1);
735 assert!(ns1 >= ns0);
736
737 let ns2 = precise_time_ns();
738 debug!("ns2={} ns", ns2);
739 assert!(ns2 >= ns1);
740 }
741
742 #[test]
743 fn test_precise_time_to() {
744 let t0 = PreciseTime(1000);
745 let t1 = PreciseTime(1023);
746 assert_eq!(Duration::nanoseconds(23), t0.to(t1));
747 }
748
749 #[test]
750 fn test_at_utc() {
751 let _reset = set_time_zone();
752
753 let time = Timespec::new(1234567890, 54321);
754 let utc = at_utc(time);
755
756 assert_eq!(utc.tm_sec, 30);
757 assert_eq!(utc.tm_min, 31);
758 assert_eq!(utc.tm_hour, 23);
759 assert_eq!(utc.tm_mday, 13);
760 assert_eq!(utc.tm_mon, 1);
761 assert_eq!(utc.tm_year, 109);
762 assert_eq!(utc.tm_wday, 5);
763 assert_eq!(utc.tm_yday, 43);
764 assert_eq!(utc.tm_isdst, 0);
765 assert_eq!(utc.tm_utcoff, 0);
766 assert_eq!(utc.tm_nsec, 54321);
767 }
768
769 #[test]
770 fn test_at() {
771 let _reset = set_time_zone();
772
773 let time = Timespec::new(1234567890, 54321);
774 let local = at(time);
775
776 debug!("time_at: {:?}", local);
777
778 assert_eq!(local.tm_sec, 30);
779 assert_eq!(local.tm_min, 31);
780 assert_eq!(local.tm_hour, 15);
781 assert_eq!(local.tm_mday, 13);
782 assert_eq!(local.tm_mon, 1);
783 assert_eq!(local.tm_year, 109);
784 assert_eq!(local.tm_wday, 5);
785 assert_eq!(local.tm_yday, 43);
786 assert_eq!(local.tm_isdst, 0);
787 assert_eq!(local.tm_utcoff, -28800);
788 assert_eq!(local.tm_nsec, 54321);
789 }
790
791 #[test]
792 fn test_to_timespec() {
793 let _reset = set_time_zone();
794
795 let time = Timespec::new(1234567890, 54321);
796 let utc = at_utc(time);
797
798 assert_eq!(utc.to_timespec(), time);
799 assert_eq!(utc.to_local().to_timespec(), time);
800 }
801
802 #[test]
803 fn test_conversions() {
804 let _reset = set_time_zone();
805
806 let time = Timespec::new(1234567890, 54321);
807 let utc = at_utc(time);
808 let local = at(time);
809
810 assert!(local.to_local() == local);
811 assert!(local.to_utc() == utc);
812 assert!(local.to_utc().to_local() == local);
813 assert!(utc.to_utc() == utc);
814 assert!(utc.to_local() == local);
815 assert!(utc.to_local().to_utc() == utc);
816 }
817
818 #[test]
819 fn test_strptime() {
820 let _reset = set_time_zone();
821
822 match strptime("", "") {
823 Ok(ref tm) => {
824 assert!(tm.tm_sec == 0);
825 assert!(tm.tm_min == 0);
826 assert!(tm.tm_hour == 0);
827 assert!(tm.tm_mday == 0);
828 assert!(tm.tm_mon == 0);
829 assert!(tm.tm_year == 0);
830 assert!(tm.tm_wday == 0);
831 assert!(tm.tm_isdst == 0);
832 assert!(tm.tm_utcoff == 0);
833 assert!(tm.tm_nsec == 0);
834 }
835 Err(_) => ()
836 }
837
838 let format = "%a %b %e %T.%f %Y";
839 assert_eq!(strptime("", format), Err(ParseError::InvalidDay));
840 assert_eq!(strptime("Fri Feb 13 15:31:30", format),
841 Err(InvalidTime));
842
843 match strptime("Fri Feb 13 15:31:30.01234 2009", format) {
844 Err(e) => panic!("{}", e),
845 Ok(ref tm) => {
846 assert_eq!(tm.tm_sec, 30);
847 assert_eq!(tm.tm_min, 31);
848 assert_eq!(tm.tm_hour, 15);
849 assert_eq!(tm.tm_mday, 13);
850 assert_eq!(tm.tm_mon, 1);
851 assert_eq!(tm.tm_year, 109);
852 assert_eq!(tm.tm_wday, 5);
853 assert_eq!(tm.tm_yday, 0);
854 assert_eq!(tm.tm_isdst, 0);
855 assert_eq!(tm.tm_utcoff, 0);
856 assert_eq!(tm.tm_nsec, 12340000);
857 }
858 }
859
860 fn test(s: &str, format: &str) -> bool {
861 match strptime(s, format) {
862 Ok(tm) => {
863 tm.strftime(format).unwrap().to_string() == s.to_string()
864 },
865 Err(e) => panic!("{:?}, s={:?}, format={:?}", e, s, format)
866 }
867 }
868
869 fn test_oneway(s : &str, format : &str) -> bool {
870 match strptime(s, format) {
871 Ok(_) => {
872 // oneway tests are used when reformatting the parsed Tm
873 // back into a string can generate a different string
874 // from the original (i.e. leading zeroes)
875 true
876 },
877 Err(e) => panic!("{:?}, s={:?}, format={:?}", e, s, format)
878 }
879 }
880
881 let days = [
882 "Sunday".to_string(),
883 "Monday".to_string(),
884 "Tuesday".to_string(),
885 "Wednesday".to_string(),
886 "Thursday".to_string(),
887 "Friday".to_string(),
888 "Saturday".to_string()
889 ];
890 for day in days.iter() {
891 assert!(test(&day, "%A"));
892 }
893
894 let days = [
895 "Sun".to_string(),
896 "Mon".to_string(),
897 "Tue".to_string(),
898 "Wed".to_string(),
899 "Thu".to_string(),
900 "Fri".to_string(),
901 "Sat".to_string()
902 ];
903 for day in days.iter() {
904 assert!(test(&day, "%a"));
905 }
906
907 let months = [
908 "January".to_string(),
909 "February".to_string(),
910 "March".to_string(),
911 "April".to_string(),
912 "May".to_string(),
913 "June".to_string(),
914 "July".to_string(),
915 "August".to_string(),
916 "September".to_string(),
917 "October".to_string(),
918 "November".to_string(),
919 "December".to_string()
920 ];
921 for day in months.iter() {
922 assert!(test(&day, "%B"));
923 }
924
925 let months = [
926 "Jan".to_string(),
927 "Feb".to_string(),
928 "Mar".to_string(),
929 "Apr".to_string(),
930 "May".to_string(),
931 "Jun".to_string(),
932 "Jul".to_string(),
933 "Aug".to_string(),
934 "Sep".to_string(),
935 "Oct".to_string(),
936 "Nov".to_string(),
937 "Dec".to_string()
938 ];
939 for day in months.iter() {
940 assert!(test(&day, "%b"));
941 }
942
943 assert!(test("19", "%C"));
944 assert!(test("Fri Feb 3 23:31:30 2009", "%c"));
945 assert!(test("Fri Feb 13 23:31:30 2009", "%c"));
946 assert!(test("02/13/09", "%D"));
947 assert!(test("03", "%d"));
948 assert!(test("13", "%d"));
949 assert!(test(" 3", "%e"));
950 assert!(test("13", "%e"));
951 assert!(test("2009-02-13", "%F"));
952 assert!(test("03", "%H"));
953 assert!(test("13", "%H"));
954 assert!(test("03", "%I")); // FIXME (#2350): flesh out
955 assert!(test("11", "%I")); // FIXME (#2350): flesh out
956 assert!(test("044", "%j"));
957 assert!(test(" 3", "%k"));
958 assert!(test("13", "%k"));
959 assert!(test(" 1", "%l"));
960 assert!(test("11", "%l"));
961 assert!(test("03", "%M"));
962 assert!(test("13", "%M"));
963 assert!(test("\n", "%n"));
964 assert!(test("am", "%P"));
965 assert!(test("pm", "%P"));
966 assert!(test("AM", "%p"));
967 assert!(test("PM", "%p"));
968 assert!(test("23:31", "%R"));
969 assert!(test("11:31:30 AM", "%r"));
970 assert!(test("11:31:30 PM", "%r"));
971 assert!(test("03", "%S"));
972 assert!(test("13", "%S"));
973 assert!(test("15:31:30", "%T"));
974 assert!(test("\t", "%t"));
975 assert!(test("1", "%u"));
976 assert!(test("7", "%u"));
977 assert!(test("13-Feb-2009", "%v"));
978 assert!(test("0", "%w"));
979 assert!(test("6", "%w"));
980 assert!(test("2009", "%Y"));
981 assert!(test("09", "%y"));
982
983 assert!(test_oneway("3", "%d"));
984 assert!(test_oneway("3", "%H"));
985 assert!(test_oneway("3", "%e"));
986 assert!(test_oneway("3", "%M"));
987 assert!(test_oneway("3", "%S"));
988
989 assert!(strptime("-0000", "%z").unwrap().tm_utcoff == 0);
990 assert!(strptime("-00:00", "%z").unwrap().tm_utcoff == 0);
991 assert!(strptime("Z", "%z").unwrap().tm_utcoff == 0);
992 assert_eq!(-28800, strptime("-0800", "%z").unwrap().tm_utcoff);
993 assert_eq!(-28800, strptime("-08:00", "%z").unwrap().tm_utcoff);
994 assert_eq!(28800, strptime("+0800", "%z").unwrap().tm_utcoff);
995 assert_eq!(28800, strptime("+08:00", "%z").unwrap().tm_utcoff);
996 assert_eq!(5400, strptime("+0130", "%z").unwrap().tm_utcoff);
997 assert_eq!(5400, strptime("+01:30", "%z").unwrap().tm_utcoff);
998 assert!(test("%", "%%"));
999
1000 // Test for #7256
1001 assert_eq!(strptime("360", "%Y-%m-%d"), Err(InvalidYear));
1002
1003 // Test for epoch seconds parsing
1004 {
1005 assert!(test("1428035610", "%s"));
1006 let tm = strptime("1428035610", "%s").unwrap();
1007 assert_eq!(tm.tm_utcoff, 0);
1008 assert_eq!(tm.tm_isdst, 0);
1009 assert_eq!(tm.tm_yday, 92);
1010 assert_eq!(tm.tm_wday, 5);
1011 assert_eq!(tm.tm_year, 115);
1012 assert_eq!(tm.tm_mon, 3);
1013 assert_eq!(tm.tm_mday, 3);
1014 assert_eq!(tm.tm_hour, 4);
1015 }
1016 }
1017
1018 #[test]
1019 fn test_asctime() {
1020 let _reset = set_time_zone();
1021
1022 let time = Timespec::new(1234567890, 54321);
1023 let utc = at_utc(time);
1024 let local = at(time);
1025
1026 debug!("test_ctime: {} {}", utc.asctime(), local.asctime());
1027
1028 assert_eq!(utc.asctime().to_string(), "Fri Feb 13 23:31:30 2009".to_string());
1029 assert_eq!(local.asctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1030 }
1031
1032 #[test]
1033 fn test_ctime() {
1034 let _reset = set_time_zone();
1035
1036 let time = Timespec::new(1234567890, 54321);
1037 let utc = at_utc(time);
1038 let local = at(time);
1039
1040 debug!("test_ctime: {} {}", utc.ctime(), local.ctime());
1041
1042 assert_eq!(utc.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1043 assert_eq!(local.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1044 }
1045
1046 #[test]
1047 fn test_strftime() {
1048 let _reset = set_time_zone();
1049
1050 let time = Timespec::new(1234567890, 54321);
1051 let utc = at_utc(time);
1052 let local = at(time);
1053
1054 assert_eq!(local.strftime("").unwrap().to_string(), "".to_string());
1055 assert_eq!(local.strftime("%A").unwrap().to_string(), "Friday".to_string());
1056 assert_eq!(local.strftime("%a").unwrap().to_string(), "Fri".to_string());
1057 assert_eq!(local.strftime("%B").unwrap().to_string(), "February".to_string());
1058 assert_eq!(local.strftime("%b").unwrap().to_string(), "Feb".to_string());
1059 assert_eq!(local.strftime("%C").unwrap().to_string(), "20".to_string());
1060 assert_eq!(local.strftime("%c").unwrap().to_string(),
1061 "Fri Feb 13 15:31:30 2009".to_string());
1062 assert_eq!(local.strftime("%D").unwrap().to_string(), "02/13/09".to_string());
1063 assert_eq!(local.strftime("%d").unwrap().to_string(), "13".to_string());
1064 assert_eq!(local.strftime("%e").unwrap().to_string(), "13".to_string());
1065 assert_eq!(local.strftime("%F").unwrap().to_string(), "2009-02-13".to_string());
1066 assert_eq!(local.strftime("%f").unwrap().to_string(), "000054321".to_string());
1067 assert_eq!(local.strftime("%G").unwrap().to_string(), "2009".to_string());
1068 assert_eq!(local.strftime("%g").unwrap().to_string(), "09".to_string());
1069 assert_eq!(local.strftime("%H").unwrap().to_string(), "15".to_string());
1070 assert_eq!(local.strftime("%h").unwrap().to_string(), "Feb".to_string());
1071 assert_eq!(local.strftime("%I").unwrap().to_string(), "03".to_string());
1072 assert_eq!(local.strftime("%j").unwrap().to_string(), "044".to_string());
1073 assert_eq!(local.strftime("%k").unwrap().to_string(), "15".to_string());
1074 assert_eq!(local.strftime("%l").unwrap().to_string(), " 3".to_string());
1075 assert_eq!(local.strftime("%M").unwrap().to_string(), "31".to_string());
1076 assert_eq!(local.strftime("%m").unwrap().to_string(), "02".to_string());
1077 assert_eq!(local.strftime("%n").unwrap().to_string(), "\n".to_string());
1078 assert_eq!(local.strftime("%P").unwrap().to_string(), "pm".to_string());
1079 assert_eq!(local.strftime("%p").unwrap().to_string(), "PM".to_string());
1080 assert_eq!(local.strftime("%R").unwrap().to_string(), "15:31".to_string());
1081 assert_eq!(local.strftime("%r").unwrap().to_string(), "03:31:30 PM".to_string());
1082 assert_eq!(local.strftime("%S").unwrap().to_string(), "30".to_string());
1083 assert_eq!(local.strftime("%s").unwrap().to_string(), "1234567890".to_string());
1084 assert_eq!(local.strftime("%T").unwrap().to_string(), "15:31:30".to_string());
1085 assert_eq!(local.strftime("%t").unwrap().to_string(), "\t".to_string());
1086 assert_eq!(local.strftime("%U").unwrap().to_string(), "06".to_string());
1087 assert_eq!(local.strftime("%u").unwrap().to_string(), "5".to_string());
1088 assert_eq!(local.strftime("%V").unwrap().to_string(), "07".to_string());
1089 assert_eq!(local.strftime("%v").unwrap().to_string(), "13-Feb-2009".to_string());
1090 assert_eq!(local.strftime("%W").unwrap().to_string(), "06".to_string());
1091 assert_eq!(local.strftime("%w").unwrap().to_string(), "5".to_string());
1092 // FIXME (#2350): support locale
1093 assert_eq!(local.strftime("%X").unwrap().to_string(), "15:31:30".to_string());
1094 // FIXME (#2350): support locale
1095 assert_eq!(local.strftime("%x").unwrap().to_string(), "02/13/09".to_string());
1096 assert_eq!(local.strftime("%Y").unwrap().to_string(), "2009".to_string());
1097 assert_eq!(local.strftime("%y").unwrap().to_string(), "09".to_string());
1098 // FIXME (#2350): support locale
1099 assert_eq!(local.strftime("%Z").unwrap().to_string(), "".to_string());
1100 assert_eq!(local.strftime("%z").unwrap().to_string(), "-0800".to_string());
1101 assert_eq!(local.strftime("%+").unwrap().to_string(),
1102 "2009-02-13T15:31:30-08:00".to_string());
1103 assert_eq!(local.strftime("%%").unwrap().to_string(), "%".to_string());
1104
1105 let invalid_specifiers = ["%E", "%J", "%K", "%L", "%N", "%O", "%o", "%Q", "%q"];
1106 for &sp in invalid_specifiers.iter() {
1107 assert_eq!(local.strftime(sp).unwrap_err(),
1108 InvalidFormatSpecifier(sp[1..].chars().next().unwrap()));
1109 }
1110 assert_eq!(local.strftime("%").unwrap_err(), MissingFormatConverter);
1111 assert_eq!(local.strftime("%A %").unwrap_err(), MissingFormatConverter);
1112
1113 assert_eq!(local.asctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1114 assert_eq!(local.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1115 assert_eq!(local.rfc822z().to_string(), "Fri, 13 Feb 2009 15:31:30 -0800".to_string());
1116 assert_eq!(local.rfc3339().to_string(), "2009-02-13T15:31:30-08:00".to_string());
1117
1118 assert_eq!(utc.asctime().to_string(), "Fri Feb 13 23:31:30 2009".to_string());
1119 assert_eq!(utc.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1120 assert_eq!(utc.rfc822().to_string(), "Fri, 13 Feb 2009 23:31:30 GMT".to_string());
1121 assert_eq!(utc.rfc822z().to_string(), "Fri, 13 Feb 2009 23:31:30 -0000".to_string());
1122 assert_eq!(utc.rfc3339().to_string(), "2009-02-13T23:31:30Z".to_string());
1123 }
1124
1125 #[test]
1126 fn test_timespec_eq_ord() {
1127 let a = &Timespec::new(-2, 1);
1128 let b = &Timespec::new(-1, 2);
1129 let c = &Timespec::new(1, 2);
1130 let d = &Timespec::new(2, 1);
1131 let e = &Timespec::new(2, 1);
1132
1133 assert!(d.eq(e));
1134 assert!(c.ne(e));
1135
1136 assert!(a.lt(b));
1137 assert!(b.lt(c));
1138 assert!(c.lt(d));
1139
1140 assert!(a.le(b));
1141 assert!(b.le(c));
1142 assert!(c.le(d));
1143 assert!(d.le(e));
1144 assert!(e.le(d));
1145
1146 assert!(b.ge(a));
1147 assert!(c.ge(b));
1148 assert!(d.ge(c));
1149 assert!(e.ge(d));
1150 assert!(d.ge(e));
1151
1152 assert!(b.gt(a));
1153 assert!(c.gt(b));
1154 assert!(d.gt(c));
1155 }
1156
1157 #[test]
1158 #[allow(deprecated)]
1159 fn test_timespec_hash() {
1160 use std::hash::{Hash, Hasher};
1161
1162 let c = &Timespec::new(3, 2);
1163 let d = &Timespec::new(2, 1);
1164 let e = &Timespec::new(2, 1);
1165
1166 let mut hasher = ::std::hash::SipHasher::new();
1167
1168 let d_hash:u64 = {
1169 d.hash(&mut hasher);
1170 hasher.finish()
1171 };
1172
1173 hasher = ::std::hash::SipHasher::new();
1174
1175 let e_hash:u64 = {
1176 e.hash(&mut hasher);
1177 hasher.finish()
1178 };
1179
1180 hasher = ::std::hash::SipHasher::new();
1181
1182 let c_hash:u64 = {
1183 c.hash(&mut hasher);
1184 hasher.finish()
1185 };
1186
1187 assert_eq!(d_hash, e_hash);
1188 assert!(c_hash != e_hash);
1189 }
1190
1191 #[test]
1192 fn test_timespec_add() {
1193 let a = Timespec::new(1, 2);
1194 let b = Duration::seconds(2) + Duration::nanoseconds(3);
1195 let c = a + b;
1196 assert_eq!(c.sec, 3);
1197 assert_eq!(c.nsec, 5);
1198
1199 let p = Timespec::new(1, super::NSEC_PER_SEC - 2);
1200 let q = Duration::seconds(2) + Duration::nanoseconds(2);
1201 let r = p + q;
1202 assert_eq!(r.sec, 4);
1203 assert_eq!(r.nsec, 0);
1204
1205 let u = Timespec::new(1, super::NSEC_PER_SEC - 2);
1206 let v = Duration::seconds(2) + Duration::nanoseconds(3);
1207 let w = u + v;
1208 assert_eq!(w.sec, 4);
1209 assert_eq!(w.nsec, 1);
1210
1211 let k = Timespec::new(1, 0);
1212 let l = Duration::nanoseconds(-1);
1213 let m = k + l;
1214 assert_eq!(m.sec, 0);
1215 assert_eq!(m.nsec, 999_999_999);
1216 }
1217
1218 #[test]
1219 fn test_timespec_sub() {
1220 let a = Timespec::new(2, 3);
1221 let b = Timespec::new(1, 2);
1222 let c = a - b;
1223 assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 + 1));
1224
1225 let p = Timespec::new(2, 0);
1226 let q = Timespec::new(1, 2);
1227 let r = p - q;
1228 assert_eq!(r.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 - 2));
1229
1230 let u = Timespec::new(1, 2);
1231 let v = Timespec::new(2, 3);
1232 let w = u - v;
1233 assert_eq!(w.num_nanoseconds(), Some(-super::NSEC_PER_SEC as i64 - 1));
1234 }
1235
1236 #[test]
1237 fn test_time_sub() {
1238 let a = ::now();
1239 let b = at(a.to_timespec() + Duration::seconds(5));
1240 let c = b - a;
1241 assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 * 5));
1242 }
1243
1244 #[test]
1245 fn test_steadytime_sub() {
1246 let a = SteadyTime::now();
1247 let b = a + Duration::seconds(1);
1248 assert_eq!(b - a, Duration::seconds(1));
1249 assert_eq!(a - b, Duration::seconds(-1));
1250 }
1251
1252 #[test]
1253 fn test_date_before_1970() {
1254 let early = strptime("1901-01-06", "%F").unwrap();
1255 let late = strptime("2000-01-01", "%F").unwrap();
1256 assert!(early < late);
1257 }
1258
1259 #[test]
1260 fn test_dst() {
1261 let _reset = set_time_zone_london_dst();
1262 let utc_in_feb = strptime("2015-02-01Z", "%F%z").unwrap();
1263 let utc_in_jun = strptime("2015-06-01Z", "%F%z").unwrap();
1264 let utc_in_nov = strptime("2015-11-01Z", "%F%z").unwrap();
1265 let local_in_feb = utc_in_feb.to_local();
1266 let local_in_jun = utc_in_jun.to_local();
1267 let local_in_nov = utc_in_nov.to_local();
1268
1269 assert_eq!(local_in_feb.tm_mon, 1);
1270 assert_eq!(local_in_feb.tm_hour, 0);
1271 assert_eq!(local_in_feb.tm_utcoff, 0);
1272 assert_eq!(local_in_feb.tm_isdst, 0);
1273
1274 assert_eq!(local_in_jun.tm_mon, 5);
1275 assert_eq!(local_in_jun.tm_hour, 1);
1276 assert_eq!(local_in_jun.tm_utcoff, 3600);
1277 assert_eq!(local_in_jun.tm_isdst, 1);
1278
1279 assert_eq!(local_in_nov.tm_mon, 10);
1280 assert_eq!(local_in_nov.tm_hour, 0);
1281 assert_eq!(local_in_nov.tm_utcoff, 0);
1282 assert_eq!(local_in_nov.tm_isdst, 0)
1283 }
1284}