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"))
}