hyperx/header/shared/
httpdate.rs

1use std::fmt::{self, Display};
2use std::str::FromStr;
3use std::time::SystemTime;
4
5use httpdate::HttpDate as InnerDate;
6
7/// A timestamp with HTTP formatting and parsing
8//   Prior to 1995, there were three different formats commonly used by
9//   servers to communicate timestamps.  For compatibility with old
10//   implementations, all three are defined here.  The preferred format is
11//   a fixed-length and single-zone subset of the date and time
12//   specification used by the Internet Message Format [RFC5322].
13//
14//     HTTP-date    = IMF-fixdate / obs-date
15//
16//   An example of the preferred format is
17//
18//     Sun, 06 Nov 1994 08:49:37 GMT    ; IMF-fixdate
19//
20//   Examples of the two obsolete formats are
21//
22//     Sunday, 06-Nov-94 08:49:37 GMT   ; obsolete RFC 850 format
23//     Sun Nov  6 08:49:37 1994         ; ANSI C's asctime() format
24//
25//   A recipient that parses a timestamp value in an HTTP header field
26//   MUST accept all three HTTP-date formats.  When a sender generates a
27//   header field that contains one or more timestamps defined as
28//   HTTP-date, the sender MUST generate those timestamps in the
29//   IMF-fixdate format.
30#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
31pub struct HttpDate(InnerDate);
32
33impl FromStr for HttpDate {
34    type Err = ::Error;
35    fn from_str(s: &str) -> ::Result<HttpDate> {
36        InnerDate::from_str(s)
37            .map(HttpDate)
38            .map_err(|_| ::Error::Header)
39    }
40}
41
42impl Display for HttpDate {
43    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44        fmt::Display::fmt(&self.0, f)
45    }
46}
47
48impl From<SystemTime> for HttpDate {
49    fn from(sys: SystemTime) -> HttpDate {
50        HttpDate(sys.into())
51    }
52}
53
54impl From<HttpDate> for SystemTime {
55    fn from(date: HttpDate) -> SystemTime {
56        date.0.into()
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use std::time::{SystemTime, Duration};
63
64    use super::HttpDate;
65
66    macro_rules! test_parse {
67        ($function: ident, $date: expr) => {
68            #[test]
69            fn $function() {
70                let nov_07 = HttpDate((
71                    SystemTime::UNIX_EPOCH + Duration::new(784198117, 0)
72                ).into());
73
74                assert_eq!($date.parse::<HttpDate>().unwrap(), nov_07);
75            }
76        };
77    }
78
79    test_parse!(test_imf_fixdate, "Mon, 07 Nov 1994 08:48:37 GMT");
80    test_parse!(test_rfc_850, "Monday, 07-Nov-94 08:48:37 GMT");
81    test_parse!(test_asctime, "Mon Nov  7 08:48:37 1994");
82
83    #[test]
84    fn test_no_date() {
85        assert!("this-is-no-date".parse::<HttpDate>().is_err());
86    }
87}