pub struct DateTimeParser {
relaxed_weekday: bool,
}
Expand description
A parser for RFC 2822 datetimes.
§Warning
The RFC 2822 format only supports writing a precise instant in time
expressed via a time zone offset. It does not support serializing
the time zone itself. This means that if you format a zoned datetime
in a time zone like America/New_York
and then deserialize it, the
zoned datetime you get back will be a “fixed offset” zoned datetime.
This in turn means it will not perform daylight saving time safe
arithmetic.
Basically, you should use the RFC 2822 format if it’s required (for example, when dealing with email). But you should not choose it as a general interchange format for new applications.
§Example
This example shows how serializing a zoned datetime to RFC 2822 format and then deserializing will drop information:
use jiff::{civil::date, fmt::rfc2822};
let zdt = date(2024, 7, 13)
.at(15, 9, 59, 789_000_000)
.in_tz("America/New_York")?;
// The default format (i.e., Temporal) guarantees lossless
// serialization.
assert_eq!(zdt.to_string(), "2024-07-13T15:09:59.789-04:00[America/New_York]");
let rfc2822 = rfc2822::to_string(&zdt)?;
// Notice that the time zone name and fractional seconds have been dropped!
assert_eq!(rfc2822, "Sat, 13 Jul 2024 15:09:59 -0400");
// And of course, if we parse it back, all that info is still lost.
// Which means this `zdt` cannot do DST safe arithmetic!
let zdt = rfc2822::parse(&rfc2822)?;
assert_eq!(zdt.to_string(), "2024-07-13T15:09:59-04:00[-04:00]");
Fields§
§relaxed_weekday: bool
Implementations§
Source§impl DateTimeParser
impl DateTimeParser
Sourcepub const fn new() -> DateTimeParser
pub const fn new() -> DateTimeParser
Create a new RFC 2822 datetime parser with the default configuration.
Sourcepub const fn relaxed_weekday(self, yes: bool) -> DateTimeParser
pub const fn relaxed_weekday(self, yes: bool) -> DateTimeParser
When enabled, parsing will permit the weekday to be inconsistent with the date. When enabled, the weekday is still parsed and can result in an error if it isn’t a valid weekday. Only the error checking for whether it is the correct weekday for the parsed date is disabled.
This is sometimes useful for interaction with systems that don’t do strict error checking.
This is disabled by default. And note that RFC 2822 compliance requires that the weekday is consistent with the date.
§Example
use jiff::{civil::date, fmt::rfc2822};
let string = "Sun, 13 Jul 2024 15:09:59 -0400";
// The above normally results in an error, since 2024-07-13 is a
// Saturday:
assert!(rfc2822::parse(string).is_err());
// But we can relax the error checking:
static P: rfc2822::DateTimeParser = rfc2822::DateTimeParser::new()
.relaxed_weekday(true);
assert_eq!(
P.parse_zoned(string)?,
date(2024, 7, 13).at(15, 9, 59, 0).in_tz("America/New_York")?,
);
// But note that something that isn't recognized as a valid weekday
// will still result in an error:
assert!(P.parse_zoned("Wat, 13 Jul 2024 15:09:59 -0400").is_err());
Sourcepub fn parse_zoned<I: AsRef<[u8]>>(&self, input: I) -> Result<Zoned, Error>
pub fn parse_zoned<I: AsRef<[u8]>>(&self, input: I) -> Result<Zoned, Error>
Parse a datetime string into a Zoned
value.
Note that RFC 2822 does not support time zone annotations. The zoned datetime returned will therefore always have a fixed offset time zone.
§Warning
The RFC 2822 format only supports writing a precise instant in time
expressed via a time zone offset. It does not support serializing
the time zone itself. This means that if you format a zoned datetime
in a time zone like America/New_York
and then deserialize it, the
zoned datetime you get back will be a “fixed offset” zoned datetime.
This in turn means it will not perform daylight saving time safe
arithmetic.
Basically, you should use the RFC 2822 format if it’s required (for example, when dealing with email). But you should not choose it as a general interchange format for new applications.
§Errors
This returns an error if the datetime string given is invalid or if it is valid but doesn’t fit in the datetime range supported by Jiff. For example, RFC 2822 supports offsets up to 99 hours and 59 minutes, but Jiff’s maximum offset is 25 hours, 59 minutes and 59 seconds.
§Example
This shows a basic example of parsing a Timestamp
from an RFC 2822
datetime string.
use jiff::fmt::rfc2822::DateTimeParser;
static PARSER: DateTimeParser = DateTimeParser::new();
let zdt = PARSER.parse_zoned("Thu, 29 Feb 2024 05:34 -0500")?;
assert_eq!(zdt.to_string(), "2024-02-29T05:34:00-05:00[-05:00]");
Sourcepub fn parse_timestamp<I: AsRef<[u8]>>(
&self,
input: I,
) -> Result<Timestamp, Error>
pub fn parse_timestamp<I: AsRef<[u8]>>( &self, input: I, ) -> Result<Timestamp, Error>
Parse an RFC 2822 datetime string into a Timestamp
.
§Errors
This returns an error if the datetime string given is invalid or if it is valid but doesn’t fit in the datetime range supported by Jiff. For example, RFC 2822 supports offsets up to 99 hours and 59 minutes, but Jiff’s maximum offset is 25 hours, 59 minutes and 59 seconds.
§Example
This shows a basic example of parsing a Timestamp
from an RFC 2822
datetime string.
use jiff::fmt::rfc2822::DateTimeParser;
static PARSER: DateTimeParser = DateTimeParser::new();
let timestamp = PARSER.parse_timestamp("Thu, 29 Feb 2024 05:34 -0500")?;
assert_eq!(timestamp.to_string(), "2024-02-29T10:34:00Z");
Sourcefn parse_zoned_internal<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, Zoned>, Error>
fn parse_zoned_internal<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, Zoned>, Error>
Parses an RFC 2822 datetime as a zoned datetime.
Note that this doesn’t check that the input has been completely consumed.
Sourcefn parse_timestamp_internal<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, Timestamp>, Error>
fn parse_timestamp_internal<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, Timestamp>, Error>
Parses an RFC 2822 datetime as a timestamp.
Note that this doesn’t check that the input has been completely consumed.
Sourcefn parse_datetime_offset<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, (DateTime, Offset)>, Error>
fn parse_datetime_offset<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, (DateTime, Offset)>, Error>
Parse the entirety of the given input into RFC 2822 components: a civil datetime and its offset.
This also consumes any trailing (superfluous) whitespace.
Sourcefn parse_datetime<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, DateTime>, Error>
fn parse_datetime<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, DateTime>, Error>
Parses a civil datetime from an RFC 2822 string. The input may have leading whitespace.
This also parses and trailing whitespace, including requiring at least one whitespace character.
This basically parses everything except for the zone.
Sourcefn parse_weekday<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, Option<Weekday>>, Error>
fn parse_weekday<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, Option<Weekday>>, Error>
Parses an optional weekday at the beginning of an RFC 2822 datetime.
This expects that any optional whitespace preceding the start of an optional day has been stripped and that the input has at least one byte.
When the first byte of the given input is a digit (or is empty), then
this returns None
, as it implies a day is not present. But if it
isn’t a digit, then we assume that it must be a weekday and return an
error based on that assumption if we couldn’t recognize a weekday.
If a weekday is parsed, then this also skips any trailing whitespace (and requires at least one whitespace character).
Sourcefn parse_day<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri8<1, 31>>, Error>
fn parse_day<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri8<1, 31>>, Error>
Parses a 1 or 2 digit day.
This assumes the input starts with what must be an ASCII digit (or it may be empty).
This also parses at least one mandatory whitespace character after the day.
Sourcefn parse_month<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri8<1, 12>>, Error>
fn parse_month<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri8<1, 12>>, Error>
Parses an abbreviated month name.
This assumes the input starts with what must be the beginning of a month name (or the input may be empty).
This also parses at least one mandatory whitespace character after the month name.
Sourcefn parse_year<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri16<-9999, 9999>>, Error>
fn parse_year<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri16<-9999, 9999>>, Error>
Parses a 2, 3 or 4 digit year.
This assumes the input starts with what must be an ASCII digit (or it may be empty).
This also parses at least one mandatory whitespace character after the day.
The 2 or 3 digit years are “obsolete,” which we support by following the rules in RFC 2822:
Where a two or three digit year occurs in a date, the year is to be interpreted as follows: If a two digit year is encountered whose value is between 00 and 49, the year is interpreted by adding 2000, ending up with a value between 2000 and 2049. If a two digit year is encountered with a value between 50 and 99, or any three digit year is encountered, the year is interpreted by adding 1900.
Sourcefn parse_hour<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri8<0, 23>>, Error>
fn parse_hour<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri8<0, 23>>, Error>
Parses a 2-digit hour. This assumes the input begins with what should be an ASCII digit. (i.e., It doesn’t trim leading whitespace.)
This parses a mandatory trailing :
, advancing the input to
immediately after it.
Sourcefn parse_minute<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri8<0, 59>>, Error>
fn parse_minute<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri8<0, 59>>, Error>
Parses a 2-digit minute. This assumes the input begins with what should be an ASCII digit. (i.e., It doesn’t trim leading whitespace.)
Sourcefn parse_second<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ri8<0, 59>>, Error>
fn parse_second<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ri8<0, 59>>, Error>
Parses a 2-digit second. This assumes the input begins with what should be an ASCII digit. (i.e., It doesn’t trim leading whitespace.)
Sourcefn parse_offset<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, Offset>, Error>
fn parse_offset<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, Offset>, Error>
Parses a time zone offset (including obsolete offsets like EDT).
This assumes the offset must begin at the beginning of input
. That
is, any leading whitespace should already have been trimmed.
Sourcefn parse_offset_obsolete<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, Offset>, Error>
fn parse_offset_obsolete<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, Offset>, Error>
Parses an obsolete time zone offset.
Sourcefn parse_time_separator<'i>(
&self,
input: &'i [u8],
) -> Result<Parsed<'i, ()>, Error>
fn parse_time_separator<'i>( &self, input: &'i [u8], ) -> Result<Parsed<'i, ()>, Error>
Parses a time separator. This returns an error if one couldn’t be found.
Sourcefn parse_whitespace<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, ()>, Error>
fn parse_whitespace<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, ()>, Error>
Parses at least one whitespace character. If no whitespace was found, then this returns an error.
Sourcefn skip_whitespace<'i>(&self, input: &'i [u8]) -> Parsed<'i, bool>
fn skip_whitespace<'i>(&self, input: &'i [u8]) -> Parsed<'i, bool>
Skips over any ASCII whitespace at the beginning of input
.
This returns the input unchanged if it does not begin with whitespace.
The resulting value is true
if any whitespace was consumed,
and false
if none was.
Sourcefn skip_comment<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, ()>, Error>
fn skip_comment<'i>(&self, input: &'i [u8]) -> Result<Parsed<'i, ()>, Error>
This attempts to parse and skip any trailing “comment” in an RFC 2822 datetime.
This is a bit more relaxed than what RFC 2822 specifies. We basically just try to balance parenthesis and skip over escapes.
This assumes that if a comment exists, its opening parenthesis is at
the beginning of input
. That is, any leading whitespace has been
stripped.