# httpdate.rs.html -- source
Source to the Rust file `src/header/shared/httpdate.rs`.
Keywords: rust, rustlang, rust-lang

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119

    use std::fmt::{self, Display};
    use std::io::Write;
    use std::str::FromStr;
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    use bytes::{BufMut, BytesMut};
    use http::header::{HeaderValue, InvalidHeaderValueBytes};
    use time;

    use error::ParseError;
    use header::IntoHeaderValue;

    /// A timestamp with HTTP formatting and parsing
    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
    pub struct HttpDate(time::Tm);

    impl FromStr for HttpDate {
        type Err = ParseError;

        fn from_str(s: &str) -> Result<HttpDate, ParseError> {
            match time::strptime(s, "%a, %d %b %Y %T %Z")
                .or_else(|_| time::strptime(s, "%A, %d-%b-%y %T %Z"))
                .or_else(|_| time::strptime(s, "%c"))
            {
                Ok(t) => Ok(HttpDate(t)),
                Err(_) => Err(ParseError::Header),
            }
        }
    }

    impl Display for HttpDate {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Display::fmt(&self.0.to_utc().rfc822(), f)
        }
    }

    impl From<time::Tm> for HttpDate {
        fn from(tm: time::Tm) -> HttpDate {
            HttpDate(tm)
        }
    }

    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 IntoHeaderValue for HttpDate {
        type Error = InvalidHeaderValueBytes;

        fn try_into(self) -> Result<HeaderValue, Self::Error> {
            let mut wrt = BytesMut::with_capacity(29).writer();
            write!(wrt, "{}", self.0.rfc822()).unwrap();
            HeaderValue::from_shared(wrt.get_mut().take().freeze())
        }
    }

    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 super::HttpDate;
        use time::Tm;

        const NOV_07: HttpDate = HttpDate(Tm {
            tm_nsec: 0,
            tm_sec: 37,
            tm_min: 48,
            tm_hour: 8,
            tm_mday: 7,
            tm_mon: 10,
            tm_year: 94,
            tm_wday: 0,
            tm_isdst: 0,
            tm_yday: 0,
            tm_utcoff: 0,
        });

        #[test]
        fn test_date() {
            assert_eq!(
                "Sun, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(),
                NOV_07
            );
            assert_eq!(
                "Sunday, 07-Nov-94 08:48:37 GMT"
                    .parse::<HttpDate>()
                    .unwrap(),
                NOV_07
            );
            assert_eq!(
                "Sun Nov  7 08:48:37 1994".parse::<HttpDate>().unwrap(),
                NOV_07
            );
            assert!("this-is-no-date".parse::<HttpDate>().is_err());
        }
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g. `str,u8` or `String,struct:Vec,test`)