summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2022-08-27 22:30:11 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2022-08-29 11:19:21 +0300
commit29042aba593210f3be73010908d5092951b3b1a1 (patch)
treeb62d41cb4c893a6e2358693271a32f1a3d4065eb
parenta42a6ca868e4590a8b93560737173e80993ecaec (diff)
downloadmeli-29042aba593210f3be73010908d5092951b3b1a1.zip
melib/datetime: add mbox date format parse
-rw-r--r--melib/src/datetime.rs3
-rw-r--r--melib/src/email/parser.rs76
2 files changed, 76 insertions, 3 deletions
diff --git a/melib/src/datetime.rs b/melib/src/datetime.rs
index 1d12ada2..88cf08a8 100644
--- a/melib/src/datetime.rs
+++ b/melib/src/datetime.rs
@@ -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 DEFAULT_FMT: &str = "%a, %d %b %Y %R\0";
//"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";
extern "C" {
@@ -301,7 +302,7 @@ where
{
let s = CString::new(s)?;
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 ret = {
let _with_locale = Locale::new(
diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs
index 29f75446..ba360707 100644
--- a/melib/src/email/parser.rs
+++ b/melib/src/email/parser.rs
@@ -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-name = "Mon" / "Tue" / "Wed" / "Thu" /
/// "Fri" / "Sat" / "Sun"
@@ -490,9 +549,9 @@ pub mod dates {
///year = (FWS 4*DIGIT FWS) / obs-year
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, _) = fws(input)?;
+ let (input, _) = opt(fws)(input)?;
Ok((input, ret))
}
@@ -511,6 +570,17 @@ pub mod dates {
};
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_err(|err: nom::Err<ParsingError<_>>| err.into())
/*
@@ -532,6 +602,8 @@ pub mod dates {
assert_eq!(rfc5322_date(_s).unwrap(), rfc5322_date(__s).unwrap());
let val = b"Fri, 23 Dec 0001 21:20:36 -0800 (PST)";
assert_eq!(rfc5322_date(val).unwrap(), 0);
+ let val = b"Wed Sep 9 00:27:54 2020";
+ assert_eq!(rfc5322_date(val).unwrap(), 1599611274);
}
}