2013-05-27 11:55:42 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-28 22:11:41 -05:00
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::int;
|
|
|
|
use std::io;
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
use std::num;
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::str;
|
2013-05-24 21:35:29 -05:00
|
|
|
|
2013-03-22 16:00:15 -05:00
|
|
|
static NSEC_PER_SEC: i32 = 1_000_000_000_i32;
|
2013-01-21 22:50:01 -06:00
|
|
|
|
2013-03-05 14:21:02 -06:00
|
|
|
pub mod rustrt {
|
|
|
|
use super::Tm;
|
|
|
|
|
|
|
|
#[abi = "cdecl"]
|
2013-07-18 21:08:57 -05:00
|
|
|
extern {
|
2013-03-05 14:21:02 -06:00
|
|
|
pub unsafe fn get_time(sec: &mut i64, nsec: &mut i32);
|
|
|
|
|
|
|
|
pub unsafe fn precise_time_ns(ns: &mut u64);
|
|
|
|
|
|
|
|
pub unsafe fn rust_tzset();
|
2013-05-27 11:52:56 -05:00
|
|
|
|
2013-03-08 19:44:37 -06:00
|
|
|
pub unsafe fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm);
|
|
|
|
pub unsafe fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm);
|
2013-05-27 11:52:56 -05:00
|
|
|
pub unsafe fn rust_timegm(tm: &Tm) -> i64;
|
|
|
|
pub unsafe fn rust_mktime(tm: &Tm) -> i64;
|
2013-03-05 14:21:02 -06:00
|
|
|
}
|
2011-04-29 13:54:06 -05:00
|
|
|
}
|
|
|
|
|
2012-08-11 14:12:40 -05:00
|
|
|
/// A record specifying a time value in seconds and nanoseconds.
|
2013-05-15 17:55:57 -05:00
|
|
|
#[deriving(Eq, Encodable, Decodable)]
|
2012-11-27 00:22:22 -06:00
|
|
|
pub struct Timespec { sec: i64, nsec: i32 }
|
|
|
|
|
2013-01-21 22:50:01 -06:00
|
|
|
/*
|
|
|
|
* 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 }`.
|
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
impl Timespec {
|
|
|
|
pub fn new(sec: i64, nsec: i32) -> Timespec {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(nsec >= 0 && nsec < NSEC_PER_SEC);
|
2012-11-27 00:22:22 -06:00
|
|
|
Timespec { sec: sec, nsec: nsec }
|
|
|
|
}
|
|
|
|
}
|
2011-04-29 13:54:06 -05:00
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Ord for Timespec {
|
2013-03-21 23:34:30 -05:00
|
|
|
fn lt(&self, other: &Timespec) -> bool {
|
2013-01-17 01:37:21 -06:00
|
|
|
self.sec < other.sec ||
|
|
|
|
(self.sec == other.sec && self.nsec < other.nsec)
|
|
|
|
}
|
2013-03-21 23:34:30 -05:00
|
|
|
fn le(&self, other: &Timespec) -> bool { !other.lt(self) }
|
|
|
|
fn ge(&self, other: &Timespec) -> bool { !self.lt(other) }
|
|
|
|
fn gt(&self, other: &Timespec) -> bool { !self.le(other) }
|
2013-01-17 01:37:21 -06:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Returns the current time as a `timespec` containing the seconds and
|
2012-08-11 14:12:40 -05:00
|
|
|
* nanoseconds since 1970-01-01T00:00:00Z.
|
2012-07-04 16:53:12 -05:00
|
|
|
*/
|
2012-10-05 18:17:10 -05:00
|
|
|
pub fn get_time() -> Timespec {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let mut sec = 0i64;
|
|
|
|
let mut nsec = 0i32;
|
|
|
|
rustrt::get_time(&mut sec, &mut nsec);
|
|
|
|
return Timespec::new(sec, nsec);
|
|
|
|
}
|
2012-10-05 18:17:10 -05:00
|
|
|
}
|
|
|
|
|
2011-06-28 19:58:44 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Returns the current value of a high-resolution performance counter
|
|
|
|
* in nanoseconds since an unspecified epoch.
|
|
|
|
*/
|
2012-10-05 18:17:10 -05:00
|
|
|
pub fn precise_time_ns() -> u64 {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let mut ns = 0u64;
|
|
|
|
rustrt::precise_time_ns(&mut ns);
|
|
|
|
ns
|
|
|
|
}
|
2012-10-05 18:17:10 -05:00
|
|
|
}
|
|
|
|
|
2011-06-28 19:58:44 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Returns the current value of a high-resolution performance counter
|
|
|
|
* in seconds since an unspecified epoch.
|
|
|
|
*/
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn precise_time_s() -> float {
|
2012-08-01 19:30:05 -05:00
|
|
|
return (precise_time_ns() as float) / 1000000000.;
|
2011-08-19 17:16:48 -05:00
|
|
|
}
|
2012-02-18 03:32:52 -06:00
|
|
|
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn tzset() {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
rustrt::rust_tzset();
|
|
|
|
}
|
2012-04-13 19:33:02 -05:00
|
|
|
}
|
|
|
|
|
2013-05-15 17:55:57 -05:00
|
|
|
#[deriving(Eq, Encodable, Decodable)]
|
2012-11-27 00:22:22 -06:00
|
|
|
pub struct Tm {
|
2012-06-29 18:26:56 -05:00
|
|
|
tm_sec: i32, // seconds after the minute ~[0-60]
|
|
|
|
tm_min: i32, // minutes after the hour ~[0-59]
|
|
|
|
tm_hour: i32, // hours after midnight ~[0-23]
|
|
|
|
tm_mday: i32, // days of the month ~[1-31]
|
|
|
|
tm_mon: i32, // months since January ~[0-11]
|
2012-04-03 12:32:26 -05:00
|
|
|
tm_year: i32, // years since 1900
|
2012-06-29 18:26:56 -05:00
|
|
|
tm_wday: i32, // days since Sunday ~[0-6]
|
|
|
|
tm_yday: i32, // days since January 1 ~[0-365]
|
2012-04-03 12:32:26 -05:00
|
|
|
tm_isdst: i32, // Daylight Savings Time flag
|
|
|
|
tm_gmtoff: i32, // offset from UTC in seconds
|
2012-07-14 00:57:48 -05:00
|
|
|
tm_zone: ~str, // timezone abbreviation
|
2012-04-03 12:32:26 -05:00
|
|
|
tm_nsec: i32, // nanoseconds
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:34:30 -05:00
|
|
|
pub fn empty_tm() -> Tm {
|
2012-11-27 00:22:22 -06:00
|
|
|
Tm {
|
2012-04-03 12:32:26 -05:00
|
|
|
tm_sec: 0_i32,
|
|
|
|
tm_min: 0_i32,
|
|
|
|
tm_hour: 0_i32,
|
|
|
|
tm_mday: 0_i32,
|
|
|
|
tm_mon: 0_i32,
|
|
|
|
tm_year: 0_i32,
|
|
|
|
tm_wday: 0_i32,
|
|
|
|
tm_yday: 0_i32,
|
|
|
|
tm_isdst: 0_i32,
|
|
|
|
tm_gmtoff: 0_i32,
|
2012-07-14 00:57:48 -05:00
|
|
|
tm_zone: ~"",
|
2012-04-03 12:32:26 -05:00
|
|
|
tm_nsec: 0_i32,
|
2012-11-27 00:22:22 -06:00
|
|
|
}
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the specified time in UTC
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn at_utc(clock: Timespec) -> Tm {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-04-12 00:10:12 -05:00
|
|
|
let Timespec { sec, nsec } = clock;
|
2013-01-10 23:23:07 -06:00
|
|
|
let mut tm = empty_tm();
|
2013-03-08 19:44:37 -06:00
|
|
|
rustrt::rust_gmtime(sec, nsec, &mut tm);
|
2013-02-15 01:30:30 -06:00
|
|
|
tm
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the current time in UTC
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn now_utc() -> Tm {
|
2012-04-03 12:32:26 -05:00
|
|
|
at_utc(get_time())
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the specified time in the local timezone
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn at(clock: Timespec) -> Tm {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-04-12 00:10:12 -05:00
|
|
|
let Timespec { sec, nsec } = clock;
|
2013-01-10 23:23:07 -06:00
|
|
|
let mut tm = empty_tm();
|
2013-03-08 19:44:37 -06:00
|
|
|
rustrt::rust_localtime(sec, nsec, &mut tm);
|
2013-02-15 01:30:30 -06:00
|
|
|
tm
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the current time in the local timezone
|
2012-09-28 18:24:57 -05:00
|
|
|
pub fn now() -> Tm {
|
2012-04-03 12:32:26 -05:00
|
|
|
at(get_time())
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Parses the time from the string according to the format string.
|
2013-03-21 23:34:30 -05:00
|
|
|
pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
2013-04-08 15:50:34 -05:00
|
|
|
do_strptime(s, format)
|
2012-11-17 11:11:57 -06:00
|
|
|
}
|
|
|
|
|
2012-11-17 11:17:43 -06:00
|
|
|
/// Formats the time according to the format string.
|
2013-03-21 23:34:30 -05:00
|
|
|
pub fn strftime(format: &str, tm: &Tm) -> ~str {
|
2013-04-08 15:50:34 -05:00
|
|
|
do_strftime(format, tm)
|
2012-11-17 11:11:57 -06:00
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl Tm {
|
2012-11-17 11:11:57 -06:00
|
|
|
/// Convert time to the seconds from January 1, 1970
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn to_timespec(&self) -> Timespec {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-05-27 11:52:56 -05:00
|
|
|
let sec = match self.tm_gmtoff {
|
|
|
|
0_i32 => rustrt::rust_timegm(self),
|
|
|
|
_ => rustrt::rust_mktime(self)
|
|
|
|
};
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
Timespec::new(sec, self.tm_nsec)
|
2012-11-17 11:11:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert time to the local timezone
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn to_local(&self) -> Tm {
|
2012-11-17 11:11:57 -06:00
|
|
|
at(self.to_timespec())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert time to the UTC
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn to_utc(&self) -> Tm {
|
2012-11-17 11:11:57 -06:00
|
|
|
at_utc(self.to_timespec())
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a string of the current time in the form
|
|
|
|
* "Thu Jan 1 00:00:00 1970".
|
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn ctime(&self) -> ~str { self.strftime("%c") }
|
2012-11-17 11:11:57 -06:00
|
|
|
|
|
|
|
/// Formats the time according to the format string.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn strftime(&self, format: &str) -> ~str {
|
2013-02-15 01:30:30 -06:00
|
|
|
strftime(format, self)
|
2012-11-27 00:22:22 -06:00
|
|
|
}
|
2012-11-17 11:11:57 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a time string formatted according to RFC 822.
|
|
|
|
*
|
|
|
|
* local: "Thu, 22 Mar 2012 07:53:18 PST"
|
|
|
|
* utc: "Thu, 22 Mar 2012 14:53:18 UTC"
|
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn rfc822(&self) -> ~str {
|
2012-11-17 11:11:57 -06:00
|
|
|
if self.tm_gmtoff == 0_i32 {
|
2013-05-19 00:07:44 -05:00
|
|
|
self.strftime("%a, %d %b %Y %T GMT")
|
2012-11-17 11:11:57 -06:00
|
|
|
} else {
|
2013-05-19 00:07:44 -05:00
|
|
|
self.strftime("%a, %d %b %Y %T %Z")
|
2012-11-17 11:11:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a time string formatted according to RFC 822 with Zulu time.
|
|
|
|
*
|
|
|
|
* local: "Thu, 22 Mar 2012 07:53:18 -0700"
|
|
|
|
* utc: "Thu, 22 Mar 2012 14:53:18 -0000"
|
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn rfc822z(&self) -> ~str {
|
2013-05-19 00:07:44 -05:00
|
|
|
self.strftime("%a, %d %b %Y %T %z")
|
2012-11-17 11:11:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a time string formatted according to ISO 8601.
|
|
|
|
*
|
|
|
|
* local: "2012-02-22T07:53:18-07:00"
|
|
|
|
* utc: "2012-02-22T14:53:18Z"
|
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn rfc3339(&self) -> ~str {
|
2012-11-17 11:11:57 -06:00
|
|
|
if self.tm_gmtoff == 0_i32 {
|
2013-05-19 00:07:44 -05:00
|
|
|
self.strftime("%Y-%m-%dT%H:%M:%SZ")
|
2012-11-17 11:11:57 -06:00
|
|
|
} else {
|
2013-05-19 00:07:44 -05:00
|
|
|
let s = self.strftime("%Y-%m-%dT%H:%M:%S");
|
2012-11-17 11:11:57 -06:00
|
|
|
let sign = if self.tm_gmtoff > 0_i32 { '+' } else { '-' };
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
let mut m = num::abs(self.tm_gmtoff) / 60_i32;
|
2012-11-17 11:11:57 -06:00
|
|
|
let h = m / 60_i32;
|
|
|
|
m -= h * 60_i32;
|
|
|
|
s + fmt!("%c%02d:%02d", sign, h as int, m as int)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
2012-08-24 14:03:11 -05:00
|
|
|
fn match_str(s: &str, pos: uint, needle: &str) -> bool {
|
2012-04-03 12:37:02 -05:00
|
|
|
let mut i = pos;
|
2013-06-08 09:38:58 -05:00
|
|
|
for needle.bytes_iter().advance |ch| {
|
2012-04-03 12:37:02 -05:00
|
|
|
if s[i] != ch {
|
2012-08-01 19:30:05 -05:00
|
|
|
return false;
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return true;
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2012-08-24 14:03:11 -05:00
|
|
|
fn match_strs(ss: &str, pos: uint, strs: &[(~str, i32)])
|
2012-08-20 14:23:37 -05:00
|
|
|
-> Option<(i32, uint)> {
|
2012-04-03 12:37:02 -05:00
|
|
|
let mut i = 0u;
|
2012-11-27 00:22:22 -06:00
|
|
|
let len = strs.len();
|
2012-04-03 12:37:02 -05:00
|
|
|
while i < len {
|
2013-06-20 00:15:50 -05:00
|
|
|
match strs[i] { // can't use let due to let-pattern bugs
|
2013-05-29 18:59:33 -05:00
|
|
|
(ref needle, value) => {
|
|
|
|
if match_str(ss, pos, *needle) {
|
2013-06-09 09:44:58 -05:00
|
|
|
return Some((value, pos + needle.len()));
|
2013-05-29 18:59:33 -05:00
|
|
|
}
|
|
|
|
}
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
|
2012-08-20 14:23:37 -05:00
|
|
|
None
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2012-08-24 14:03:11 -05:00
|
|
|
fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
|
2012-08-20 14:23:37 -05:00
|
|
|
-> Option<(i32, uint)> {
|
2012-04-03 12:37:02 -05:00
|
|
|
let mut pos = pos;
|
|
|
|
let mut value = 0_i32;
|
|
|
|
|
|
|
|
let mut i = 0u;
|
|
|
|
while i < digits {
|
2013-06-10 06:46:36 -05:00
|
|
|
let range = ss.char_range_at(pos);
|
2012-11-26 22:05:19 -06:00
|
|
|
pos = range.next;
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2012-11-26 22:05:19 -06:00
|
|
|
match range.ch {
|
2012-09-01 20:38:05 -05:00
|
|
|
'0' .. '9' => {
|
2012-11-26 22:05:19 -06:00
|
|
|
value = value * 10_i32 + (range.ch as i32 - '0' as i32);
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
' ' if ws => (),
|
2012-08-20 14:23:37 -05:00
|
|
|
_ => return None
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
|
2012-08-20 14:23:37 -05:00
|
|
|
Some((value, pos))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2013-01-13 22:31:09 -06:00
|
|
|
fn match_digits_in_range(ss: &str, pos: uint, digits: uint, ws: bool,
|
|
|
|
min: i32, max: i32) -> Option<(i32, uint)> {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits(ss, pos, digits, ws) {
|
|
|
|
Some((val, pos)) if val >= min && val <= max => {
|
|
|
|
Some((val, pos))
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-26 18:54:31 -05:00
|
|
|
fn parse_char(s: &str, pos: uint, c: char) -> Result<uint, ~str> {
|
2013-06-10 06:46:36 -05:00
|
|
|
let range = s.char_range_at(pos);
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2012-11-26 22:05:19 -06:00
|
|
|
if c == range.ch {
|
|
|
|
Ok(range.next)
|
2012-04-03 12:37:02 -05:00
|
|
|
} else {
|
2012-08-26 18:54:31 -05:00
|
|
|
Err(fmt!("Expected %?, found %?",
|
2012-04-03 12:37:02 -05:00
|
|
|
str::from_char(c),
|
2012-11-26 22:05:19 -06:00
|
|
|
str::from_char(range.ch)))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-27 00:22:22 -06:00
|
|
|
fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
|
2012-08-26 18:54:31 -05:00
|
|
|
-> Result<uint, ~str> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match ch {
|
2013-05-19 00:07:44 -05:00
|
|
|
'A' => match match_strs(s, pos, [
|
2012-08-03 21:59:04 -05:00
|
|
|
(~"Sunday", 0_i32),
|
|
|
|
(~"Monday", 1_i32),
|
|
|
|
(~"Tuesday", 2_i32),
|
|
|
|
(~"Wednesday", 3_i32),
|
|
|
|
(~"Thursday", 4_i32),
|
|
|
|
(~"Friday", 5_i32),
|
|
|
|
(~"Saturday", 6_i32)
|
|
|
|
]) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid day")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2013-05-19 00:07:44 -05:00
|
|
|
'a' => match match_strs(s, pos, [
|
2012-08-03 21:59:04 -05:00
|
|
|
(~"Sun", 0_i32),
|
|
|
|
(~"Mon", 1_i32),
|
|
|
|
(~"Tue", 2_i32),
|
|
|
|
(~"Wed", 3_i32),
|
|
|
|
(~"Thu", 4_i32),
|
|
|
|
(~"Fri", 5_i32),
|
|
|
|
(~"Sat", 6_i32)
|
|
|
|
]) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid day")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2013-05-19 00:07:44 -05:00
|
|
|
'B' => match match_strs(s, pos, [
|
2012-08-03 21:59:04 -05:00
|
|
|
(~"January", 0_i32),
|
|
|
|
(~"February", 1_i32),
|
|
|
|
(~"March", 2_i32),
|
|
|
|
(~"April", 3_i32),
|
|
|
|
(~"May", 4_i32),
|
|
|
|
(~"June", 5_i32),
|
|
|
|
(~"July", 6_i32),
|
|
|
|
(~"August", 7_i32),
|
|
|
|
(~"September", 8_i32),
|
|
|
|
(~"October", 9_i32),
|
|
|
|
(~"November", 10_i32),
|
|
|
|
(~"December", 11_i32)
|
|
|
|
]) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_mon = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid month")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2013-05-19 00:07:44 -05:00
|
|
|
'b' | 'h' => match match_strs(s, pos, [
|
2012-08-03 21:59:04 -05:00
|
|
|
(~"Jan", 0_i32),
|
|
|
|
(~"Feb", 1_i32),
|
|
|
|
(~"Mar", 2_i32),
|
|
|
|
(~"Apr", 3_i32),
|
|
|
|
(~"May", 4_i32),
|
|
|
|
(~"Jun", 5_i32),
|
|
|
|
(~"Jul", 6_i32),
|
|
|
|
(~"Aug", 7_i32),
|
|
|
|
(~"Sep", 8_i32),
|
|
|
|
(~"Oct", 9_i32),
|
|
|
|
(~"Nov", 10_i32),
|
|
|
|
(~"Dec", 11_i32)
|
|
|
|
]) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_mon = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid month")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2013-01-13 22:31:09 -06:00
|
|
|
'C' => match match_digits_in_range(s, pos, 2u, false, 0_i32,
|
|
|
|
99_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
2012-08-03 21:59:04 -05:00
|
|
|
tm.tm_year += (v * 100_i32) - 1900_i32;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid year")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-03 21:59:04 -05:00
|
|
|
'c' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'a', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ' '))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'b', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ' '))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'e', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ' '))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'T', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ' '))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'D' | 'x' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'm', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '/'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'd', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '/'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'y', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2013-01-13 22:31:09 -06:00
|
|
|
'd' => match match_digits_in_range(s, pos, 2u, false, 1_i32,
|
|
|
|
31_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_mday = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid day of the month")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2013-01-13 22:31:09 -06:00
|
|
|
'e' => match match_digits_in_range(s, pos, 2u, true, 1_i32,
|
|
|
|
31_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_mday = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid day of the month")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-03 21:59:04 -05:00
|
|
|
'F' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'Y', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '-'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'm', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '-'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'd', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'H' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 0_i32, 23_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_hour = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid hour")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'I' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 1_i32, 12_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_hour = if v == 12_i32 { 0_i32 } else { v };
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid hour")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'j' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 3u, false, 1_i32, 366_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_yday = v - 1_i32;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2013-01-13 05:05:37 -06:00
|
|
|
None => Err(~"Invalid day of year")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'k' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, true, 0_i32, 23_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_hour = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid hour")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'l' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, true, 1_i32, 12_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_hour = if v == 12_i32 { 0_i32 } else { v };
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid hour")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'M' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 0_i32, 59_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_min = v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid minute")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'm' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 1_i32, 12_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_mon = v - 1_i32;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid month")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'n' => parse_char(s, pos, '\n'),
|
2012-08-06 14:34:08 -05:00
|
|
|
'P' => match match_strs(s, pos,
|
2013-05-19 00:07:44 -05:00
|
|
|
[(~"am", 0_i32), (~"pm", 12_i32)]) {
|
2012-08-06 14:34:08 -05:00
|
|
|
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid hour")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-06 14:34:08 -05:00
|
|
|
'p' => match match_strs(s, pos,
|
2013-05-19 00:07:44 -05:00
|
|
|
[(~"AM", 0_i32), (~"PM", 12_i32)]) {
|
2012-08-06 14:34:08 -05:00
|
|
|
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) }
|
|
|
|
None => Err(~"Invalid hour")
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-03 21:59:04 -05:00
|
|
|
'R' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'H', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ':'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'M', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'r' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'I', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ':'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'M', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ':'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'S', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ' '))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'p', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'S' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 0_i32, 60_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_sec = v;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid second")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//'s' {}
|
2012-08-03 21:59:04 -05:00
|
|
|
'T' | 'X' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'H', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ':'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'M', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, ':'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'S', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
't' => parse_char(s, pos, '\t'),
|
|
|
|
'u' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 1u, false, 1_i32, 7_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
2013-01-22 23:41:56 -06:00
|
|
|
tm.tm_wday = if v == 7 { 0 } else { v };
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2013-01-13 05:05:37 -06:00
|
|
|
None => Err(~"Invalid day of week")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'v' => {
|
2013-01-11 23:01:42 -06:00
|
|
|
parse_type(s, pos, 'e', &mut *tm)
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '-'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'b', &mut *tm))
|
2012-12-20 23:15:49 -06:00
|
|
|
.chain(|pos| parse_char(s, pos, '-'))
|
2013-01-11 23:01:42 -06:00
|
|
|
.chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
//'W' {}
|
2012-08-03 21:59:04 -05:00
|
|
|
'w' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 1u, false, 0_i32, 6_i32) {
|
2012-08-26 18:54:31 -05:00
|
|
|
Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
|
2013-01-13 05:05:37 -06:00
|
|
|
None => Err(~"Invalid day of week")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//'X' {}
|
|
|
|
//'x' {}
|
2012-08-03 21:59:04 -05:00
|
|
|
'Y' => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match match_digits(s, pos, 4u, false) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
tm.tm_year = v - 1900_i32;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2013-01-13 05:05:37 -06:00
|
|
|
None => Err(~"Invalid year")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'y' => {
|
2013-01-13 05:38:33 -06:00
|
|
|
match match_digits_in_range(s, pos, 2u, false, 0_i32, 99_i32) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
2013-01-13 05:18:34 -06:00
|
|
|
tm.tm_year = v;
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2013-01-13 05:05:37 -06:00
|
|
|
None => Err(~"Invalid year")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'Z' => {
|
2013-05-19 00:07:44 -05:00
|
|
|
if match_str(s, pos, "UTC") || match_str(s, pos, "GMT") {
|
2012-04-03 12:37:02 -05:00
|
|
|
tm.tm_gmtoff = 0_i32;
|
2012-07-14 00:57:48 -05:00
|
|
|
tm.tm_zone = ~"UTC";
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos + 3u)
|
2012-04-03 12:37:02 -05:00
|
|
|
} else {
|
|
|
|
// It's odd, but to maintain compatibility with c's
|
|
|
|
// strptime we ignore the timezone.
|
|
|
|
let mut pos = pos;
|
2013-06-09 09:44:58 -05:00
|
|
|
let len = s.len();
|
2012-04-03 12:37:02 -05:00
|
|
|
while pos < len {
|
2013-06-10 06:46:36 -05:00
|
|
|
let range = s.char_range_at(pos);
|
2012-11-26 22:05:19 -06:00
|
|
|
pos = range.next;
|
|
|
|
if range.ch == ' ' { break; }
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'z' => {
|
2013-06-10 06:46:36 -05:00
|
|
|
let range = s.char_range_at(pos);
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2012-11-26 22:05:19 -06:00
|
|
|
if range.ch == '+' || range.ch == '-' {
|
|
|
|
match match_digits(s, range.next, 4u, false) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(item) => {
|
2012-04-03 12:37:02 -05:00
|
|
|
let (v, pos) = item;
|
|
|
|
if v == 0_i32 {
|
|
|
|
tm.tm_gmtoff = 0_i32;
|
2012-07-14 00:57:48 -05:00
|
|
|
tm.tm_zone = ~"UTC";
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2012-08-26 18:54:31 -05:00
|
|
|
Ok(pos)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
None => Err(~"Invalid zone offset")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
} else {
|
2012-08-26 18:54:31 -05:00
|
|
|
Err(~"Invalid zone offset")
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'%' => parse_char(s, pos, '%'),
|
|
|
|
ch => {
|
2012-08-26 18:54:31 -05:00
|
|
|
Err(fmt!("unknown formatting type: %?", str::from_char(ch)))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-29 13:10:16 -05:00
|
|
|
do io::with_str_reader(format) |rdr| {
|
2012-11-27 00:22:22 -06:00
|
|
|
let mut tm = Tm {
|
2012-11-17 11:17:43 -06:00
|
|
|
tm_sec: 0_i32,
|
|
|
|
tm_min: 0_i32,
|
|
|
|
tm_hour: 0_i32,
|
|
|
|
tm_mday: 0_i32,
|
|
|
|
tm_mon: 0_i32,
|
|
|
|
tm_year: 0_i32,
|
|
|
|
tm_wday: 0_i32,
|
|
|
|
tm_yday: 0_i32,
|
|
|
|
tm_isdst: 0_i32,
|
|
|
|
tm_gmtoff: 0_i32,
|
|
|
|
tm_zone: ~"",
|
|
|
|
tm_nsec: 0_i32,
|
2012-04-03 12:37:02 -05:00
|
|
|
};
|
|
|
|
let mut pos = 0u;
|
2013-06-09 09:44:58 -05:00
|
|
|
let len = s.len();
|
2012-08-26 18:54:31 -05:00
|
|
|
let mut result = Err(~"Invalid time");
|
2012-04-03 12:37:02 -05:00
|
|
|
|
|
|
|
while !rdr.eof() && pos < len {
|
2013-06-10 06:46:36 -05:00
|
|
|
let range = s.char_range_at(pos);
|
2012-11-26 22:05:19 -06:00
|
|
|
let ch = range.ch;
|
|
|
|
let next = range.next;
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match rdr.read_char() {
|
2012-11-27 00:22:22 -06:00
|
|
|
'%' => {
|
|
|
|
match parse_type(s, pos, rdr.read_char(), &mut tm) {
|
|
|
|
Ok(next) => pos = next,
|
2013-02-15 01:30:30 -06:00
|
|
|
Err(e) => { result = Err(e); break; }
|
2012-11-27 00:22:22 -06:00
|
|
|
}
|
|
|
|
},
|
|
|
|
c => {
|
|
|
|
if c != ch { break }
|
|
|
|
pos = next;
|
|
|
|
}
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos == len && rdr.eof() {
|
2012-11-27 00:22:22 -06:00
|
|
|
Ok(Tm {
|
2012-04-03 12:37:02 -05:00
|
|
|
tm_sec: tm.tm_sec,
|
|
|
|
tm_min: tm.tm_min,
|
|
|
|
tm_hour: tm.tm_hour,
|
|
|
|
tm_mday: tm.tm_mday,
|
|
|
|
tm_mon: tm.tm_mon,
|
|
|
|
tm_year: tm.tm_year,
|
|
|
|
tm_wday: tm.tm_wday,
|
|
|
|
tm_yday: tm.tm_yday,
|
|
|
|
tm_isdst: tm.tm_isdst,
|
|
|
|
tm_gmtoff: tm.tm_gmtoff,
|
2013-07-02 14:47:32 -05:00
|
|
|
tm_zone: tm.tm_zone.clone(),
|
2012-04-03 12:37:02 -05:00
|
|
|
tm_nsec: tm.tm_nsec,
|
2012-11-27 00:22:22 -06:00
|
|
|
})
|
2013-02-15 01:30:30 -06:00
|
|
|
} else { result }
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-27 00:22:22 -06:00
|
|
|
priv fn do_strftime(format: &str, tm: &Tm) -> ~str {
|
2012-08-29 18:09:41 -05:00
|
|
|
fn parse_type(ch: char, tm: &Tm) -> ~str {
|
2012-06-21 18:44:10 -05:00
|
|
|
//FIXME (#2350): Implement missing types.
|
2012-10-12 14:32:36 -05:00
|
|
|
let die = || fmt!("strftime: can't understand this format %c ", ch);
|
2012-08-15 13:55:17 -05:00
|
|
|
match ch {
|
|
|
|
'A' => match tm.tm_wday as int {
|
2012-08-03 21:59:04 -05:00
|
|
|
0 => ~"Sunday",
|
|
|
|
1 => ~"Monday",
|
|
|
|
2 => ~"Tuesday",
|
|
|
|
3 => ~"Wednesday",
|
|
|
|
4 => ~"Thursday",
|
|
|
|
5 => ~"Friday",
|
2012-08-15 13:55:17 -05:00
|
|
|
6 => ~"Saturday",
|
|
|
|
_ => die()
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-15 13:55:17 -05:00
|
|
|
'a' => match tm.tm_wday as int {
|
2012-08-03 21:59:04 -05:00
|
|
|
0 => ~"Sun",
|
|
|
|
1 => ~"Mon",
|
|
|
|
2 => ~"Tue",
|
|
|
|
3 => ~"Wed",
|
|
|
|
4 => ~"Thu",
|
|
|
|
5 => ~"Fri",
|
2012-08-15 13:55:17 -05:00
|
|
|
6 => ~"Sat",
|
|
|
|
_ => die()
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-15 13:55:17 -05:00
|
|
|
'B' => match tm.tm_mon as int {
|
2012-08-03 21:59:04 -05:00
|
|
|
0 => ~"January",
|
|
|
|
1 => ~"February",
|
|
|
|
2 => ~"March",
|
|
|
|
3 => ~"April",
|
|
|
|
4 => ~"May",
|
|
|
|
5 => ~"June",
|
|
|
|
6 => ~"July",
|
|
|
|
7 => ~"August",
|
|
|
|
8 => ~"September",
|
|
|
|
9 => ~"October",
|
|
|
|
10 => ~"November",
|
2012-08-15 13:55:17 -05:00
|
|
|
11 => ~"December",
|
|
|
|
_ => die()
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-15 13:55:17 -05:00
|
|
|
'b' | 'h' => match tm.tm_mon as int {
|
2012-08-03 21:59:04 -05:00
|
|
|
0 => ~"Jan",
|
|
|
|
1 => ~"Feb",
|
|
|
|
2 => ~"Mar",
|
|
|
|
3 => ~"Apr",
|
|
|
|
4 => ~"May",
|
|
|
|
5 => ~"Jun",
|
|
|
|
6 => ~"Jul",
|
|
|
|
7 => ~"Aug",
|
|
|
|
8 => ~"Sep",
|
|
|
|
9 => ~"Oct",
|
|
|
|
10 => ~"Nov",
|
|
|
|
11 => ~"Dec",
|
2012-08-15 13:55:17 -05:00
|
|
|
_ => die()
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-08-22 19:24:52 -05:00
|
|
|
'C' => fmt!("%02d", (tm.tm_year as int + 1900) / 100),
|
2012-08-03 21:59:04 -05:00
|
|
|
'c' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s %s %s %s %s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('a', tm),
|
|
|
|
parse_type('b', tm),
|
|
|
|
parse_type('e', tm),
|
|
|
|
parse_type('T', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('Y', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'D' | 'x' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s/%s/%s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('m', tm),
|
|
|
|
parse_type('d', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('y', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-22 19:24:52 -05:00
|
|
|
'd' => fmt!("%02d", tm.tm_mday as int),
|
|
|
|
'e' => fmt!("%2d", tm.tm_mday as int),
|
2012-08-03 21:59:04 -05:00
|
|
|
'F' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s-%s-%s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('Y', tm),
|
|
|
|
parse_type('m', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('d', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
//'G' {}
|
|
|
|
//'g' {}
|
2012-08-22 19:24:52 -05:00
|
|
|
'H' => fmt!("%02d", tm.tm_hour as int),
|
2012-08-03 21:59:04 -05:00
|
|
|
'I' => {
|
2012-04-03 12:38:54 -05:00
|
|
|
let mut h = tm.tm_hour as int;
|
|
|
|
if h == 0 { h = 12 }
|
|
|
|
if h > 12 { h -= 12 }
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%02d", h)
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-22 19:24:52 -05:00
|
|
|
'j' => fmt!("%03d", tm.tm_yday as int + 1),
|
|
|
|
'k' => fmt!("%2d", tm.tm_hour as int),
|
2012-08-03 21:59:04 -05:00
|
|
|
'l' => {
|
2012-04-03 12:38:54 -05:00
|
|
|
let mut h = tm.tm_hour as int;
|
|
|
|
if h == 0 { h = 12 }
|
|
|
|
if h > 12 { h -= 12 }
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%2d", h)
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-22 19:24:52 -05:00
|
|
|
'M' => fmt!("%02d", tm.tm_min as int),
|
|
|
|
'm' => fmt!("%02d", tm.tm_mon as int + 1),
|
2012-08-03 21:59:04 -05:00
|
|
|
'n' => ~"\n",
|
2013-03-20 15:24:09 -05:00
|
|
|
'P' => if (tm.tm_hour as int) < 12 { ~"am" } else { ~"pm" },
|
|
|
|
'p' => if (tm.tm_hour as int) < 12 { ~"AM" } else { ~"PM" },
|
2012-08-03 21:59:04 -05:00
|
|
|
'R' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s:%s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('H', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('M', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
'r' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s:%s:%s %s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('I', tm),
|
|
|
|
parse_type('M', tm),
|
|
|
|
parse_type('S', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('p', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-22 19:24:52 -05:00
|
|
|
'S' => fmt!("%02d", tm.tm_sec as int),
|
|
|
|
's' => fmt!("%d", tm.to_timespec().sec as int),
|
2012-08-03 21:59:04 -05:00
|
|
|
'T' | 'X' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s:%s:%s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('H', tm),
|
|
|
|
parse_type('M', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('S', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
't' => ~"\t",
|
2012-04-03 12:38:54 -05:00
|
|
|
//'U' {}
|
2012-08-03 21:59:04 -05:00
|
|
|
'u' => {
|
2012-04-03 12:38:54 -05:00
|
|
|
let i = tm.tm_wday as int;
|
2013-02-26 09:36:59 -06:00
|
|
|
int::to_str(if i == 0 { 7 } else { i })
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
//'V' {}
|
2012-08-03 21:59:04 -05:00
|
|
|
'v' => {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s-%s-%s",
|
2012-04-03 12:38:54 -05:00
|
|
|
parse_type('e', tm),
|
|
|
|
parse_type('b', tm),
|
2012-08-22 19:24:52 -05:00
|
|
|
parse_type('Y', tm))
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
//'W' {}
|
2013-02-26 09:36:59 -06:00
|
|
|
'w' => int::to_str(tm.tm_wday as int),
|
2012-04-03 12:38:54 -05:00
|
|
|
//'X' {}
|
|
|
|
//'x' {}
|
2013-02-26 09:36:59 -06:00
|
|
|
'Y' => int::to_str(tm.tm_year as int + 1900),
|
2012-08-22 19:24:52 -05:00
|
|
|
'y' => fmt!("%02d", (tm.tm_year as int + 1900) % 100),
|
2013-07-02 14:47:32 -05:00
|
|
|
'Z' => tm.tm_zone.clone(),
|
2012-08-03 21:59:04 -05:00
|
|
|
'z' => {
|
2012-04-03 12:38:54 -05:00
|
|
|
let sign = if tm.tm_gmtoff > 0_i32 { '+' } else { '-' };
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
let mut m = num::abs(tm.tm_gmtoff) / 60_i32;
|
2012-04-03 12:38:54 -05:00
|
|
|
let h = m / 60_i32;
|
|
|
|
m -= h * 60_i32;
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%c%02d%02d", sign, h as int, m as int)
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
//'+' {}
|
2012-08-15 13:55:17 -05:00
|
|
|
'%' => ~"%",
|
|
|
|
_ => die()
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut buf = ~"";
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2013-05-29 13:10:16 -05:00
|
|
|
do io::with_str_reader(format) |rdr| {
|
2012-04-03 12:38:54 -05:00
|
|
|
while !rdr.eof() {
|
2012-08-06 14:34:08 -05:00
|
|
|
match rdr.read_char() {
|
2013-06-11 21:13:42 -05:00
|
|
|
'%' => buf.push_str(parse_type(rdr.read_char(), tm)),
|
2013-06-10 02:42:24 -05:00
|
|
|
ch => buf.push_char(ch)
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-15 01:30:30 -06:00
|
|
|
buf
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
|
2012-02-18 03:32:52 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2013-01-08 21:37:25 -06:00
|
|
|
use time::*;
|
|
|
|
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::float;
|
|
|
|
use std::os;
|
|
|
|
use std::result;
|
|
|
|
use std::result::{Err, Ok};
|
|
|
|
use std::str;
|
2012-12-27 20:24:18 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_get_time() {
|
2013-06-30 22:51:13 -05:00
|
|
|
static SOME_RECENT_DATE: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
|
|
|
|
static SOME_FUTURE_DATE: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
|
2012-02-18 03:32:52 -06:00
|
|
|
|
|
|
|
let tv1 = get_time();
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("tv1=%? sec + %? nsec", tv1.sec as uint, tv1.nsec as uint);
|
2012-02-18 03:32:52 -06:00
|
|
|
|
2013-06-30 22:51:13 -05:00
|
|
|
assert!(tv1.sec > SOME_RECENT_DATE);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tv1.nsec < 1000000000i32);
|
2012-02-18 03:32:52 -06:00
|
|
|
|
|
|
|
let tv2 = get_time();
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("tv2=%? sec + %? nsec", tv2.sec as uint, tv2.nsec as uint);
|
2012-02-18 03:32:52 -06:00
|
|
|
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tv2.sec >= tv1.sec);
|
2013-06-30 22:51:13 -05:00
|
|
|
assert!(tv2.sec < SOME_FUTURE_DATE);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tv2.nsec < 1000000000i32);
|
2012-02-18 03:32:52 -06:00
|
|
|
if tv2.sec == tv1.sec {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tv2.nsec >= tv1.nsec);
|
2012-02-18 03:32:52 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_precise_time() {
|
2012-02-18 03:32:52 -06:00
|
|
|
let s0 = precise_time_s();
|
|
|
|
let ns1 = precise_time_ns();
|
|
|
|
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("s0=%s sec", float::to_str_digits(s0, 9u));
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(s0 > 0.);
|
2012-02-18 03:32:52 -06:00
|
|
|
let ns0 = (s0 * 1000000000.) as u64;
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("ns0=%? ns", ns0);
|
2012-02-18 03:32:52 -06:00
|
|
|
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("ns1=%? ns", ns0);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(ns1 >= ns0);
|
2012-02-18 03:32:52 -06:00
|
|
|
|
|
|
|
let ns2 = precise_time_ns();
|
2013-02-25 13:11:21 -06:00
|
|
|
debug!("ns2=%? ns", ns0);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(ns2 >= ns1);
|
2012-02-18 03:32:52 -06:00
|
|
|
}
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_at_utc() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:32:26 -05:00
|
|
|
let utc = at_utc(time);
|
|
|
|
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(utc.tm_sec == 30_i32);
|
|
|
|
assert!(utc.tm_min == 31_i32);
|
|
|
|
assert!(utc.tm_hour == 23_i32);
|
|
|
|
assert!(utc.tm_mday == 13_i32);
|
|
|
|
assert!(utc.tm_mon == 1_i32);
|
|
|
|
assert!(utc.tm_year == 109_i32);
|
|
|
|
assert!(utc.tm_wday == 5_i32);
|
|
|
|
assert!(utc.tm_yday == 43_i32);
|
|
|
|
assert!(utc.tm_isdst == 0_i32);
|
|
|
|
assert!(utc.tm_gmtoff == 0_i32);
|
|
|
|
assert!(utc.tm_zone == ~"UTC");
|
|
|
|
assert!(utc.tm_nsec == 54321_i32);
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_at() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:32:26 -05:00
|
|
|
let local = at(time);
|
|
|
|
|
2012-08-22 19:24:52 -05:00
|
|
|
error!("time_at: %?", local);
|
2012-04-13 19:33:02 -05:00
|
|
|
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(local.tm_sec == 30_i32);
|
|
|
|
assert!(local.tm_min == 31_i32);
|
|
|
|
assert!(local.tm_hour == 15_i32);
|
|
|
|
assert!(local.tm_mday == 13_i32);
|
|
|
|
assert!(local.tm_mon == 1_i32);
|
|
|
|
assert!(local.tm_year == 109_i32);
|
|
|
|
assert!(local.tm_wday == 5_i32);
|
|
|
|
assert!(local.tm_yday == 43_i32);
|
|
|
|
assert!(local.tm_isdst == 0_i32);
|
|
|
|
assert!(local.tm_gmtoff == -28800_i32);
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2350): We should probably standardize on the timezone
|
2012-04-03 12:32:26 -05:00
|
|
|
// abbreviation.
|
2012-11-27 00:22:22 -06:00
|
|
|
let zone = &local.tm_zone;
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(*zone == ~"PST" || *zone == ~"Pacific Standard Time");
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(local.tm_nsec == 54321_i32);
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_to_timespec() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:32:26 -05:00
|
|
|
let utc = at_utc(time);
|
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(utc.to_timespec(), time);
|
|
|
|
assert_eq!(utc.to_local().to_timespec(), time);
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_conversions() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:32:26 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:32:26 -05:00
|
|
|
let utc = at_utc(time);
|
|
|
|
let local = at(time);
|
|
|
|
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(local.to_local() == local);
|
|
|
|
assert!(local.to_utc() == utc);
|
|
|
|
assert!(local.to_utc().to_local() == local);
|
|
|
|
assert!(utc.to_utc() == utc);
|
|
|
|
assert!(utc.to_local() == local);
|
|
|
|
assert!(utc.to_local().to_utc() == utc);
|
2012-04-03 12:32:26 -05:00
|
|
|
}
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_strptime() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
match strptime("", "") {
|
2012-09-28 04:26:20 -05:00
|
|
|
Ok(ref tm) => {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tm.tm_sec == 0_i32);
|
|
|
|
assert!(tm.tm_min == 0_i32);
|
|
|
|
assert!(tm.tm_hour == 0_i32);
|
|
|
|
assert!(tm.tm_mday == 0_i32);
|
|
|
|
assert!(tm.tm_mon == 0_i32);
|
|
|
|
assert!(tm.tm_year == 0_i32);
|
|
|
|
assert!(tm.tm_wday == 0_i32);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert!(tm.tm_isdst == 0_i32);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tm.tm_gmtoff == 0_i32);
|
|
|
|
assert!(tm.tm_zone == ~"");
|
|
|
|
assert!(tm.tm_nsec == 0_i32);
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
2012-08-26 18:54:31 -05:00
|
|
|
Err(_) => ()
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
let format = "%a %b %e %T %Y";
|
|
|
|
assert_eq!(strptime("", format), Err(~"Invalid time"));
|
|
|
|
assert!(strptime("Fri Feb 13 15:31:30", format)
|
2013-03-06 15:58:02 -06:00
|
|
|
== Err(~"Invalid time"));
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
match strptime("Fri Feb 13 15:31:30 2009", format) {
|
2013-05-29 18:59:33 -05:00
|
|
|
Err(e) => fail!(e),
|
2012-09-28 04:26:20 -05:00
|
|
|
Ok(ref tm) => {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(tm.tm_sec == 30_i32);
|
|
|
|
assert!(tm.tm_min == 31_i32);
|
|
|
|
assert!(tm.tm_hour == 15_i32);
|
|
|
|
assert!(tm.tm_mday == 13_i32);
|
|
|
|
assert!(tm.tm_mon == 1_i32);
|
|
|
|
assert!(tm.tm_year == 109_i32);
|
|
|
|
assert!(tm.tm_wday == 5_i32);
|
|
|
|
assert!(tm.tm_yday == 0_i32);
|
|
|
|
assert!(tm.tm_isdst == 0_i32);
|
|
|
|
assert!(tm.tm_gmtoff == 0_i32);
|
|
|
|
assert!(tm.tm_zone == ~"");
|
|
|
|
assert!(tm.tm_nsec == 0_i32);
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-24 14:03:11 -05:00
|
|
|
fn test(s: &str, format: &str) -> bool {
|
2012-08-06 14:34:08 -05:00
|
|
|
match strptime(s, format) {
|
2013-07-23 08:49:17 -05:00
|
|
|
Ok(ref tm) => tm.strftime(format) == s.to_owned(),
|
2013-05-29 18:59:33 -05:00
|
|
|
Err(e) => fail!(e)
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 07:29:53 -05:00
|
|
|
let days = [
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Sunday",
|
|
|
|
~"Monday",
|
|
|
|
~"Tuesday",
|
|
|
|
~"Wednesday",
|
|
|
|
~"Thursday",
|
|
|
|
~"Friday",
|
|
|
|
~"Saturday"
|
2013-06-21 07:29:53 -05:00
|
|
|
];
|
|
|
|
for days.iter().advance |day| {
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test(*day, "%A"));
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2013-06-21 07:29:53 -05:00
|
|
|
let days = [
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Sun",
|
|
|
|
~"Mon",
|
|
|
|
~"Tue",
|
|
|
|
~"Wed",
|
|
|
|
~"Thu",
|
|
|
|
~"Fri",
|
|
|
|
~"Sat"
|
2013-06-21 07:29:53 -05:00
|
|
|
];
|
|
|
|
for days.iter().advance |day| {
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test(*day, "%a"));
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2013-06-21 07:29:53 -05:00
|
|
|
let months = [
|
2012-07-14 00:57:48 -05:00
|
|
|
~"January",
|
|
|
|
~"February",
|
|
|
|
~"March",
|
|
|
|
~"April",
|
|
|
|
~"May",
|
|
|
|
~"June",
|
|
|
|
~"July",
|
|
|
|
~"August",
|
|
|
|
~"September",
|
|
|
|
~"October",
|
|
|
|
~"November",
|
|
|
|
~"December"
|
2013-06-21 07:29:53 -05:00
|
|
|
];
|
|
|
|
for months.iter().advance |day| {
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test(*day, "%B"));
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-04-03 12:37:02 -05:00
|
|
|
|
2013-06-21 07:29:53 -05:00
|
|
|
let months = [
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Jan",
|
|
|
|
~"Feb",
|
|
|
|
~"Mar",
|
|
|
|
~"Apr",
|
|
|
|
~"May",
|
|
|
|
~"Jun",
|
|
|
|
~"Jul",
|
|
|
|
~"Aug",
|
|
|
|
~"Sep",
|
|
|
|
~"Oct",
|
|
|
|
~"Nov",
|
|
|
|
~"Dec"
|
2013-06-21 07:29:53 -05:00
|
|
|
];
|
|
|
|
for months.iter().advance |day| {
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test(*day, "%b"));
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-07-14 00:57:48 -05:00
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test("19", "%C"));
|
|
|
|
assert!(test("Fri Feb 13 23:31:30 2009", "%c"));
|
|
|
|
assert!(test("02/13/09", "%D"));
|
|
|
|
assert!(test("03", "%d"));
|
|
|
|
assert!(test("13", "%d"));
|
|
|
|
assert!(test(" 3", "%e"));
|
|
|
|
assert!(test("13", "%e"));
|
|
|
|
assert!(test("2009-02-13", "%F"));
|
|
|
|
assert!(test("03", "%H"));
|
|
|
|
assert!(test("13", "%H"));
|
|
|
|
assert!(test("03", "%I")); // FIXME (#2350): flesh out
|
|
|
|
assert!(test("11", "%I")); // FIXME (#2350): flesh out
|
|
|
|
assert!(test("044", "%j"));
|
|
|
|
assert!(test(" 3", "%k"));
|
|
|
|
assert!(test("13", "%k"));
|
|
|
|
assert!(test(" 1", "%l"));
|
|
|
|
assert!(test("11", "%l"));
|
|
|
|
assert!(test("03", "%M"));
|
|
|
|
assert!(test("13", "%M"));
|
|
|
|
assert!(test("\n", "%n"));
|
|
|
|
assert!(test("am", "%P"));
|
|
|
|
assert!(test("pm", "%P"));
|
|
|
|
assert!(test("AM", "%p"));
|
|
|
|
assert!(test("PM", "%p"));
|
|
|
|
assert!(test("23:31", "%R"));
|
|
|
|
assert!(test("11:31:30 AM", "%r"));
|
|
|
|
assert!(test("11:31:30 PM", "%r"));
|
|
|
|
assert!(test("03", "%S"));
|
|
|
|
assert!(test("13", "%S"));
|
|
|
|
assert!(test("15:31:30", "%T"));
|
|
|
|
assert!(test("\t", "%t"));
|
|
|
|
assert!(test("1", "%u"));
|
|
|
|
assert!(test("7", "%u"));
|
|
|
|
assert!(test("13-Feb-2009", "%v"));
|
|
|
|
assert!(test("0", "%w"));
|
|
|
|
assert!(test("6", "%w"));
|
|
|
|
assert!(test("2009", "%Y"));
|
|
|
|
assert!(test("09", "%y"));
|
|
|
|
assert!(result::unwrap(strptime("UTC", "%Z")).tm_zone ==
|
2013-03-06 21:09:17 -06:00
|
|
|
~"UTC");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(result::unwrap(strptime("PST", "%Z")).tm_zone ==
|
2013-03-06 21:09:17 -06:00
|
|
|
~"");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(result::unwrap(strptime("-0000", "%z")).tm_gmtoff ==
|
2013-03-06 21:09:17 -06:00
|
|
|
0);
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(result::unwrap(strptime("-0800", "%z")).tm_gmtoff ==
|
2013-03-06 21:09:17 -06:00
|
|
|
0);
|
2013-05-23 11:39:00 -05:00
|
|
|
assert!(test("%", "%%"));
|
2013-06-20 10:07:05 -05:00
|
|
|
|
|
|
|
// Test for #7256
|
|
|
|
assert_eq!(strptime("360", "%Y-%m-%d"), Err(~"Invalid year"))
|
2012-04-03 12:37:02 -05:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_ctime() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:38:54 -05:00
|
|
|
let utc = at_utc(time);
|
|
|
|
let local = at(time);
|
|
|
|
|
2012-08-22 19:24:52 -05:00
|
|
|
error!("test_ctime: %? %?", utc.ctime(), local.ctime());
|
2012-04-13 19:33:02 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009");
|
|
|
|
assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009");
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_strftime() {
|
2013-05-23 11:39:00 -05:00
|
|
|
os::setenv("TZ", "America/Los_Angeles");
|
2012-04-13 19:33:02 -05:00
|
|
|
tzset();
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2012-12-27 20:24:18 -06:00
|
|
|
let time = ::time::Timespec::new(1234567890, 54321);
|
2012-04-03 12:38:54 -05:00
|
|
|
let utc = at_utc(time);
|
|
|
|
let local = at(time);
|
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime(""), ~"");
|
|
|
|
assert_eq!(local.strftime("%A"), ~"Friday");
|
|
|
|
assert_eq!(local.strftime("%a"), ~"Fri");
|
|
|
|
assert_eq!(local.strftime("%B"), ~"February");
|
|
|
|
assert_eq!(local.strftime("%b"), ~"Feb");
|
|
|
|
assert_eq!(local.strftime("%C"), ~"20");
|
|
|
|
assert_eq!(local.strftime("%c"), ~"Fri Feb 13 15:31:30 2009");
|
|
|
|
assert_eq!(local.strftime("%D"), ~"02/13/09");
|
|
|
|
assert_eq!(local.strftime("%d"), ~"13");
|
|
|
|
assert_eq!(local.strftime("%e"), ~"13");
|
|
|
|
assert_eq!(local.strftime("%F"), ~"2009-02-13");
|
2013-03-28 20:39:09 -05:00
|
|
|
// assert!(local.strftime("%G") == "2009");
|
|
|
|
// assert!(local.strftime("%g") == "09");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%H"), ~"15");
|
|
|
|
assert_eq!(local.strftime("%I"), ~"03");
|
|
|
|
assert_eq!(local.strftime("%j"), ~"044");
|
|
|
|
assert_eq!(local.strftime("%k"), ~"15");
|
|
|
|
assert_eq!(local.strftime("%l"), ~" 3");
|
|
|
|
assert_eq!(local.strftime("%M"), ~"31");
|
|
|
|
assert_eq!(local.strftime("%m"), ~"02");
|
|
|
|
assert_eq!(local.strftime("%n"), ~"\n");
|
|
|
|
assert_eq!(local.strftime("%P"), ~"pm");
|
|
|
|
assert_eq!(local.strftime("%p"), ~"PM");
|
|
|
|
assert_eq!(local.strftime("%R"), ~"15:31");
|
|
|
|
assert_eq!(local.strftime("%r"), ~"03:31:30 PM");
|
|
|
|
assert_eq!(local.strftime("%S"), ~"30");
|
|
|
|
assert_eq!(local.strftime("%s"), ~"1234567890");
|
|
|
|
assert_eq!(local.strftime("%T"), ~"15:31:30");
|
|
|
|
assert_eq!(local.strftime("%t"), ~"\t");
|
2013-03-28 20:39:09 -05:00
|
|
|
// assert!(local.strftime("%U") == "06");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%u"), ~"5");
|
2013-03-28 20:39:09 -05:00
|
|
|
// assert!(local.strftime("%V") == "07");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%v"), ~"13-Feb-2009");
|
2013-03-28 20:39:09 -05:00
|
|
|
// assert!(local.strftime("%W") == "06");
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%w"), ~"5");
|
2012-04-03 12:38:54 -05:00
|
|
|
// handle "%X"
|
|
|
|
// handle "%x"
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%Y"), ~"2009");
|
|
|
|
assert_eq!(local.strftime("%y"), ~"09");
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2350): We should probably standardize on the timezone
|
2012-04-03 12:38:54 -05:00
|
|
|
// abbreviation.
|
2013-05-23 11:39:00 -05:00
|
|
|
let zone = local.strftime("%Z");
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(zone == ~"PST" || zone == ~"Pacific Standard Time");
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2013-05-23 11:39:00 -05:00
|
|
|
assert_eq!(local.strftime("%z"), ~"-0800");
|
|
|
|
assert_eq!(local.strftime("%%"), ~"%");
|
2012-04-03 12:38:54 -05:00
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2350): We should probably standardize on the timezone
|
2012-04-03 12:38:54 -05:00
|
|
|
// abbreviation.
|
|
|
|
let rfc822 = local.rfc822();
|
2012-07-14 00:57:48 -05:00
|
|
|
let prefix = ~"Fri, 13 Feb 2009 15:31:30 ";
|
2013-05-27 18:04:00 -05:00
|
|
|
assert!(rfc822 == prefix + "PST" ||
|
|
|
|
rfc822 == prefix + "Pacific Standard Time");
|
2012-07-14 00:57:48 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009");
|
|
|
|
assert_eq!(local.rfc822z(), ~"Fri, 13 Feb 2009 15:31:30 -0800");
|
|
|
|
assert_eq!(local.rfc3339(), ~"2009-02-13T15:31:30-08:00");
|
2012-07-14 00:57:48 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009");
|
|
|
|
assert_eq!(utc.rfc822(), ~"Fri, 13 Feb 2009 23:31:30 GMT");
|
|
|
|
assert_eq!(utc.rfc822z(), ~"Fri, 13 Feb 2009 23:31:30 -0000");
|
|
|
|
assert_eq!(utc.rfc3339(), ~"2009-02-13T23:31:30Z");
|
2012-04-03 12:38:54 -05:00
|
|
|
}
|
2013-01-17 01:37:21 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_timespec_eq_ord() {
|
2013-01-17 01:37:21 -06:00
|
|
|
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);
|
|
|
|
|
2013-06-09 02:23:05 -05:00
|
|
|
assert!(d.eq(e));
|
|
|
|
assert!(c.ne(e));
|
2013-01-17 01:37:21 -06:00
|
|
|
|
2013-06-09 02:23:05 -05:00
|
|
|
assert!(a.lt(b));
|
|
|
|
assert!(b.lt(c));
|
|
|
|
assert!(c.lt(d));
|
2013-01-17 01:37:21 -06:00
|
|
|
|
2013-06-09 02:23:05 -05:00
|
|
|
assert!(a.le(b));
|
|
|
|
assert!(b.le(c));
|
|
|
|
assert!(c.le(d));
|
|
|
|
assert!(d.le(e));
|
|
|
|
assert!(e.le(d));
|
2013-01-17 01:37:21 -06:00
|
|
|
|
2013-06-09 02:23:05 -05:00
|
|
|
assert!(b.ge(a));
|
|
|
|
assert!(c.ge(b));
|
|
|
|
assert!(d.ge(c));
|
|
|
|
assert!(e.ge(d));
|
|
|
|
assert!(d.ge(e));
|
2013-01-17 01:37:21 -06:00
|
|
|
|
2013-06-09 02:23:05 -05:00
|
|
|
assert!(b.gt(a));
|
|
|
|
assert!(c.gt(b));
|
|
|
|
assert!(d.gt(c));
|
2013-01-17 01:37:21 -06:00
|
|
|
}
|
2013-01-23 18:38:07 -06:00
|
|
|
|
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn run_tests() {
|
2013-01-23 18:38:07 -06:00
|
|
|
// The tests race on tzset. So instead of having many independent
|
|
|
|
// tests, we will just call the functions now.
|
|
|
|
test_get_time();
|
|
|
|
test_precise_time();
|
|
|
|
test_at_utc();
|
|
|
|
test_at();
|
|
|
|
test_to_timespec();
|
|
|
|
test_conversions();
|
|
|
|
test_strptime();
|
|
|
|
test_ctime();
|
|
|
|
test_strftime();
|
|
|
|
test_timespec_eq_ord();
|
|
|
|
}
|
2012-02-18 03:32:52 -06:00
|
|
|
}
|