edge-schema 0.1.0

Shared schema types for Wasmer Edge.
Documentation
use time::{
    format_description::well_known::{Rfc2822, Rfc3339},
    Date, OffsetDateTime, PrimitiveDateTime, Time,
};

/// Try to parse the string as a timestamp in a number of well-known formats.
///
/// Supported formats,
///
/// - RFC 3339 (`2006-01-02T03:04:05-07:00`)
/// - RFC 2822 (`Mon, 02 Jan 2006 03:04:05 MST`)
/// - Date (`2006-01-02`)
/// - Unix timestamp (`1136196245`)
/// - Relative time (`10m` / `-1h`, `1d1h30s`)
pub fn parse_timestamp_or_relative_time(s: &str) -> Result<OffsetDateTime, anyhow::Error> {
    parse_timestamp_or_relative_time_based(s, OffsetDateTime::now_utc())
}

pub fn parse_timestamp_or_relative_time_based(
    s: &str,
    base: OffsetDateTime,
) -> Result<OffsetDateTime, anyhow::Error> {
    if let Ok(t) = OffsetDateTime::parse(s, &Rfc3339) {
        return Ok(t);
    }
    if let Ok(t) = OffsetDateTime::parse(s, &Rfc2822) {
        return Ok(t);
    }
    if let Ok(t) = Date::parse(s, time::macros::format_description!("[year]-[month]-[day]")) {
        return Ok(PrimitiveDateTime::new(t, Time::MIDNIGHT).assume_utc());
    }
    if let Ok(t) = OffsetDateTime::parse(s, time::macros::format_description!("[unix_timestamp]")) {
        return Ok(t);
    }

    // Relative time.
    let (is_negative, v) = match s.strip_prefix('-') {
        Some(rest) => (true, rest),
        None => (false, s.trim_start_matches('+')),
    };

    if let Ok(duration) = v.parse::<super::PrettyDuration>() {
        let time = if is_negative {
            base - duration.0
        } else {
            base + duration.0
        };

        return Ok(time);
    }

    anyhow::bail!("Unable to parse the timestamp - no known format matched")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_reltime() {
        let expected = time::macros::datetime!(2006-01-02 03:04:05 -07:00);

        assert_eq!(
            parse_timestamp_or_relative_time("2006-01-02T03:04:05-07:00").unwrap(),
            expected,
        );
        assert_eq!(
            parse_timestamp_or_relative_time("2006-01-02T10:04:05Z").unwrap(),
            expected
        );
        assert_eq!(
            parse_timestamp_or_relative_time("2006-01-02T10:04:05.000000000Z").unwrap(),
            expected
        );
        assert_eq!(
            parse_timestamp_or_relative_time("Mon, 02 Jan 2006 03:04:05 MST").unwrap(),
            expected,
        );
        assert_eq!(
            parse_timestamp_or_relative_time("2006-01-02").unwrap(),
            time::macros::datetime!(2006-01-02 00:00:00 +00:00),
        );
        assert_eq!(
            parse_timestamp_or_relative_time("1136196245").unwrap(),
            expected
        );
    }
}