redirectionio 3.1.0

Redirection IO Library to handle matching rule, redirect and filtering headers and body.
Documentation
use std::fmt::Display;

use chrono::{DateTime, NaiveDateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Hash, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
pub struct RouteDateTime {
    pub start: Option<NaiveDateTime>,
    pub end: Option<NaiveDateTime>,
}

impl RouteDateTime {
    pub fn from_range(start: &Option<String>, end: &Option<String>) -> RouteDateTime {
        let mut route_start = None;
        let mut route_end = None;
        match start {
            None => (),
            Some(datetime) => match datetime.parse::<DateTime<Utc>>() {
                Ok(dt) => route_start = Some(dt.naive_utc()),
                Err(err) => {
                    tracing::error!("cannot parse datetime {datetime}: {err}");
                }
            },
        }
        match end {
            None => (),
            Some(datetime) => match datetime.parse::<DateTime<Utc>>() {
                Ok(dt) => route_end = Some(dt.naive_utc()),
                Err(err) => {
                    tracing::error!("cannot parse datetime {datetime}: {err}");
                }
            },
        }

        RouteDateTime {
            start: route_start,
            end: route_end,
        }
    }

    pub fn match_datetime(&self, datetime: &DateTime<Utc>) -> bool {
        let naive_datetime = datetime.naive_utc();
        match self.start {
            None => match self.end {
                None => true,
                Some(end) => naive_datetime < end,
            },
            Some(start) => match self.end {
                None => naive_datetime >= start,
                Some(end) => (naive_datetime >= start) && (naive_datetime < end),
            },
        }
    }
}

impl Display for RouteDateTime {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let str = match self.start {
            None => match self.end {
                None => "always".to_string(),
                Some(end) => format!("before({})", end.format("%Y-%m-%d %H:%M:%S")),
            },
            Some(start) => match self.end {
                None => format!("after({})", start.format("%Y-%m-%d %H:%M:%S")),
                Some(end) => format!("in({}, {})", start.format("%Y-%m-%d %H:%M:%S"), end.format("%Y-%m-%d %H:%M:%S")),
            },
        };
        write!(f, "{str}")
    }
}