fix datetime code for bytes
This commit is contained in:
parent
6e7cb5500c
commit
56166018a5
3 changed files with 93 additions and 90 deletions
|
@ -7,7 +7,7 @@ use nom::{
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::error::IMFError;
|
//use crate::error::IMFError;
|
||||||
use crate::rfc5322::mailbox::{mailbox, MailboxRef};
|
use crate::rfc5322::mailbox::{mailbox, MailboxRef};
|
||||||
use crate::text::misc_token::{phrase, Phrase};
|
use crate::text::misc_token::{phrase, Phrase};
|
||||||
use crate::text::whitespace::cfws;
|
use crate::text::whitespace::cfws;
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
use crate::error::IMFError;
|
|
||||||
use crate::fragments::lazy;
|
|
||||||
use crate::fragments::whitespace::{cfws, fws};
|
|
||||||
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveTime};
|
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveTime};
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{is_a, tag, tag_no_case, take_while_m_n},
|
bytes::complete::{is_a, tag, tag_no_case, take_while_m_n},
|
||||||
character,
|
character,
|
||||||
character::complete::{alphanumeric1, digit0, one_of},
|
character::complete::{alphanumeric1, digit0},
|
||||||
combinator::{map, opt, value},
|
combinator::{map, opt, value},
|
||||||
sequence::{delimited, preceded, terminated, tuple},
|
sequence::{delimited, preceded, terminated, tuple},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::text::whitespace::{cfws, fws};
|
||||||
|
//use crate::error::IMFError;
|
||||||
|
|
||||||
const MIN: i32 = 60;
|
const MIN: i32 = 60;
|
||||||
const HOUR: i32 = 60 * MIN;
|
const HOUR: i32 = 60 * MIN;
|
||||||
|
|
||||||
|
/*
|
||||||
impl<'a> TryFrom<&'a lazy::DateTime<'a>> for DateTime<FixedOffset> {
|
impl<'a> TryFrom<&'a lazy::DateTime<'a>> for DateTime<FixedOffset> {
|
||||||
type Error = IMFError<'a>;
|
type Error = IMFError<'a>;
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ impl<'a> TryFrom<&'a lazy::DateTime<'a>> for DateTime<FixedOffset> {
|
||||||
_ => Err(IMFError::DateTimeLogic),
|
_ => Err(IMFError::DateTimeLogic),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/// Read datetime
|
/// Read datetime
|
||||||
///
|
///
|
||||||
|
@ -42,7 +43,7 @@ impl<'a> TryFrom<&'a lazy::DateTime<'a>> for DateTime<FixedOffset> {
|
||||||
/// - Obsolete military zones should be considered as NaiveTime
|
/// - Obsolete military zones should be considered as NaiveTime
|
||||||
/// due to an error in RFC0822 but are interpreted as their respective
|
/// due to an error in RFC0822 but are interpreted as their respective
|
||||||
/// timezone according to the RFC5322 definition
|
/// timezone according to the RFC5322 definition
|
||||||
pub fn section(input: &str) -> IResult<&str, Option<DateTime<FixedOffset>>> {
|
pub fn section(input: &[u8]) -> IResult<&[u8], Option<DateTime<FixedOffset>>> {
|
||||||
map(
|
map(
|
||||||
terminated(
|
terminated(
|
||||||
alt((
|
alt((
|
||||||
|
@ -71,95 +72,96 @@ pub fn section(input: &str) -> IResult<&str, Option<DateTime<FixedOffset>>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// day-of-week = ([FWS] day-name) / obs-day-of-week
|
/// day-of-week = ([FWS] day-name) / obs-day-of-week
|
||||||
fn strict_day_of_week(input: &str) -> IResult<&str, &str> {
|
fn strict_day_of_week(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
preceded(opt(fws), day_name)(input)
|
preceded(opt(fws), day_name)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// obs-day-of-week = [CFWS] day-name [CFWS]
|
/// obs-day-of-week = [CFWS] day-name [CFWS]
|
||||||
fn obs_day_of_week(input: &str) -> IResult<&str, &str> {
|
fn obs_day_of_week(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
delimited(opt(cfws), day_name, opt(cfws))(input)
|
delimited(opt(cfws), day_name, opt(cfws))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// day-name = "Mon" / "Tue" / "Wed" / "Thu" /
|
/// day-name = "Mon" / "Tue" / "Wed" / "Thu" /
|
||||||
/// "Fri" / "Sat" / "Sun"
|
/// "Fri" / "Sat" / "Sun"
|
||||||
fn day_name(input: &str) -> IResult<&str, &str> {
|
fn day_name(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
alt((
|
alt((
|
||||||
tag_no_case("Mon"),
|
tag_no_case(b"Mon"),
|
||||||
tag_no_case("Tue"),
|
tag_no_case(b"Tue"),
|
||||||
tag_no_case("Wed"),
|
tag_no_case(b"Wed"),
|
||||||
tag_no_case("Thu"),
|
tag_no_case(b"Thu"),
|
||||||
tag_no_case("Fri"),
|
tag_no_case(b"Fri"),
|
||||||
tag_no_case("Sat"),
|
tag_no_case(b"Sat"),
|
||||||
tag_no_case("Sun"),
|
tag_no_case(b"Sun"),
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// date = day month year
|
/// date = day month year
|
||||||
fn strict_date(input: &str) -> IResult<&str, Option<NaiveDate>> {
|
fn strict_date(input: &[u8]) -> IResult<&[u8], Option<NaiveDate>> {
|
||||||
map(tuple((strict_day, month, strict_year)), |(d, m, y)| {
|
map(tuple((strict_day, month, strict_year)), |(d, m, y)| {
|
||||||
NaiveDate::from_ymd_opt(y, m, d)
|
NaiveDate::from_ymd_opt(y, m, d)
|
||||||
})(input)
|
})(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// date = day month year
|
/// date = day month year
|
||||||
fn obs_date(input: &str) -> IResult<&str, Option<NaiveDate>> {
|
fn obs_date(input: &[u8]) -> IResult<&[u8], Option<NaiveDate>> {
|
||||||
map(tuple((obs_day, month, obs_year)), |(d, m, y)| {
|
map(tuple((obs_day, month, obs_year)), |(d, m, y)| {
|
||||||
NaiveDate::from_ymd_opt(y, m, d)
|
NaiveDate::from_ymd_opt(y, m, d)
|
||||||
})(input)
|
})(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// day = ([FWS] 1*2DIGIT FWS) / obs-day
|
/// day = ([FWS] 1*2DIGIT FWS) / obs-day
|
||||||
fn strict_day(input: &str) -> IResult<&str, u32> {
|
fn strict_day(input: &[u8]) -> IResult<&[u8], u32> {
|
||||||
delimited(opt(fws), character::complete::u32, fws)(input)
|
delimited(opt(fws), character::complete::u32, fws)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// obs-day = [CFWS] 1*2DIGIT [CFWS]
|
/// obs-day = [CFWS] 1*2DIGIT [CFWS]
|
||||||
fn obs_day(input: &str) -> IResult<&str, u32> {
|
fn obs_day(input: &[u8]) -> IResult<&[u8], u32> {
|
||||||
delimited(opt(cfws), character::complete::u32, opt(cfws))(input)
|
delimited(opt(cfws), character::complete::u32, opt(cfws))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// month = "Jan" / "Feb" / "Mar" / "Apr" /
|
/// month = "Jan" / "Feb" / "Mar" / "Apr" /
|
||||||
/// "May" / "Jun" / "Jul" / "Aug" /
|
/// "May" / "Jun" / "Jul" / "Aug" /
|
||||||
/// "Sep" / "Oct" / "Nov" / "Dec"
|
/// "Sep" / "Oct" / "Nov" / "Dec"
|
||||||
fn month(input: &str) -> IResult<&str, u32> {
|
fn month(input: &[u8]) -> IResult<&[u8], u32> {
|
||||||
alt((
|
alt((
|
||||||
value(1, tag_no_case("Jan")),
|
value(1, tag_no_case(b"Jan")),
|
||||||
value(2, tag_no_case("Feb")),
|
value(2, tag_no_case(b"Feb")),
|
||||||
value(3, tag_no_case("Mar")),
|
value(3, tag_no_case(b"Mar")),
|
||||||
value(4, tag_no_case("Apr")),
|
value(4, tag_no_case(b"Apr")),
|
||||||
value(5, tag_no_case("May")),
|
value(5, tag_no_case(b"May")),
|
||||||
value(6, tag_no_case("Jun")),
|
value(6, tag_no_case(b"Jun")),
|
||||||
value(7, tag_no_case("Jul")),
|
value(7, tag_no_case(b"Jul")),
|
||||||
value(8, tag_no_case("Aug")),
|
value(8, tag_no_case(b"Aug")),
|
||||||
value(9, tag_no_case("Sep")),
|
value(9, tag_no_case(b"Sep")),
|
||||||
value(10, tag_no_case("Oct")),
|
value(10, tag_no_case(b"Oct")),
|
||||||
value(11, tag_no_case("Nov")),
|
value(11, tag_no_case(b"Nov")),
|
||||||
value(12, tag_no_case("Dec")),
|
value(12, tag_no_case(b"Dec")),
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// year = (FWS 4*DIGIT FWS) / obs-year
|
/// year = (FWS 4*DIGIT FWS) / obs-year
|
||||||
fn strict_year(input: &str) -> IResult<&str, i32> {
|
fn strict_year(input: &[u8]) -> IResult<&[u8], i32> {
|
||||||
delimited(
|
delimited(
|
||||||
fws,
|
fws,
|
||||||
map(
|
map(
|
||||||
terminated(take_while_m_n(4, 9, |c| c >= '\x30' && c <= '\x39'), digit0),
|
terminated(take_while_m_n(4, 9, |c| c >= 0x30 && c <= 0x39), digit0),
|
||||||
|d: &str| d.parse::<i32>().unwrap(),
|
|d: &[u8]| encoding_rs::UTF_8.decode_without_bom_handling(d).0.parse::<i32>().unwrap_or(0),
|
||||||
),
|
),
|
||||||
fws,
|
fws,
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// obs-year = [CFWS] 2*DIGIT [CFWS]
|
/// obs-year = [CFWS] 2*DIGIT [CFWS]
|
||||||
fn obs_year(input: &str) -> IResult<&str, i32> {
|
fn obs_year(input: &[u8]) -> IResult<&[u8], i32> {
|
||||||
map(
|
map(
|
||||||
delimited(
|
delimited(
|
||||||
opt(cfws),
|
opt(cfws),
|
||||||
terminated(take_while_m_n(2, 7, |c| c >= '\x30' && c <= '\x39'), digit0),
|
terminated(take_while_m_n(2, 7, |c| c >= 0x30 && c <= 0x39), digit0),
|
||||||
opt(cfws),
|
opt(cfws),
|
||||||
),
|
),
|
||||||
|cap: &str| {
|
|cap: &[u8]| {
|
||||||
let d = cap.parse::<i32>().unwrap();
|
let year_txt = encoding_rs::UTF_8.decode_without_bom_handling(cap).0;
|
||||||
|
let d = year_txt.parse::<i32>().unwrap_or(0);
|
||||||
if d >= 0 && d <= 49 {
|
if d >= 0 && d <= 49 {
|
||||||
2000 + d
|
2000 + d
|
||||||
} else if d >= 50 && d <= 999 {
|
} else if d >= 50 && d <= 999 {
|
||||||
|
@ -172,7 +174,7 @@ fn obs_year(input: &str) -> IResult<&str, i32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// time-of-day = hour ":" minute [ ":" second ]
|
/// time-of-day = hour ":" minute [ ":" second ]
|
||||||
fn strict_time_of_day(input: &str) -> IResult<&str, Option<NaiveTime>> {
|
fn strict_time_of_day(input: &[u8]) -> IResult<&[u8], Option<NaiveTime>> {
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
strict_time_digit,
|
strict_time_digit,
|
||||||
|
@ -187,7 +189,7 @@ fn strict_time_of_day(input: &str) -> IResult<&str, Option<NaiveTime>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// time-of-day = hour ":" minute [ ":" second ]
|
/// time-of-day = hour ":" minute [ ":" second ]
|
||||||
fn obs_time_of_day(input: &str) -> IResult<&str, Option<NaiveTime>> {
|
fn obs_time_of_day(input: &[u8]) -> IResult<&[u8], Option<NaiveTime>> {
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
obs_time_digit,
|
obs_time_digit,
|
||||||
|
@ -201,11 +203,11 @@ fn obs_time_of_day(input: &str) -> IResult<&str, Option<NaiveTime>> {
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strict_time_digit(input: &str) -> IResult<&str, u32> {
|
fn strict_time_digit(input: &[u8]) -> IResult<&[u8], u32> {
|
||||||
character::complete::u32(input)
|
character::complete::u32(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn obs_time_digit(input: &str) -> IResult<&str, u32> {
|
fn obs_time_digit(input: &[u8]) -> IResult<&[u8], u32> {
|
||||||
delimited(opt(cfws), character::complete::u32, opt(cfws))(input)
|
delimited(opt(cfws), character::complete::u32, opt(cfws))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,20 +216,20 @@ fn obs_time_digit(input: &str) -> IResult<&str, u32> {
|
||||||
/// ```abnf
|
/// ```abnf
|
||||||
/// zone = (FWS ( "+" / "-" ) 4DIGIT) / (FWS obs-zone)
|
/// zone = (FWS ( "+" / "-" ) 4DIGIT) / (FWS obs-zone)
|
||||||
/// ```
|
/// ```
|
||||||
fn strict_zone(input: &str) -> IResult<&str, Option<FixedOffset>> {
|
fn strict_zone(input: &[u8]) -> IResult<&[u8], Option<FixedOffset>> {
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
opt(fws),
|
opt(fws),
|
||||||
is_a("+-"),
|
is_a("+-"),
|
||||||
take_while_m_n(2, 2, |c| c >= '\x30' && c <= '\x39'),
|
take_while_m_n(2, 2, |c| c >= 0x30 && c <= 0x39),
|
||||||
take_while_m_n(2, 2, |c| c >= '\x30' && c <= '\x39'),
|
take_while_m_n(2, 2, |c| c >= 0x30 && c <= 0x39),
|
||||||
)),
|
)),
|
||||||
|(_, op, dig_zone_hour, dig_zone_min)| {
|
|(_, op, dig_zone_hour, dig_zone_min)| {
|
||||||
let zone_hour = dig_zone_hour.parse::<i32>().unwrap() * HOUR;
|
let zone_hour: i32 = ((dig_zone_hour[0] - 0x30) * 10 + (dig_zone_hour[1] - 0x30)) as i32 * HOUR;
|
||||||
let zone_min = dig_zone_min.parse::<i32>().unwrap() * MIN;
|
let zone_min: i32 = ((dig_zone_min[0] - 0x30) * 10 + (dig_zone_min[1] - 0x30)) as i32 * MIN;
|
||||||
match op {
|
match op {
|
||||||
"+" => FixedOffset::east_opt(zone_hour + zone_min),
|
b"+" => FixedOffset::east_opt(zone_hour + zone_min),
|
||||||
"-" => FixedOffset::west_opt(zone_hour + zone_min),
|
b"-" => FixedOffset::west_opt(zone_hour + zone_min),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -250,7 +252,7 @@ fn strict_zone(input: &str) -> IResult<&str, Option<FixedOffset>> {
|
||||||
/// %d107-122 / ; upper and lower case
|
/// %d107-122 / ; upper and lower case
|
||||||
/// ;
|
/// ;
|
||||||
/// 1*(ALPHA / DIGIT) ; Unknown legacy timezones
|
/// 1*(ALPHA / DIGIT) ; Unknown legacy timezones
|
||||||
fn obs_zone(input: &str) -> IResult<&str, Option<FixedOffset>> {
|
fn obs_zone(input: &[u8]) -> IResult<&[u8], Option<FixedOffset>> {
|
||||||
// The writing of this function is volontarily verbose
|
// The writing of this function is volontarily verbose
|
||||||
// to keep it straightforward to understand.
|
// to keep it straightforward to understand.
|
||||||
// @FIXME: Could return a TimeZone and not an Option<TimeZone>
|
// @FIXME: Could return a TimeZone and not an Option<TimeZone>
|
||||||
|
@ -262,57 +264,57 @@ fn obs_zone(input: &str) -> IResult<&str, Option<FixedOffset>> {
|
||||||
// Legacy UTC/GMT
|
// Legacy UTC/GMT
|
||||||
value(
|
value(
|
||||||
FixedOffset::west_opt(0 * HOUR),
|
FixedOffset::west_opt(0 * HOUR),
|
||||||
alt((tag("UTC"), tag("UT"), tag("GMT"))),
|
alt((tag_no_case(b"UTC"), tag_no_case(b"UT"), tag_no_case(b"GMT"))),
|
||||||
),
|
),
|
||||||
// USA Timezones
|
// USA Timezones
|
||||||
value(FixedOffset::west_opt(4 * HOUR), tag("EDT")),
|
value(FixedOffset::west_opt(4 * HOUR), tag_no_case(b"EDT")),
|
||||||
value(
|
value(
|
||||||
FixedOffset::west_opt(5 * HOUR),
|
FixedOffset::west_opt(5 * HOUR),
|
||||||
alt((tag("EST"), tag("CDT"))),
|
alt((tag_no_case(b"EST"), tag_no_case(b"CDT"))),
|
||||||
),
|
),
|
||||||
value(
|
value(
|
||||||
FixedOffset::west_opt(6 * HOUR),
|
FixedOffset::west_opt(6 * HOUR),
|
||||||
alt((tag("CST"), tag("MDT"))),
|
alt((tag_no_case(b"CST"), tag_no_case(b"MDT"))),
|
||||||
),
|
),
|
||||||
value(
|
value(
|
||||||
FixedOffset::west_opt(7 * HOUR),
|
FixedOffset::west_opt(7 * HOUR),
|
||||||
alt((tag("MST"), tag("PDT"))),
|
alt((tag_no_case(b"MST"), tag_no_case(b"PDT"))),
|
||||||
),
|
),
|
||||||
value(FixedOffset::west_opt(8 * HOUR), tag("PST")),
|
value(FixedOffset::west_opt(8 * HOUR), tag_no_case(b"PST")),
|
||||||
// Military Timezone UTC
|
// Military Timezone UTC
|
||||||
value(FixedOffset::west_opt(0 * HOUR), tag("Z")),
|
value(FixedOffset::west_opt(0 * HOUR), tag_no_case(b"Z")),
|
||||||
// Military Timezones East
|
// Military Timezones East
|
||||||
map(one_of("ABCDEFGHIKLMabcdefghiklm"), |c| match c {
|
alt((
|
||||||
'A' | 'a' => FixedOffset::east_opt(1 * HOUR),
|
value(FixedOffset::east_opt(1 * HOUR), tag_no_case(b"A")),
|
||||||
'B' | 'b' => FixedOffset::east_opt(2 * HOUR),
|
value(FixedOffset::east_opt(2 * HOUR), tag_no_case(b"B")),
|
||||||
'C' | 'c' => FixedOffset::east_opt(3 * HOUR),
|
value(FixedOffset::east_opt(3 * HOUR), tag_no_case(b"C")),
|
||||||
'D' | 'd' => FixedOffset::east_opt(4 * HOUR),
|
value(FixedOffset::east_opt(4 * HOUR), tag_no_case(b"D")),
|
||||||
'E' | 'e' => FixedOffset::east_opt(5 * HOUR),
|
value(FixedOffset::east_opt(5 * HOUR), tag_no_case(b"E")),
|
||||||
'F' | 'f' => FixedOffset::east_opt(6 * HOUR),
|
value(FixedOffset::east_opt(6 * HOUR), tag_no_case(b"F")),
|
||||||
'G' | 'g' => FixedOffset::east_opt(7 * HOUR),
|
value(FixedOffset::east_opt(7 * HOUR), tag_no_case(b"G")),
|
||||||
'H' | 'h' => FixedOffset::east_opt(8 * HOUR),
|
value(FixedOffset::east_opt(8 * HOUR), tag_no_case(b"H")),
|
||||||
'I' | 'i' => FixedOffset::east_opt(9 * HOUR),
|
value(FixedOffset::east_opt(9 * HOUR), tag_no_case(b"I")),
|
||||||
'K' | 'k' => FixedOffset::east_opt(10 * HOUR),
|
value(FixedOffset::east_opt(10 * HOUR), tag_no_case(b"K")),
|
||||||
'L' | 'l' => FixedOffset::east_opt(11 * HOUR),
|
value(FixedOffset::east_opt(11 * HOUR), tag_no_case(b"L")),
|
||||||
'M' | 'm' => FixedOffset::east_opt(12 * HOUR),
|
value(FixedOffset::east_opt(12 * HOUR), tag_no_case(b"M")),
|
||||||
_ => unreachable!(),
|
)),
|
||||||
}),
|
|
||||||
// Military Timezones West
|
// Military Timezones West
|
||||||
map(one_of("nopqrstuvwxyNOPQRSTUVWXY"), |c| match c {
|
alt((
|
||||||
'N' | 'n' => FixedOffset::west_opt(1 * HOUR),
|
value(FixedOffset::west_opt(1 * HOUR), tag_no_case(b"N")),
|
||||||
'O' | 'o' => FixedOffset::west_opt(2 * HOUR),
|
value(FixedOffset::west_opt(2 * HOUR), tag_no_case(b"O")),
|
||||||
'P' | 'p' => FixedOffset::west_opt(3 * HOUR),
|
value(FixedOffset::west_opt(3 * HOUR), tag_no_case(b"P")),
|
||||||
'Q' | 'q' => FixedOffset::west_opt(4 * HOUR),
|
value(FixedOffset::west_opt(4 * HOUR), tag_no_case(b"Q")),
|
||||||
'R' | 'r' => FixedOffset::west_opt(5 * HOUR),
|
value(FixedOffset::west_opt(5 * HOUR), tag_no_case(b"R")),
|
||||||
'S' | 's' => FixedOffset::west_opt(6 * HOUR),
|
value(FixedOffset::west_opt(6 * HOUR), tag_no_case(b"S")),
|
||||||
'T' | 't' => FixedOffset::west_opt(7 * HOUR),
|
value(FixedOffset::west_opt(7 * HOUR), tag_no_case(b"T")),
|
||||||
'U' | 'u' => FixedOffset::west_opt(8 * HOUR),
|
value(FixedOffset::west_opt(8 * HOUR), tag_no_case(b"U")),
|
||||||
'V' | 'v' => FixedOffset::west_opt(9 * HOUR),
|
value(FixedOffset::west_opt(9 * HOUR), tag_no_case(b"V")),
|
||||||
'W' | 'w' => FixedOffset::west_opt(10 * HOUR),
|
value(FixedOffset::west_opt(10 * HOUR), tag_no_case(b"W")),
|
||||||
'X' | 'x' => FixedOffset::west_opt(11 * HOUR),
|
value(FixedOffset::west_opt(11 * HOUR), tag_no_case(b"X")),
|
||||||
'Y' | 'y' => FixedOffset::west_opt(12 * HOUR),
|
value(FixedOffset::west_opt(12 * HOUR), tag_no_case(b"Y")),
|
||||||
_ => unreachable!(),
|
)),
|
||||||
}),
|
|
||||||
// Unknown timezone
|
// Unknown timezone
|
||||||
value(FixedOffset::west_opt(0 * HOUR), alphanumeric1),
|
value(FixedOffset::west_opt(0 * HOUR), alphanumeric1),
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod mailbox;
|
pub mod mailbox;
|
||||||
pub mod address;
|
pub mod address;
|
||||||
|
pub mod datetime;
|
||||||
|
|
Loading…
Reference in a new issue