Fix maximum SystemTime on windows, wasm32-unknown-unknown, cloudabi

According to https://github.com/tailhook/humantime/issues/2#issuecomment-369315826
these platforms have larger timestamp limit then 32bit unix
This commit is contained in:
Paul Colomiets 2018-02-28 23:11:00 +02:00
parent f51503361f
commit 7e35030209

View File

@ -1,8 +1,23 @@
use std::fmt;
use std::i32;
use std::str;
use std::time::{SystemTime, Duration, UNIX_EPOCH};
#[cfg(target_os="cloudabi")]
const MAX_SECONDS: u64 = ::std::u64::MAX / 1_000_000_000;
#[cfg(all(
target_pointer_width="32",
not(target_os="cloudabi"),
not(target_os="windows"),
not(all(target_arch="wasm32", not(target_os="emscripten")))
))]
const MAX_SECONDS: u64 = ::std::i32::MAX as u64;
#[cfg(any(
target_pointer_width="64",
target_os="windows",
all(target_arch="wasm32", not(target_os="emscripten")),
))]
const MAX_SECONDS: u64 = 253402300800-1; // last second of year 9999
quick_error! {
/// Error parsing datetime (timestamp)
#[derive(Debug, PartialEq, Clone, Copy)]
@ -149,10 +164,8 @@ pub fn parse_rfc3339_weak(s: &str) -> Result<SystemTime, Error> {
}
let total_seconds = time + days * 86400;
if cfg!(target_pointer_width="32") {
if total_seconds > i32::MAX as u64 {
return Err(Error::OutOfRange);
}
if total_seconds > MAX_SECONDS {
return Err(Error::OutOfRange);
}
return Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos));
@ -298,11 +311,11 @@ mod test {
extern crate time;
extern crate rand;
use std::i32;
use std::str::from_utf8;
use self::rand::Rng;
use std::time::{UNIX_EPOCH, SystemTime, Duration};
use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339, Error};
use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339};
use super::{MAX_SECONDS};
fn from_sec(sec: u64) -> (String, SystemTime) {
let s = time::at_utc(time::Timespec { sec: sec as i64, nsec: 0 })
@ -312,20 +325,13 @@ mod test {
}
#[test]
#[should_panic(expected="overflow when adding duration to time")]
#[cfg(target_pointer_width="32")]
fn check_32bit_still_has_2038_year_problem() {
UNIX_EPOCH + Duration::from_secs((i32::MAX as u64) + 1);
}
#[test]
#[cfg(target_pointer_width="32")]
#[cfg(all(target_pointer_width="32", target_os="linux"))]
fn year_after_2038_fails_gracefully() {
// next second
assert_eq!(parse_rfc3339("2038-01-19T03:14:08Z").unwrap_err(),
Error::OutOfRange);
super::Error::OutOfRange);
assert_eq!(parse_rfc3339("9999-12-31T23:59:59Z").unwrap_err(),
Error::OutOfRange);
super::Error::OutOfRange);
}
#[test]
@ -358,13 +364,13 @@ mod test {
#[test]
fn upper_bound_32bit() {
let max = UNIX_EPOCH + Duration::new((::std::i32::MAX as u64), 0);
let max = UNIX_EPOCH + Duration::new(::std::i32::MAX as u64, 0);
assert_eq!(format_rfc3339(max).to_string(), "2038-01-19T03:14:07Z");
assert_eq!(parse_rfc3339("2038-01-19T03:14:07Z").unwrap(), max);
}
#[test]
#[cfg(target_pointer_width="64")]
#[cfg(all(target_pointer_width="64", not(target_os="cloudabi")))]
fn upper_bound_64bit() {
assert_eq!(parse_rfc3339("9999-12-31T23:59:59Z").unwrap(),
UNIX_EPOCH + Duration::new(253402300800-1, 0));
@ -423,15 +429,8 @@ mod test {
#[test]
fn random_wide_range() {
let max_date = if cfg!(target_pointer_width="32") {
// 32bit duration supports only up to u32::MAX seconds
i32::MAX as u64
} else {
// on 64bit we support up to a year 9999
253370764800
};
for _ in 0..10000 {
let sec = rand::thread_rng().gen_range(0, max_date);
for _ in 0..100000 {
let sec = rand::thread_rng().gen_range(0, MAX_SECONDS);
let (s, time) = from_sec(sec);
assert_eq!(parse_rfc3339(&s).unwrap(), time);
assert_eq!(format_rfc3339(time).to_string(), s);