use crate::Validator;
use chrono::prelude::DateTime as ChronoDateTime;
use chrono::prelude::{NaiveDate, NaiveDateTime, NaiveTime};
#[derive(Debug, Clone)]
pub struct Date {
pub formats: Vec<String>,
}
impl Default for Date {
fn default() -> Self {
Date {
formats: vec![
"%Y-%m-%d".into(),
"%d-%m-%Y".into(),
"%d/%m/%Y".into(),
"%m/%d/%Y".into(),
"%d/%m/%y".into(),
"%m/%d/%y".into(),
],
}
}
}
impl Validator for Date {
fn validate(&mut self, value: &str) -> bool {
self.formats
.retain(|format| NaiveDate::parse_from_str(value, format).is_ok());
!self.formats.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct Time {
pub formats: Vec<String>,
}
impl Default for Time {
fn default() -> Self {
Time {
formats: vec![
"T%H:%M:%S".into(),
"%H:%M:%S".into(),
"%H:%M".into(),
"%I:%M%p".into(),
],
}
}
}
impl Validator for Time {
fn validate(&mut self, value: &str) -> bool {
self.formats
.retain(|format| NaiveTime::parse_from_str(value, format).is_ok());
!self.formats.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct DateTime {
pub formats: Vec<DateTimeFormat>,
}
impl DateTime {
pub fn new(formats: Vec<DateTimeFormat>) -> Self {
DateTime { formats }
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum DateTimeFormat {
RFC2822,
RFC3339,
Strftime(String),
Unix,
}
impl Default for DateTime {
fn default() -> Self {
DateTime {
formats: vec![DateTimeFormat::RFC2822, DateTimeFormat::RFC3339],
}
}
}
impl Validator for DateTime {
fn validate(&mut self, value: &str) -> bool {
self.formats.retain(|format| match format {
DateTimeFormat::RFC2822 => ChronoDateTime::parse_from_rfc2822(value).is_ok(),
DateTimeFormat::RFC3339 => ChronoDateTime::parse_from_rfc3339(value).is_ok(),
DateTimeFormat::Strftime(strftime) => {
NaiveDateTime::parse_from_str(value, strftime).is_ok()
}
DateTimeFormat::Unix => value
.parse::<i64>()
.map(|timestamp| NaiveDateTime::from_timestamp_opt(timestamp, 0))
.ok()
.flatten()
.is_some(),
});
!self.formats.is_empty()
}
}
#[cfg(test)]
mod test {
use crate::validators::time::DateTimeFormat;
use crate::Validator;
use crate::{Date, DateTime, Time};
#[test]
fn date() {
let mut validator = Date::default();
assert!(validator.validate("2001-01-22"));
assert_eq!(1, validator.formats.len());
assert_eq!("%Y-%m-%d", validator.formats[0]);
assert!(!validator.validate("22/01/2001"));
let mut validator = Date {
formats: vec!["%Y %m %d".into()],
};
assert!(validator.validate("2001 01 22"));
assert!(!validator.validate("2001-01-22"));
}
#[test]
fn time() {
let mut validator = Time::default();
assert!(validator.validate("12:34:56"));
assert_eq!(1, validator.formats.len());
assert_eq!("%H:%M:%S", validator.formats[0]);
assert!(!validator.validate("12:34PM"));
let mut validator = Time {
formats: vec!["T%H:%M".into()],
};
assert!(validator.validate("T12:34"));
assert!(!validator.validate("12:34PM"));
}
#[test]
fn date_time() {
let mut validator = DateTime::default();
assert!(validator.validate("2001-01-22T00:00:00+00:00"));
assert!(validator.validate("2001-01-22T00:00:00Z"));
assert_eq!(1, validator.formats.len());
assert_eq!(DateTimeFormat::RFC3339, validator.formats[0]);
assert!(!validator.validate("Mon, 22 Jan 2001 00:00:00 GMT"));
let mut validator = DateTime::default();
assert!(validator.validate("Mon, 22 Jan 2001 00:00:00 GMT"));
assert_eq!(1, validator.formats.len());
assert_eq!(DateTimeFormat::RFC2822, validator.formats[0]);
assert!(!validator.validate("2001-01-22T00:00:00+00:00"));
let mut validator = DateTime {
formats: vec![DateTimeFormat::Unix],
};
assert!(validator.validate("980121600"));
assert!(!validator.validate("2001-01-22T00:00:00+00:00"));
}
}