]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/time.rs
Merge pull request #4466 from ScriptDevil/master
[rust.git] / src / libstd / time.rs
index 02ed3692a989579f3737f42342be1e265089c498..8e7ffde65ece237ed4e9ae12bc2f29674aa10049 100644 (file)
@@ -10,7 +10,7 @@
 
 #[forbid(deprecated_mode)];
 
-use core::cmp::Eq;
+use core::cmp::{Eq, Ord};
 use core::int;
 use core::libc::{c_char, c_int, c_long, size_t, time_t};
 use core::i32;
@@ -20,6 +20,8 @@
 use core::result::{Result, Ok, Err};
 use core::str;
 
+const NSEC_PER_SEC: i32 = 1_000_000_000_i32;
+
 #[abi = "cdecl"]
 extern mod rustrt {
     #[legacy_exports]
 #[auto_decode]
 pub struct Timespec { sec: i64, nsec: i32 }
 
+/*
+ * Timespec assumes that pre-epoch Timespecs have negative sec and positive
+ * nsec fields. Darwin's and Linux's struct timespec functions handle pre-
+ * epoch timestamps using a "two steps back, one step forward" representation,
+ * though the man pages do not actually document this. For example, the time
+ * -1.2 seconds before the epoch is represented by `Timespec { sec: -2_i64,
+ * nsec: 800_000_000_i32 }`.
+ */
 impl Timespec {
-    static fn new(sec: i64, nsec: i32) -> Timespec {
+    static pure fn new(sec: i64, nsec: i32) -> Timespec {
+        assert nsec >= 0 && nsec < NSEC_PER_SEC;
         Timespec { sec: sec, nsec: nsec }
     }
 }
@@ -53,6 +64,16 @@ impl Timespec : Eq {
     pure fn ne(&self, other: &Timespec) -> bool { !self.eq(other) }
 }
 
+impl Timespec : Ord {
+    pure fn lt(&self, other: &Timespec) -> bool {
+        self.sec < other.sec ||
+            (self.sec == other.sec && self.nsec < other.nsec)
+    }
+    pure fn le(&self, other: &Timespec) -> bool { !other.lt(self) }
+    pure fn ge(&self, other: &Timespec) -> bool { !self.lt(other) }
+    pure fn gt(&self, other: &Timespec) -> bool { !self.le(other) }
+}
+
 /**
  * Returns the current time as a `timespec` containing the seconds and
  * nanoseconds since 1970-01-01T00:00:00Z.
@@ -413,22 +434,22 @@ fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
             None => Err(~"Invalid year")
           },
           'c' => {
-            parse_type(s, pos, 'a', tm)
+            parse_type(s, pos, 'a', &mut *tm)
                 .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'b', tm))
+                .chain(|pos| parse_type(s, pos, 'b', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'e', tm))
+                .chain(|pos| parse_type(s, pos, 'e', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'T', tm))
+                .chain(|pos| parse_type(s, pos, 'T', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'Y', tm))
+                .chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
           }
           'D' | 'x' => {
-            parse_type(s, pos, 'm', tm)
+            parse_type(s, pos, 'm', &mut *tm)
                 .chain(|pos| parse_char(s, pos, '/'))
-                .chain(|pos| parse_type(s, pos, 'd', tm))
+                .chain(|pos| parse_type(s, pos, 'd', &mut *tm))
                 .chain(|pos| parse_char(s, pos, '/'))
-                .chain(|pos| parse_type(s, pos, 'y', tm))
+                .chain(|pos| parse_type(s, pos, 'y', &mut *tm))
           }
           'd' => match match_digits_in_range(s, pos, 2u, false, 1_i32,
                                              31_i32) {
@@ -441,11 +462,11 @@ fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
             None => Err(~"Invalid day of the month")
           },
           'F' => {
-            parse_type(s, pos, 'Y', tm)
+            parse_type(s, pos, 'Y', &mut *tm)
                 .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'm', tm))
+                .chain(|pos| parse_type(s, pos, 'm', &mut *tm))
                 .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'd', tm))
+                .chain(|pos| parse_type(s, pos, 'd', &mut *tm))
           }
           'H' => {
             match match_digits_in_range(s, pos, 2u, false, 0_i32, 23_i32) {
@@ -519,18 +540,18 @@ fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
             None => Err(~"Invalid hour")
           },
           'R' => {
-            parse_type(s, pos, 'H', tm)
+            parse_type(s, pos, 'H', &mut *tm)
                 .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', tm))
+                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
           }
           'r' => {
-            parse_type(s, pos, 'I', tm)
+            parse_type(s, pos, 'I', &mut *tm)
                 .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', tm))
+                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'S', tm))
+                .chain(|pos| parse_type(s, pos, 'S', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'p', tm))
+                .chain(|pos| parse_type(s, pos, 'p', &mut *tm))
           }
           'S' => {
             match match_digits_in_range(s, pos, 2u, false, 0_i32, 60_i32) {
@@ -544,11 +565,11 @@ fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
           }
           //'s' {}
           'T' | 'X' => {
-            parse_type(s, pos, 'H', tm)
+            parse_type(s, pos, 'H', &mut *tm)
                 .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', tm))
+                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
                 .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'S', tm))
+                .chain(|pos| parse_type(s, pos, 'S', &mut *tm))
           }
           't' => parse_char(s, pos, '\t'),
           'u' => {
@@ -562,11 +583,11 @@ fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
             }
           }
           'v' => {
-            parse_type(s, pos, 'e', tm)
+            parse_type(s, pos, 'e', &mut *tm)
                 .chain(|pos|  parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'b', tm))
+                .chain(|pos| parse_type(s, pos, 'b', &mut *tm))
                 .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'Y', tm))
+                .chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
           }
           //'W' {}
           'w' => {
@@ -1248,4 +1269,38 @@ fn test_strftime() {
         assert utc.rfc822z() == ~"Fri, 13 Feb 2009 23:31:30 -0000";
         assert utc.rfc3339() == ~"2009-02-13T23:31:30Z";
     }
+
+    #[test]
+    fn test_timespec_eq_ord() {
+        use core::cmp::{eq, ge, gt, le, lt, ne};
+
+        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);
+
+        assert eq(d, e);
+        assert ne(c, e);
+
+        assert lt(a, b);
+        assert lt(b, c);
+        assert lt(c, d);
+
+        assert le(a, b);
+        assert le(b, c);
+        assert le(c, d);
+        assert le(d, e);
+        assert le(e, d);
+
+        assert ge(b, a);
+        assert ge(c, b);
+        assert ge(d, c);
+        assert ge(e, d);
+        assert ge(d, e);
+
+        assert gt(b, a);
+        assert gt(c, b);
+        assert gt(d, c);
+    }
 }