fn parse_imf_fixdate()

in rust-runtime/aws-smithy-types/src/date_time/format.rs [277:354]


    fn parse_imf_fixdate(s: &[u8]) -> Result<DateTime, DateTimeParseError> {
        // Example: `Sun, 06 Nov 1994 08:49:37 GMT`
        if s.len() < 29
            || s.len() > 33
            || !s.ends_with(b" GMT")
            || s[16] != b' '
            || s[19] != b':'
            || s[22] != b':'
        {
            return Err(DateTimeParseError::Invalid(
                "incorrectly shaped string".into(),
            ));
        }
        let nanos: u32 = match &s[25] {
            b'.' => {
                // The date must end with " GMT", so read from the character after the `.`
                // to 4 from the end
                let fraction_slice = &s[26..s.len() - 4];
                if fraction_slice.len() > 3 {
                    // Only thousandths are supported
                    return Err(DateTimeParseError::Invalid(
                        "Smithy http-date only supports millisecond precision".into(),
                    ));
                }
                let fraction: u32 = parse_slice(fraction_slice)?;
                // We need to convert the fractional second to nanoseconds, so we need to scale
                // according the the number of decimals provided
                let multiplier = [10, 100, 1000];
                fraction * (NANOS_PER_SECOND / multiplier[fraction_slice.len() - 1])
            }
            b' ' => 0,
            _ => {
                return Err(DateTimeParseError::Invalid(
                    "incorrectly shaped string".into(),
                ))
            }
        };

        let hours = parse_slice(&s[17..19])?;
        let minutes = parse_slice(&s[20..22])?;
        let seconds = parse_slice(&s[23..25])?;
        let time = Time::from_hms_nano(hours, minutes, seconds, nanos).map_err(|err| {
            DateTimeParseError::Invalid(format!("time components are out of range: {}", err).into())
        })?;

        let month = match &s[7..12] {
            b" Jan " => Month::January,
            b" Feb " => Month::February,
            b" Mar " => Month::March,
            b" Apr " => Month::April,
            b" May " => Month::May,
            b" Jun " => Month::June,
            b" Jul " => Month::July,
            b" Aug " => Month::August,
            b" Sep " => Month::September,
            b" Oct " => Month::October,
            b" Nov " => Month::November,
            b" Dec " => Month::December,
            month => {
                return Err(DateTimeParseError::Invalid(
                    format!(
                        "invalid month: {}",
                        std::str::from_utf8(month).unwrap_or_default()
                    )
                    .into(),
                ))
            }
        };
        let year = parse_slice(&s[12..16])?;
        let day = parse_slice(&s[5..7])?;
        let date = Date::from_calendar_date(year, month, day).map_err(|err| {
            DateTimeParseError::Invalid(format!("date components are out of range: {}", err).into())
        })?;
        let date_time = PrimitiveDateTime::new(date, time).assume_offset(UtcOffset::UTC);

        Ok(DateTime::from_nanos(date_time.unix_timestamp_nanos())
            .expect("this date format cannot produce out of range date-times"))
    }