refactor(header): change HttpDate to opaque over SystemTime

This removes the need for someone to use the `time` crate to create a
date compatible with HTTP headers. It now works with the `SystemTime`
type from the standard library.

BREAKING CHANGE: `HttpDate` no longer has public fields. Convert between
  `HttpDate` and `SystemTime` as needed.
This commit is contained in:
Sean McArthur
2017-04-24 15:09:10 -07:00
parent 011f28cb18
commit 316c6fad30
10 changed files with 106 additions and 129 deletions

View File

@@ -1,10 +1,10 @@
use std::str::FromStr;
use std::fmt::{self, Display};
use std::str::FromStr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use time;
/// A `time::Time` with HTTP formatting and parsing
///
/// A timestamp with HTTP formatting and parsing
// Prior to 1995, there were three different formats commonly used by
// servers to communicate timestamps. For compatibility with old
// implementations, all three are defined here. The preferred format is
@@ -28,7 +28,7 @@ use time;
// HTTP-date, the sender MUST generate those timestamps in the
// IMF-fixdate format.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct HttpDate(pub time::Tm);
pub struct HttpDate(time::Tm);
impl FromStr for HttpDate {
type Err = ::Error;
@@ -50,6 +50,32 @@ impl Display for HttpDate {
}
}
impl From<SystemTime> for HttpDate {
fn from(sys: SystemTime) -> HttpDate {
let tmspec = match sys.duration_since(UNIX_EPOCH) {
Ok(dur) => {
time::Timespec::new(dur.as_secs() as i64, dur.subsec_nanos() as i32)
},
Err(err) => {
let neg = err.duration();
time::Timespec::new(-(neg.as_secs() as i64), -(neg.subsec_nanos() as i32))
},
};
HttpDate(time::at_utc(tmspec))
}
}
impl From<HttpDate> for SystemTime {
fn from(date: HttpDate) -> SystemTime {
let spec = date.0.to_timespec();
if spec.sec >= 0 {
UNIX_EPOCH + Duration::new(spec.sec as u64, spec.nsec as u32)
} else {
UNIX_EPOCH - Duration::new(spec.sec as u64, spec.nsec as u32)
}
}
}
#[cfg(test)]
mod tests {
use time::Tm;