1#![allow(missing_docs)]
2#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
18 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
19 html_root_url = "https://doc.rust-lang.org/time/")]
20#![allow(trivial_numeric_casts, ellipsis_inclusive_range_patterns)]
21
22mod display;
23mod duration;
24mod parse;
25mod sys;
26
27use std::cmp::Ordering;
28use std::error::Error;
29use std::fmt;
30use std::ops::{Add, Sub};
31
32pub use self::duration::{Duration, OutOfRangeError};
33
34use self::ParseError::{InvalidDay, InvalidDayOfMonth, InvalidDayOfWeek,
35 InvalidDayOfYear, InvalidFormatSpecifier, InvalidHour,
36 InvalidMinute, InvalidMonth, InvalidSecond, InvalidTime,
37 InvalidYear, InvalidZoneOffset, InvalidSecondsSinceEpoch,
38 MissingFormatConverter, UnexpectedCharacter};
39
40pub use self::parse::strptime;
41
42pub static NSEC_PER_SEC: i32 = 1_000_000_000;
43
44#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
50#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
51pub struct Timespec { pub sec: i64, pub nsec: i32 }
52impl Timespec {
61 pub fn new(sec: i64, nsec: i32) -> Timespec {
62 assert!(nsec >= 0 && nsec < NSEC_PER_SEC);
63 Timespec { sec: sec, nsec: nsec }
64 }
65}
66
67impl Add<Duration> for Timespec {
68 type Output = Timespec;
69
70 fn add(self, other: Duration) -> Timespec {
71 let d_sec = other.num_seconds();
72 let d_nsec = (other - Duration::seconds(d_sec))
75 .num_nanoseconds().unwrap() as i32;
76 let mut sec = self.sec + d_sec;
77 let mut nsec = self.nsec + d_nsec;
78 if nsec >= NSEC_PER_SEC {
79 nsec -= NSEC_PER_SEC;
80 sec += 1;
81 } else if nsec < 0 {
82 nsec += NSEC_PER_SEC;
83 sec -= 1;
84 }
85 Timespec::new(sec, nsec)
86 }
87}
88
89impl Sub<Duration> for Timespec {
90 type Output = Timespec;
91
92 fn sub(self, other: Duration) -> Timespec {
93 let d_sec = other.num_seconds();
94 let d_nsec = (other - Duration::seconds(d_sec))
97 .num_nanoseconds().unwrap() as i32;
98 let mut sec = self.sec - d_sec;
99 let mut nsec = self.nsec - d_nsec;
100 if nsec >= NSEC_PER_SEC {
101 nsec -= NSEC_PER_SEC;
102 sec += 1;
103 } else if nsec < 0 {
104 nsec += NSEC_PER_SEC;
105 sec -= 1;
106 }
107 Timespec::new(sec, nsec)
108 }
109}
110
111impl Sub<Timespec> for Timespec {
112 type Output = Duration;
113
114 fn sub(self, other: Timespec) -> Duration {
115 let sec = self.sec - other.sec;
116 let nsec = self.nsec - other.nsec;
117 Duration::seconds(sec) + Duration::nanoseconds(nsec as i64)
118 }
119}
120
121pub fn get_time() -> Timespec {
126 let (sec, nsec) = sys::get_time();
127 Timespec::new(sec, nsec)
128}
129
130
131#[inline]
136pub fn precise_time_ns() -> u64 {
137 sys::get_precise_ns()
138}
139
140
141#[allow(unused)]
146pub fn precise_time_s() -> f64 {
147 return (precise_time_ns() as f64) / 1000000000.;
148}
149
150#[derive(Debug, Copy, Clone)]
170pub struct PreciseTime(u64);
171
172impl PreciseTime {
173 pub fn now() -> PreciseTime {
175 PreciseTime(precise_time_ns())
176 }
177
178 #[inline]
189 pub fn to(&self, later: PreciseTime) -> Duration {
190 Duration::nanoseconds((later.0 - self.0) as i64)
197 }
198}
199
200#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
220pub struct SteadyTime(sys::SteadyTime);
221
222impl SteadyTime {
223 pub fn now() -> SteadyTime {
225 SteadyTime(sys::SteadyTime::now())
226 }
227}
228
229impl fmt::Display for SteadyTime {
230 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
231 fmt::Debug::fmt(self, fmt)
233 }
234}
235
236impl Sub for SteadyTime {
237 type Output = Duration;
238
239 fn sub(self, other: SteadyTime) -> Duration {
240 self.0 - other.0
241 }
242}
243
244impl Sub<Duration> for SteadyTime {
245 type Output = SteadyTime;
246
247 fn sub(self, other: Duration) -> SteadyTime {
248 SteadyTime(self.0 - other)
249 }
250}
251
252impl Add<Duration> for SteadyTime {
253 type Output = SteadyTime;
254
255 fn add(self, other: Duration) -> SteadyTime {
256 SteadyTime(self.0 + other)
257 }
258}
259
260#[cfg(not(windows))]
261#[allow(unused)]
262pub fn tzset() {
263 extern { fn tzset(); }
264 unsafe { tzset() }
265}
266
267
268#[cfg(windows)]
269pub fn tzset() {}
270
271#[repr(C)]
275#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
276#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
277pub struct Tm {
278 pub tm_sec: i32,
280
281 pub tm_min: i32,
283
284 pub tm_hour: i32,
286
287 pub tm_mday: i32,
289
290 pub tm_mon: i32,
292
293 pub tm_year: i32,
295
296 pub tm_wday: i32,
298
299 pub tm_yday: i32,
301
302 pub tm_isdst: i32,
308
309 pub tm_utcoff: i32,
314
315 pub tm_nsec: i32,
317}
318
319impl Add<Duration> for Tm {
320 type Output = Tm;
321
322 fn add(self, other: Duration) -> Tm {
327 at_utc(self.to_timespec() + other)
328 }
329}
330
331impl Sub<Duration> for Tm {
332 type Output = Tm;
333
334 fn sub(self, other: Duration) -> Tm {
339 at_utc(self.to_timespec() - other)
340 }
341}
342
343impl Sub<Tm> for Tm {
344 type Output = Duration;
345
346 fn sub(self, other: Tm) -> Duration {
347 self.to_timespec() - other.to_timespec()
348 }
349}
350
351impl PartialOrd for Tm {
352 fn partial_cmp(&self, other: &Tm) -> Option<Ordering> {
353 self.to_timespec().partial_cmp(&other.to_timespec())
354 }
355}
356
357impl Ord for Tm {
358 fn cmp(&self, other: &Tm) -> Ordering {
359 self.to_timespec().cmp(&other.to_timespec())
360 }
361}
362
363pub fn empty_tm() -> Tm {
364 Tm {
365 tm_sec: 0,
366 tm_min: 0,
367 tm_hour: 0,
368 tm_mday: 0,
369 tm_mon: 0,
370 tm_year: 0,
371 tm_wday: 0,
372 tm_yday: 0,
373 tm_isdst: 0,
374 tm_utcoff: 0,
375 tm_nsec: 0,
376 }
377}
378
379pub fn at_utc(clock: Timespec) -> Tm {
381 let Timespec { sec, nsec } = clock;
382 let mut tm = empty_tm();
383 sys::time_to_utc_tm(sec, &mut tm);
384 tm.tm_nsec = nsec;
385 tm
386}
387
388#[allow(unused)]
390pub fn now_utc() -> Tm {
391 at_utc(get_time())
392}
393
394pub fn at(clock: Timespec) -> Tm {
396 let Timespec { sec, nsec } = clock;
397 let mut tm = empty_tm();
398 sys::time_to_local_tm(sec, &mut tm);
399 tm.tm_nsec = nsec;
400 tm
401}
402
403pub fn now() -> Tm {
405 at(get_time())
406}
407
408impl Tm {
409 pub fn to_timespec(&self) -> Timespec {
411 let sec = match self.tm_utcoff {
412 0 => sys::utc_tm_to_time(self),
413 _ => sys::local_tm_to_time(self)
414 };
415
416 Timespec::new(sec, self.tm_nsec)
417 }
418
419 pub fn to_local(&self) -> Tm {
421 at(self.to_timespec())
422 }
423
424 #[allow(unused)]
426 pub fn to_utc(&self) -> Tm {
427 match self.tm_utcoff {
428 0 => *self,
429 _ => at_utc(self.to_timespec())
430 }
431 }
432
433 #[allow(unused)]
440 pub fn ctime(&self) -> TmFmt {
441 TmFmt {
442 tm: self,
443 format: Fmt::Ctime,
444 }
445 }
446
447 pub fn asctime(&self) -> TmFmt {
454 TmFmt {
455 tm: self,
456 format: Fmt::Str("%c"),
457 }
458 }
459
460 #[allow(unused)]
462 pub fn strftime<'a>(&'a self, format: &'a str) -> Result<TmFmt<'a>, ParseError> {
463 validate_format(TmFmt {
464 tm: self,
465 format: Fmt::Str(format),
466 })
467 }
468
469 #[allow(unused)]
476 pub fn rfc822(&self) -> TmFmt {
477 let fmt = if self.tm_utcoff == 0 {
478 "%a, %d %b %Y %T GMT"
479 } else {
480 "%a, %d %b %Y %T %Z"
481 };
482 TmFmt {
483 tm: self,
484 format: Fmt::Str(fmt),
485 }
486 }
487
488 #[allow(unused)]
495 pub fn rfc822z(&self) -> TmFmt {
496 TmFmt {
497 tm: self,
498 format: Fmt::Str("%a, %d %b %Y %T %z"),
499 }
500 }
501
502 pub fn rfc3339<'a>(&'a self) -> TmFmt {
510 TmFmt {
511 tm: self,
512 format: Fmt::Rfc3339,
513 }
514 }
515}
516
517#[derive(Copy, PartialEq, Debug, Clone)]
518pub enum ParseError {
519 InvalidSecond,
520 InvalidMinute,
521 InvalidHour,
522 InvalidDay,
523 InvalidMonth,
524 InvalidYear,
525 InvalidDayOfWeek,
526 InvalidDayOfMonth,
527 InvalidDayOfYear,
528 InvalidZoneOffset,
529 InvalidTime,
530 InvalidSecondsSinceEpoch,
531 MissingFormatConverter,
532 InvalidFormatSpecifier(char),
533 UnexpectedCharacter(char, char),
534}
535
536impl fmt::Display for ParseError {
537 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
538 match *self {
539 InvalidFormatSpecifier(ch) => {
540 write!(f, "{}: %{}", self.description(), ch)
541 }
542 UnexpectedCharacter(a, b) => {
543 write!(f, "expected: `{}`, found: `{}`", a, b)
544 }
545 _ => write!(f, "{}", self.description())
546 }
547 }
548}
549
550impl Error for ParseError {
551 fn description(&self) -> &str {
552 match *self {
553 InvalidSecond => "Invalid second.",
554 InvalidMinute => "Invalid minute.",
555 InvalidHour => "Invalid hour.",
556 InvalidDay => "Invalid day.",
557 InvalidMonth => "Invalid month.",
558 InvalidYear => "Invalid year.",
559 InvalidDayOfWeek => "Invalid day of the week.",
560 InvalidDayOfMonth => "Invalid day of the month.",
561 InvalidDayOfYear => "Invalid day of the year.",
562 InvalidZoneOffset => "Invalid zone offset.",
563 InvalidTime => "Invalid time.",
564 InvalidSecondsSinceEpoch => "Invalid seconds since epoch.",
565 MissingFormatConverter => "missing format converter after `%`",
566 InvalidFormatSpecifier(..) => "invalid format specifier",
567 UnexpectedCharacter(..) => "Unexpected character.",
568 }
569 }
570}
571
572#[derive(Debug)]
574pub struct TmFmt<'a> {
575 tm: &'a Tm,
576 format: Fmt<'a>
577}
578
579#[derive(Debug)]
580enum Fmt<'a> {
581 Str(&'a str),
582 Rfc3339,
583 Ctime,
584}
585
586fn validate_format<'a>(fmt: TmFmt<'a>) -> Result<TmFmt<'a>, ParseError> {
587
588 match (fmt.tm.tm_wday, fmt.tm.tm_mon) {
589 (0...6, 0...11) => (),
590 (_wday, 0...11) => return Err(InvalidDayOfWeek),
591 (0...6, _mon) => return Err(InvalidMonth),
592 _ => return Err(InvalidDay)
593 }
594 match fmt.format {
595 Fmt::Str(ref s) => {
596 let mut chars = s.chars();
597 loop {
598 match chars.next() {
599 Some('%') => {
600 match chars.next() {
601 Some('A') | Some('a') | Some('B') | Some('b') |
602 Some('C') | Some('c') | Some('D') | Some('d') |
603 Some('e') | Some('F') | Some('f') | Some('G') |
604 Some('g') | Some('H') | Some('h') | Some('I') |
605 Some('j') | Some('k') | Some('l') | Some('M') |
606 Some('m') | Some('n') | Some('P') | Some('p') |
607 Some('R') | Some('r') | Some('S') | Some('s') |
608 Some('T') | Some('t') | Some('U') | Some('u') |
609 Some('V') | Some('v') | Some('W') | Some('w') |
610 Some('X') | Some('x') | Some('Y') | Some('y') |
611 Some('Z') | Some('z') | Some('+') | Some('%') => (),
612
613 Some(c) => return Err(InvalidFormatSpecifier(c)),
614 None => return Err(MissingFormatConverter),
615 }
616 },
617 None => break,
618 _ => ()
619 }
620 }
621 },
622 _ => ()
623 }
624 Ok(fmt)
625}
626
627#[allow(unused)]
629pub fn strftime(format: &str, tm: &Tm) -> Result<String, ParseError> {
630 tm.strftime(format).map(|fmt| fmt.to_string())
631}
632
633#[cfg(test)]
634mod tests {
635 use ::time::sys;
636
637 use super::{Timespec, get_time, precise_time_ns, precise_time_s,
638 at_utc, at, strptime, PreciseTime, SteadyTime, ParseError, Duration};
639 use super::ParseError::{InvalidTime, InvalidYear, MissingFormatConverter,
640 InvalidFormatSpecifier};
641
642 use std::sync::{Once, Mutex, MutexGuard, LockResult};
643 use std::mem;
644
645 struct TzReset {
646 _tzreset: sys::TzReset,
647 _lock: LockResult<MutexGuard<'static, ()>>,
648 }
649
650 fn set_time_zone_la_or_london(london: bool) -> TzReset {
651 static mut LOCK: *mut Mutex<()> = 0 as *mut _;
654 static INIT: Once = Once::new();
655
656 unsafe {
657 INIT.call_once(|| {
658 LOCK = mem::transmute(Box::new(Mutex::new(())));
659 });
660
661 let timezone_lock = (*LOCK).lock();
662 let reset_func = if london {
663 sys::set_london_with_dst_time_zone()
664 } else {
665 sys::set_los_angeles_time_zone()
666 };
667 TzReset {
668 _lock: timezone_lock,
669 _tzreset: reset_func,
670 }
671 }
672 }
673
674 fn set_time_zone() -> TzReset {
675 set_time_zone_la_or_london(false)
676 }
677
678 fn set_time_zone_london_dst() -> TzReset {
679 set_time_zone_la_or_london(true)
680 }
681
682 #[test]
683 fn test_get_time() {
684 static SOME_RECENT_DATE: i64 = 1325376000i64; static SOME_FUTURE_DATE: i64 = 1577836800i64; let tv1 = get_time();
688 debug!("tv1={} sec + {} nsec", tv1.sec, tv1.nsec);
689
690 assert!(tv1.sec > SOME_RECENT_DATE);
691 assert!(tv1.nsec < 1000000000i32);
692
693 let tv2 = get_time();
694 debug!("tv2={} sec + {} nsec", tv2.sec, tv2.nsec);
695
696 assert!(tv2.sec >= tv1.sec);
697 assert!(tv2.sec < SOME_FUTURE_DATE);
698 assert!(tv2.nsec < 1000000000i32);
699 if tv2.sec == tv1.sec {
700 assert!(tv2.nsec >= tv1.nsec);
701 }
702 }
703
704 #[test]
705 fn test_precise_time() {
706 let s0 = precise_time_s();
707 debug!("s0={} sec", s0);
708 assert!(s0 > 0.);
709
710 let ns0 = precise_time_ns();
711 let ns1 = precise_time_ns();
712 debug!("ns0={} ns", ns0);
713 debug!("ns1={} ns", ns1);
714 assert!(ns1 >= ns0);
715
716 let ns2 = precise_time_ns();
717 debug!("ns2={} ns", ns2);
718 assert!(ns2 >= ns1);
719 }
720
721 #[test]
722 fn test_precise_time_to() {
723 let t0 = PreciseTime(1000);
724 let t1 = PreciseTime(1023);
725 assert_eq!(Duration::nanoseconds(23), t0.to(t1));
726 }
727
728 #[test]
729 fn test_at_utc() {
730 let _reset = set_time_zone();
731
732 let time = Timespec::new(1234567890, 54321);
733 let utc = at_utc(time);
734
735 assert_eq!(utc.tm_sec, 30);
736 assert_eq!(utc.tm_min, 31);
737 assert_eq!(utc.tm_hour, 23);
738 assert_eq!(utc.tm_mday, 13);
739 assert_eq!(utc.tm_mon, 1);
740 assert_eq!(utc.tm_year, 109);
741 assert_eq!(utc.tm_wday, 5);
742 assert_eq!(utc.tm_yday, 43);
743 assert_eq!(utc.tm_isdst, 0);
744 assert_eq!(utc.tm_utcoff, 0);
745 assert_eq!(utc.tm_nsec, 54321);
746 }
747
748 #[test]
749 fn test_at() {
750 let _reset = set_time_zone();
751
752 let time = Timespec::new(1234567890, 54321);
753 let local = at(time);
754
755 debug!("time_at: {:?}", local);
756
757 assert_eq!(local.tm_sec, 30);
758 assert_eq!(local.tm_min, 31);
759 assert_eq!(local.tm_hour, 15);
760 assert_eq!(local.tm_mday, 13);
761 assert_eq!(local.tm_mon, 1);
762 assert_eq!(local.tm_year, 109);
763 assert_eq!(local.tm_wday, 5);
764 assert_eq!(local.tm_yday, 43);
765 assert_eq!(local.tm_isdst, 0);
766 assert_eq!(local.tm_utcoff, -28800);
767 assert_eq!(local.tm_nsec, 54321);
768 }
769
770 #[test]
771 fn test_to_timespec() {
772 let _reset = set_time_zone();
773
774 let time = Timespec::new(1234567890, 54321);
775 let utc = at_utc(time);
776
777 assert_eq!(utc.to_timespec(), time);
778 assert_eq!(utc.to_local().to_timespec(), time);
779 }
780
781 #[test]
782 fn test_conversions() {
783 let _reset = set_time_zone();
784
785 let time = Timespec::new(1234567890, 54321);
786 let utc = at_utc(time);
787 let local = at(time);
788
789 assert!(local.to_local() == local);
790 assert!(local.to_utc() == utc);
791 assert!(local.to_utc().to_local() == local);
792 assert!(utc.to_utc() == utc);
793 assert!(utc.to_local() == local);
794 assert!(utc.to_local().to_utc() == utc);
795 }
796
797 #[test]
798 fn test_strptime() {
799 let _reset = set_time_zone();
800
801 match strptime("", "") {
802 Ok(ref tm) => {
803 assert!(tm.tm_sec == 0);
804 assert!(tm.tm_min == 0);
805 assert!(tm.tm_hour == 0);
806 assert!(tm.tm_mday == 0);
807 assert!(tm.tm_mon == 0);
808 assert!(tm.tm_year == 0);
809 assert!(tm.tm_wday == 0);
810 assert!(tm.tm_isdst == 0);
811 assert!(tm.tm_utcoff == 0);
812 assert!(tm.tm_nsec == 0);
813 }
814 Err(_) => ()
815 }
816
817 let format = "%a %b %e %T.%f %Y";
818 assert_eq!(strptime("", format), Err(ParseError::InvalidDay));
819 assert_eq!(strptime("Fri Feb 13 15:31:30", format),
820 Err(InvalidTime));
821
822 match strptime("Fri Feb 13 15:31:30.01234 2009", format) {
823 Err(e) => panic!("{}", e),
824 Ok(ref tm) => {
825 assert_eq!(tm.tm_sec, 30);
826 assert_eq!(tm.tm_min, 31);
827 assert_eq!(tm.tm_hour, 15);
828 assert_eq!(tm.tm_mday, 13);
829 assert_eq!(tm.tm_mon, 1);
830 assert_eq!(tm.tm_year, 109);
831 assert_eq!(tm.tm_wday, 5);
832 assert_eq!(tm.tm_yday, 0);
833 assert_eq!(tm.tm_isdst, 0);
834 assert_eq!(tm.tm_utcoff, 0);
835 assert_eq!(tm.tm_nsec, 12340000);
836 }
837 }
838
839 fn test(s: &str, format: &str) -> bool {
840 match strptime(s, format) {
841 Ok(tm) => {
842 tm.strftime(format).unwrap().to_string() == s.to_string()
843 },
844 Err(e) => panic!("{:?}, s={:?}, format={:?}", e, s, format)
845 }
846 }
847
848 fn test_oneway(s : &str, format : &str) -> bool {
849 match strptime(s, format) {
850 Ok(_) => {
851 true
855 },
856 Err(e) => panic!("{:?}, s={:?}, format={:?}", e, s, format)
857 }
858 }
859
860 let days = [
861 "Sunday".to_string(),
862 "Monday".to_string(),
863 "Tuesday".to_string(),
864 "Wednesday".to_string(),
865 "Thursday".to_string(),
866 "Friday".to_string(),
867 "Saturday".to_string()
868 ];
869 for day in days.iter() {
870 assert!(test(&day, "%A"));
871 }
872
873 let days = [
874 "Sun".to_string(),
875 "Mon".to_string(),
876 "Tue".to_string(),
877 "Wed".to_string(),
878 "Thu".to_string(),
879 "Fri".to_string(),
880 "Sat".to_string()
881 ];
882 for day in days.iter() {
883 assert!(test(&day, "%a"));
884 }
885
886 let months = [
887 "January".to_string(),
888 "February".to_string(),
889 "March".to_string(),
890 "April".to_string(),
891 "May".to_string(),
892 "June".to_string(),
893 "July".to_string(),
894 "August".to_string(),
895 "September".to_string(),
896 "October".to_string(),
897 "November".to_string(),
898 "December".to_string()
899 ];
900 for day in months.iter() {
901 assert!(test(&day, "%B"));
902 }
903
904 let months = [
905 "Jan".to_string(),
906 "Feb".to_string(),
907 "Mar".to_string(),
908 "Apr".to_string(),
909 "May".to_string(),
910 "Jun".to_string(),
911 "Jul".to_string(),
912 "Aug".to_string(),
913 "Sep".to_string(),
914 "Oct".to_string(),
915 "Nov".to_string(),
916 "Dec".to_string()
917 ];
918 for day in months.iter() {
919 assert!(test(&day, "%b"));
920 }
921
922 assert!(test("19", "%C"));
923 assert!(test("Fri Feb 3 23:31:30 2009", "%c"));
924 assert!(test("Fri Feb 13 23:31:30 2009", "%c"));
925 assert!(test("02/13/09", "%D"));
926 assert!(test("03", "%d"));
927 assert!(test("13", "%d"));
928 assert!(test(" 3", "%e"));
929 assert!(test("13", "%e"));
930 assert!(test("2009-02-13", "%F"));
931 assert!(test("03", "%H"));
932 assert!(test("13", "%H"));
933 assert!(test("03", "%I")); assert!(test("11", "%I")); assert!(test("044", "%j"));
936 assert!(test(" 3", "%k"));
937 assert!(test("13", "%k"));
938 assert!(test(" 1", "%l"));
939 assert!(test("11", "%l"));
940 assert!(test("03", "%M"));
941 assert!(test("13", "%M"));
942 assert!(test("\n", "%n"));
943 assert!(test("am", "%P"));
944 assert!(test("pm", "%P"));
945 assert!(test("AM", "%p"));
946 assert!(test("PM", "%p"));
947 assert!(test("23:31", "%R"));
948 assert!(test("11:31:30 AM", "%r"));
949 assert!(test("11:31:30 PM", "%r"));
950 assert!(test("03", "%S"));
951 assert!(test("13", "%S"));
952 assert!(test("15:31:30", "%T"));
953 assert!(test("\t", "%t"));
954 assert!(test("1", "%u"));
955 assert!(test("7", "%u"));
956 assert!(test("13-Feb-2009", "%v"));
957 assert!(test("0", "%w"));
958 assert!(test("6", "%w"));
959 assert!(test("2009", "%Y"));
960 assert!(test("09", "%y"));
961
962 assert!(test_oneway("3", "%d"));
963 assert!(test_oneway("3", "%H"));
964 assert!(test_oneway("3", "%e"));
965 assert!(test_oneway("3", "%M"));
966 assert!(test_oneway("3", "%S"));
967
968 assert!(strptime("-0000", "%z").unwrap().tm_utcoff == 0);
969 assert!(strptime("-00:00", "%z").unwrap().tm_utcoff == 0);
970 assert!(strptime("Z", "%z").unwrap().tm_utcoff == 0);
971 assert_eq!(-28800, strptime("-0800", "%z").unwrap().tm_utcoff);
972 assert_eq!(-28800, strptime("-08:00", "%z").unwrap().tm_utcoff);
973 assert_eq!(28800, strptime("+0800", "%z").unwrap().tm_utcoff);
974 assert_eq!(28800, strptime("+08:00", "%z").unwrap().tm_utcoff);
975 assert_eq!(5400, strptime("+0130", "%z").unwrap().tm_utcoff);
976 assert_eq!(5400, strptime("+01:30", "%z").unwrap().tm_utcoff);
977 assert!(test("%", "%%"));
978
979 assert_eq!(strptime("360", "%Y-%m-%d"), Err(InvalidYear));
981
982 {
984 assert!(test("1428035610", "%s"));
985 let tm = strptime("1428035610", "%s").unwrap();
986 assert_eq!(tm.tm_utcoff, 0);
987 assert_eq!(tm.tm_isdst, 0);
988 assert_eq!(tm.tm_yday, 92);
989 assert_eq!(tm.tm_wday, 5);
990 assert_eq!(tm.tm_year, 115);
991 assert_eq!(tm.tm_mon, 3);
992 assert_eq!(tm.tm_mday, 3);
993 assert_eq!(tm.tm_hour, 4);
994 }
995 }
996
997 #[test]
998 fn test_asctime() {
999 let _reset = set_time_zone();
1000
1001 let time = Timespec::new(1234567890, 54321);
1002 let utc = at_utc(time);
1003 let local = at(time);
1004
1005 debug!("test_ctime: {} {}", utc.asctime(), local.asctime());
1006
1007 assert_eq!(utc.asctime().to_string(), "Fri Feb 13 23:31:30 2009".to_string());
1008 assert_eq!(local.asctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1009 }
1010
1011 #[test]
1012 fn test_ctime() {
1013 let _reset = set_time_zone();
1014
1015 let time = Timespec::new(1234567890, 54321);
1016 let utc = at_utc(time);
1017 let local = at(time);
1018
1019 debug!("test_ctime: {} {}", utc.ctime(), local.ctime());
1020
1021 assert_eq!(utc.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1022 assert_eq!(local.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1023 }
1024
1025 #[test]
1026 fn test_strftime() {
1027 let _reset = set_time_zone();
1028
1029 let time = Timespec::new(1234567890, 54321);
1030 let utc = at_utc(time);
1031 let local = at(time);
1032
1033 assert_eq!(local.strftime("").unwrap().to_string(), "".to_string());
1034 assert_eq!(local.strftime("%A").unwrap().to_string(), "Friday".to_string());
1035 assert_eq!(local.strftime("%a").unwrap().to_string(), "Fri".to_string());
1036 assert_eq!(local.strftime("%B").unwrap().to_string(), "February".to_string());
1037 assert_eq!(local.strftime("%b").unwrap().to_string(), "Feb".to_string());
1038 assert_eq!(local.strftime("%C").unwrap().to_string(), "20".to_string());
1039 assert_eq!(local.strftime("%c").unwrap().to_string(),
1040 "Fri Feb 13 15:31:30 2009".to_string());
1041 assert_eq!(local.strftime("%D").unwrap().to_string(), "02/13/09".to_string());
1042 assert_eq!(local.strftime("%d").unwrap().to_string(), "13".to_string());
1043 assert_eq!(local.strftime("%e").unwrap().to_string(), "13".to_string());
1044 assert_eq!(local.strftime("%F").unwrap().to_string(), "2009-02-13".to_string());
1045 assert_eq!(local.strftime("%f").unwrap().to_string(), "000054321".to_string());
1046 assert_eq!(local.strftime("%G").unwrap().to_string(), "2009".to_string());
1047 assert_eq!(local.strftime("%g").unwrap().to_string(), "09".to_string());
1048 assert_eq!(local.strftime("%H").unwrap().to_string(), "15".to_string());
1049 assert_eq!(local.strftime("%h").unwrap().to_string(), "Feb".to_string());
1050 assert_eq!(local.strftime("%I").unwrap().to_string(), "03".to_string());
1051 assert_eq!(local.strftime("%j").unwrap().to_string(), "044".to_string());
1052 assert_eq!(local.strftime("%k").unwrap().to_string(), "15".to_string());
1053 assert_eq!(local.strftime("%l").unwrap().to_string(), " 3".to_string());
1054 assert_eq!(local.strftime("%M").unwrap().to_string(), "31".to_string());
1055 assert_eq!(local.strftime("%m").unwrap().to_string(), "02".to_string());
1056 assert_eq!(local.strftime("%n").unwrap().to_string(), "\n".to_string());
1057 assert_eq!(local.strftime("%P").unwrap().to_string(), "pm".to_string());
1058 assert_eq!(local.strftime("%p").unwrap().to_string(), "PM".to_string());
1059 assert_eq!(local.strftime("%R").unwrap().to_string(), "15:31".to_string());
1060 assert_eq!(local.strftime("%r").unwrap().to_string(), "03:31:30 PM".to_string());
1061 assert_eq!(local.strftime("%S").unwrap().to_string(), "30".to_string());
1062 assert_eq!(local.strftime("%s").unwrap().to_string(), "1234567890".to_string());
1063 assert_eq!(local.strftime("%T").unwrap().to_string(), "15:31:30".to_string());
1064 assert_eq!(local.strftime("%t").unwrap().to_string(), "\t".to_string());
1065 assert_eq!(local.strftime("%U").unwrap().to_string(), "06".to_string());
1066 assert_eq!(local.strftime("%u").unwrap().to_string(), "5".to_string());
1067 assert_eq!(local.strftime("%V").unwrap().to_string(), "07".to_string());
1068 assert_eq!(local.strftime("%v").unwrap().to_string(), "13-Feb-2009".to_string());
1069 assert_eq!(local.strftime("%W").unwrap().to_string(), "06".to_string());
1070 assert_eq!(local.strftime("%w").unwrap().to_string(), "5".to_string());
1071 assert_eq!(local.strftime("%X").unwrap().to_string(), "15:31:30".to_string());
1073 assert_eq!(local.strftime("%x").unwrap().to_string(), "02/13/09".to_string());
1075 assert_eq!(local.strftime("%Y").unwrap().to_string(), "2009".to_string());
1076 assert_eq!(local.strftime("%y").unwrap().to_string(), "09".to_string());
1077 assert_eq!(local.strftime("%Z").unwrap().to_string(), "".to_string());
1079 assert_eq!(local.strftime("%z").unwrap().to_string(), "-0800".to_string());
1080 assert_eq!(local.strftime("%+").unwrap().to_string(),
1081 "2009-02-13T15:31:30-08:00".to_string());
1082 assert_eq!(local.strftime("%%").unwrap().to_string(), "%".to_string());
1083
1084 let invalid_specifiers = ["%E", "%J", "%K", "%L", "%N", "%O", "%o", "%Q", "%q"];
1085 for &sp in invalid_specifiers.iter() {
1086 assert_eq!(local.strftime(sp).unwrap_err(),
1087 InvalidFormatSpecifier(sp[1..].chars().next().unwrap()));
1088 }
1089 assert_eq!(local.strftime("%").unwrap_err(), MissingFormatConverter);
1090 assert_eq!(local.strftime("%A %").unwrap_err(), MissingFormatConverter);
1091
1092 assert_eq!(local.asctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1093 assert_eq!(local.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1094 assert_eq!(local.rfc822z().to_string(), "Fri, 13 Feb 2009 15:31:30 -0800".to_string());
1095 assert_eq!(local.rfc3339().to_string(), "2009-02-13T15:31:30-08:00".to_string());
1096
1097 assert_eq!(utc.asctime().to_string(), "Fri Feb 13 23:31:30 2009".to_string());
1098 assert_eq!(utc.ctime().to_string(), "Fri Feb 13 15:31:30 2009".to_string());
1099 assert_eq!(utc.rfc822().to_string(), "Fri, 13 Feb 2009 23:31:30 GMT".to_string());
1100 assert_eq!(utc.rfc822z().to_string(), "Fri, 13 Feb 2009 23:31:30 -0000".to_string());
1101 assert_eq!(utc.rfc3339().to_string(), "2009-02-13T23:31:30Z".to_string());
1102 }
1103
1104 #[test]
1105 fn test_timespec_eq_ord() {
1106 let a = &Timespec::new(-2, 1);
1107 let b = &Timespec::new(-1, 2);
1108 let c = &Timespec::new(1, 2);
1109 let d = &Timespec::new(2, 1);
1110 let e = &Timespec::new(2, 1);
1111
1112 assert!(d.eq(e));
1113 assert!(c.ne(e));
1114
1115 assert!(a.lt(b));
1116 assert!(b.lt(c));
1117 assert!(c.lt(d));
1118
1119 assert!(a.le(b));
1120 assert!(b.le(c));
1121 assert!(c.le(d));
1122 assert!(d.le(e));
1123 assert!(e.le(d));
1124
1125 assert!(b.ge(a));
1126 assert!(c.ge(b));
1127 assert!(d.ge(c));
1128 assert!(e.ge(d));
1129 assert!(d.ge(e));
1130
1131 assert!(b.gt(a));
1132 assert!(c.gt(b));
1133 assert!(d.gt(c));
1134 }
1135
1136 #[test]
1137 #[allow(deprecated)]
1138 fn test_timespec_hash() {
1139 use std::hash::{Hash, Hasher};
1140
1141 let c = &Timespec::new(3, 2);
1142 let d = &Timespec::new(2, 1);
1143 let e = &Timespec::new(2, 1);
1144
1145 let mut hasher = ::std::hash::SipHasher::new();
1146
1147 let d_hash:u64 = {
1148 d.hash(&mut hasher);
1149 hasher.finish()
1150 };
1151
1152 hasher = ::std::hash::SipHasher::new();
1153
1154 let e_hash:u64 = {
1155 e.hash(&mut hasher);
1156 hasher.finish()
1157 };
1158
1159 hasher = ::std::hash::SipHasher::new();
1160
1161 let c_hash:u64 = {
1162 c.hash(&mut hasher);
1163 hasher.finish()
1164 };
1165
1166 assert_eq!(d_hash, e_hash);
1167 assert!(c_hash != e_hash);
1168 }
1169
1170 #[test]
1171 fn test_timespec_add() {
1172 let a = Timespec::new(1, 2);
1173 let b = Duration::seconds(2) + Duration::nanoseconds(3);
1174 let c = a + b;
1175 assert_eq!(c.sec, 3);
1176 assert_eq!(c.nsec, 5);
1177
1178 let p = Timespec::new(1, super::NSEC_PER_SEC - 2);
1179 let q = Duration::seconds(2) + Duration::nanoseconds(2);
1180 let r = p + q;
1181 assert_eq!(r.sec, 4);
1182 assert_eq!(r.nsec, 0);
1183
1184 let u = Timespec::new(1, super::NSEC_PER_SEC - 2);
1185 let v = Duration::seconds(2) + Duration::nanoseconds(3);
1186 let w = u + v;
1187 assert_eq!(w.sec, 4);
1188 assert_eq!(w.nsec, 1);
1189
1190 let k = Timespec::new(1, 0);
1191 let l = Duration::nanoseconds(-1);
1192 let m = k + l;
1193 assert_eq!(m.sec, 0);
1194 assert_eq!(m.nsec, 999_999_999);
1195 }
1196
1197 #[test]
1198 fn test_timespec_sub() {
1199 let a = Timespec::new(2, 3);
1200 let b = Timespec::new(1, 2);
1201 let c = a - b;
1202 assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 + 1));
1203
1204 let p = Timespec::new(2, 0);
1205 let q = Timespec::new(1, 2);
1206 let r = p - q;
1207 assert_eq!(r.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 - 2));
1208
1209 let u = Timespec::new(1, 2);
1210 let v = Timespec::new(2, 3);
1211 let w = u - v;
1212 assert_eq!(w.num_nanoseconds(), Some(-super::NSEC_PER_SEC as i64 - 1));
1213 }
1214
1215 #[test]
1216 fn test_time_sub() {
1217 let a = ::time::now();
1218 let b = at(a.to_timespec() + Duration::seconds(5));
1219 let c = b - a;
1220 assert_eq!(c.num_nanoseconds(), Some(super::NSEC_PER_SEC as i64 * 5));
1221 }
1222
1223 #[test]
1224 fn test_steadytime_sub() {
1225 let a = SteadyTime::now();
1226 let b = a + Duration::seconds(1);
1227 assert_eq!(b - a, Duration::seconds(1));
1228 assert_eq!(a - b, Duration::seconds(-1));
1229 }
1230
1231 #[test]
1232 fn test_date_before_1970() {
1233 let early = strptime("1901-01-06", "%F").unwrap();
1234 let late = strptime("2000-01-01", "%F").unwrap();
1235 assert!(early < late);
1236 }
1237
1238 #[test]
1239 fn test_dst() {
1240 let _reset = set_time_zone_london_dst();
1241 let utc_in_feb = strptime("2015-02-01Z", "%F%z").unwrap();
1242 let utc_in_jun = strptime("2015-06-01Z", "%F%z").unwrap();
1243 let utc_in_nov = strptime("2015-11-01Z", "%F%z").unwrap();
1244 let local_in_feb = utc_in_feb.to_local();
1245 let local_in_jun = utc_in_jun.to_local();
1246 let local_in_nov = utc_in_nov.to_local();
1247
1248 assert_eq!(local_in_feb.tm_mon, 1);
1249 assert_eq!(local_in_feb.tm_hour, 0);
1250 assert_eq!(local_in_feb.tm_utcoff, 0);
1251 assert_eq!(local_in_feb.tm_isdst, 0);
1252
1253 assert_eq!(local_in_jun.tm_mon, 5);
1254 assert_eq!(local_in_jun.tm_hour, 1);
1255 assert_eq!(local_in_jun.tm_utcoff, 3600);
1256 assert_eq!(local_in_jun.tm_isdst, 1);
1257
1258 assert_eq!(local_in_nov.tm_mon, 10);
1259 assert_eq!(local_in_nov.tm_hour, 0);
1260 assert_eq!(local_in_nov.tm_utcoff, 0);
1261 assert_eq!(local_in_nov.tm_isdst, 0)
1262 }
1263}