melib/datetime: add mbox date format parse
parent
a42a6ca868
commit
29042aba59
|
@ -50,6 +50,7 @@ pub const RFC822_FMT_WITH_TIME: &str = "%a, %e %h %Y %H:%M:%S \0";
|
||||||
pub const RFC822_FMT: &str = "%e %h %Y %H:%M:%S \0";
|
pub const RFC822_FMT: &str = "%e %h %Y %H:%M:%S \0";
|
||||||
pub const DEFAULT_FMT: &str = "%a, %d %b %Y %R\0";
|
pub const DEFAULT_FMT: &str = "%a, %d %b %Y %R\0";
|
||||||
//"Tue May 21 13:46:22 1991\n"
|
//"Tue May 21 13:46:22 1991\n"
|
||||||
|
//"Wed Sep 9 00:27:54 2020\n"
|
||||||
pub const ASCTIME_FMT: &str = "%a %b %d %H:%M:%S %Y\n\0";
|
pub const ASCTIME_FMT: &str = "%a %b %d %H:%M:%S %Y\n\0";
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -301,7 +302,7 @@ where
|
||||||
{
|
{
|
||||||
let s = CString::new(s)?;
|
let s = CString::new(s)?;
|
||||||
let mut new_tm: libc::tm = unsafe { std::mem::zeroed() };
|
let mut new_tm: libc::tm = unsafe { std::mem::zeroed() };
|
||||||
for fmt in &[RFC822_FMT_WITH_TIME, RFC822_FMT] {
|
for fmt in &[RFC822_FMT_WITH_TIME, RFC822_FMT, ASCTIME_FMT] {
|
||||||
let fmt = unsafe { CStr::from_bytes_with_nul_unchecked(fmt.as_bytes()) };
|
let fmt = unsafe { CStr::from_bytes_with_nul_unchecked(fmt.as_bytes()) };
|
||||||
let ret = {
|
let ret = {
|
||||||
let _with_locale = Locale::new(
|
let _with_locale = Locale::new(
|
||||||
|
|
|
@ -443,6 +443,65 @@ pub mod dates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///e.g Wed Sep 9 00:27:54 2020
|
||||||
|
///day-of-week month day time year
|
||||||
|
///date-time = [ day-of-week "," ] date time [CFWS]
|
||||||
|
///date = day month year
|
||||||
|
///time = time-of-day zone
|
||||||
|
///time-of-day = hour ":" minute [ ":" second ]
|
||||||
|
///hour = 2DIGIT / obs-hour
|
||||||
|
///minute = 2DIGIT / obs-minute
|
||||||
|
///second = 2DIGIT / obs-second
|
||||||
|
pub fn mbox_date_time(input: &[u8]) -> IResult<&[u8], UnixTimestamp> {
|
||||||
|
let orig_input = input;
|
||||||
|
let mut accum: SmallVec<[u8; 32]> = SmallVec::new();
|
||||||
|
let (input, _) = opt(cfws)(input)?;
|
||||||
|
let (input, day_of_week) = day_of_week(input)?;
|
||||||
|
let (input, _) = opt(cfws)(input)?;
|
||||||
|
let (input, month) = month(input)?;
|
||||||
|
let (input, _) = opt(cfws)(input)?;
|
||||||
|
let (input, day) = day(input)?;
|
||||||
|
let (input, _) = opt(cfws)(input)?;
|
||||||
|
let (input, hour) = take_n_digits(2)(input)?;
|
||||||
|
let (input, _) = tag(":")(input)?;
|
||||||
|
let (input, minute) = take_n_digits(2)(input)?;
|
||||||
|
let (input, second) = opt(preceded(tag(":"), take_n_digits(2)))(input)?;
|
||||||
|
let (input, _) = fws(input)?;
|
||||||
|
let (input, zone) = opt(zone)(input)?;
|
||||||
|
let (input, _) = opt(cfws)(input)?;
|
||||||
|
let (input, year) = year(input)?;
|
||||||
|
accum.extend_from_slice(&day_of_week);
|
||||||
|
accum.extend_from_slice(b", ");
|
||||||
|
accum.extend_from_slice(&day);
|
||||||
|
accum.extend_from_slice(b" ");
|
||||||
|
accum.extend_from_slice(&month);
|
||||||
|
accum.extend_from_slice(b" ");
|
||||||
|
accum.extend_from_slice(&year);
|
||||||
|
accum.extend_from_slice(b" ");
|
||||||
|
accum.extend_from_slice(&hour);
|
||||||
|
accum.extend_from_slice(b":");
|
||||||
|
accum.extend_from_slice(&minute);
|
||||||
|
if let Some(second) = second {
|
||||||
|
accum.extend_from_slice(b":");
|
||||||
|
accum.extend_from_slice(&second);
|
||||||
|
}
|
||||||
|
if let Some((sign, zone)) = zone {
|
||||||
|
accum.extend_from_slice(b" ");
|
||||||
|
accum.extend_from_slice(&sign);
|
||||||
|
accum.extend_from_slice(&zone);
|
||||||
|
}
|
||||||
|
match crate::datetime::rfc822_to_timestamp(accum.to_vec()) {
|
||||||
|
Ok(t) => Ok((input, t)),
|
||||||
|
Err(_err) => Err(nom::Err::Error(
|
||||||
|
(
|
||||||
|
orig_input,
|
||||||
|
"mbox_date_time(): could not convert date from rfc822",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///`day-of-week = ([FWS] day-name) / obs-day-of-week`
|
///`day-of-week = ([FWS] day-name) / obs-day-of-week`
|
||||||
///day-name = "Mon" / "Tue" / "Wed" / "Thu" /
|
///day-name = "Mon" / "Tue" / "Wed" / "Thu" /
|
||||||
/// "Fri" / "Sat" / "Sun"
|
/// "Fri" / "Sat" / "Sun"
|
||||||
|
@ -490,9 +549,9 @@ pub mod dates {
|
||||||
|
|
||||||
///year = (FWS 4*DIGIT FWS) / obs-year
|
///year = (FWS 4*DIGIT FWS) / obs-year
|
||||||
fn year(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
fn year(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
let (input, _) = fws(input)?;
|
let (input, _) = opt(fws)(input)?;
|
||||||
let (input, ret) = take_n_digits(4)(input)?;
|
let (input, ret) = take_n_digits(4)(input)?;
|
||||||
let (input, _) = fws(input)?;
|
let (input, _) = opt(fws)(input)?;
|
||||||
Ok((input, ret))
|
Ok((input, ret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,6 +570,17 @@ pub mod dates {
|
||||||
};
|
};
|
||||||
Ok((rest, ret))
|
Ok((rest, ret))
|
||||||
})
|
})
|
||||||
|
.or_else(|_| {
|
||||||
|
let (rest, ret) = match mbox_date_time(&input) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
return Err(nom::Err::Error(
|
||||||
|
(input, "rfc5322_date(): invalid input").into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((rest, ret))
|
||||||
|
})
|
||||||
.map(|(_, r)| r)
|
.map(|(_, r)| r)
|
||||||
.map_err(|err: nom::Err<ParsingError<_>>| err.into())
|
.map_err(|err: nom::Err<ParsingError<_>>| err.into())
|
||||||
/*
|
/*
|
||||||
|
@ -532,6 +602,8 @@ pub mod dates {
|
||||||
assert_eq!(rfc5322_date(_s).unwrap(), rfc5322_date(__s).unwrap());
|
assert_eq!(rfc5322_date(_s).unwrap(), rfc5322_date(__s).unwrap());
|
||||||
let val = b"Fri, 23 Dec 0001 21:20:36 -0800 (PST)";
|
let val = b"Fri, 23 Dec 0001 21:20:36 -0800 (PST)";
|
||||||
assert_eq!(rfc5322_date(val).unwrap(), 0);
|
assert_eq!(rfc5322_date(val).unwrap(), 0);
|
||||||
|
let val = b"Wed Sep 9 00:27:54 2020";
|
||||||
|
assert_eq!(rfc5322_date(val).unwrap(), 1599611274);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue