Skip to main content

ntex_files/header/
http_date.rs

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