hyper_sync/header/shared/
httpdate.rs1use std::fmt::{self, Display};
2use std::str::FromStr;
3use std::time::{Duration, SystemTime, UNIX_EPOCH};
4
5use time;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
31pub struct HttpDate(time::Tm);
32
33impl FromStr for HttpDate {
34 type Err = ::Error;
35 fn from_str(s: &str) -> ::Result<HttpDate> {
36 match time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| {
37 time::strptime(s, "%A, %d-%b-%y %T %Z")
38 }).or_else(|_| {
39 time::strptime(s, "%c")
40 }) {
41 Ok(t) => Ok(HttpDate(t)),
42 Err(_) => Err(::Error::Header),
43 }
44 }
45}
46
47impl Display for HttpDate {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 fmt::Display::fmt(&self.0.to_utc().rfc822(), f)
50 }
51}
52
53impl From<SystemTime> for HttpDate {
54 fn from(sys: SystemTime) -> HttpDate {
55 let tmspec = match sys.duration_since(UNIX_EPOCH) {
56 Ok(dur) => {
57 time::Timespec::new(dur.as_secs() as i64, dur.subsec_nanos() as i32)
58 },
59 Err(err) => {
60 let neg = err.duration();
61 time::Timespec::new(-(neg.as_secs() as i64), -(neg.subsec_nanos() as i32))
62 },
63 };
64 HttpDate(time::at_utc(tmspec))
65 }
66}
67
68impl From<HttpDate> for SystemTime {
69 fn from(date: HttpDate) -> SystemTime {
70 let spec = date.0.to_timespec();
71 if spec.sec >= 0 {
72 UNIX_EPOCH + Duration::new(spec.sec as u64, spec.nsec as u32)
73 } else {
74 UNIX_EPOCH - Duration::new(spec.sec as u64, spec.nsec as u32)
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use time::Tm;
82 use super::HttpDate;
83
84 const NOV_07: HttpDate = HttpDate(Tm {
85 tm_nsec: 0,
86 tm_sec: 37,
87 tm_min: 48,
88 tm_hour: 8,
89 tm_mday: 7,
90 tm_mon: 10,
91 tm_year: 94,
92 tm_wday: 0,
93 tm_isdst: 0,
94 tm_yday: 0,
95 tm_utcoff: 0,
96 });
97
98 #[test]
99 fn test_imf_fixdate() {
100 assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07);
101 }
102
103 #[test]
104 fn test_rfc_850() {
105 assert_eq!("Sunday, 07-Nov-94 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07);
106 }
107
108 #[test]
109 fn test_asctime() {
110 assert_eq!("Sun Nov 7 08:48:37 1994".parse::<HttpDate>().unwrap(), NOV_07);
111 }
112
113 #[test]
114 fn test_no_date() {
115 assert!("this-is-no-date".parse::<HttpDate>().is_err());
116 }
117}