Merge pull request #360 from quodlibetor/chrono-0_4_10

Prepare for and Bump Chrono version to 0.4.10
This commit is contained in:
Brandon W Maister 2019-11-23 19:53:58 -05:00 committed by GitHub
commit 5b4fc23bcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 166 additions and 153 deletions

View File

@ -8,13 +8,29 @@ Chrono obeys the principle of [Semantic Versioning](http://semver.org/).
There were/are numerous minor versions before 1.0 due to the language changes. There were/are numerous minor versions before 1.0 due to the language changes.
Versions with only mechanical changes will be omitted from the following list. Versions with only mechanical changes will be omitted from the following list.
## next ## 0.4.10
### Improvements
* `DateTime::parse_from_str` is more than 2x faster in some cases. (@michalsrb
#358)
* Significant improvements to no-std and alloc support (This should also make
many format/serialization operations induce zero unnecessary allocations)
(@CryZe #341)
### Features ### Features
* Functions that were accepting `Iterator` of `Item`s (for example * Functions that were accepting `Iterator` of `Item`s (for example
`format_with_items`) now accept `Iterator` of `Borrow<Item>`, so one can `format_with_items`) now accept `Iterator` of `Borrow<Item>`, so one can
use values or references. use values or references. (@michalsrb #358)
* Add built-in support for structs with nested `Option<Datetime>` etc fields
(@manifest #302)
### Internal/doc improvements
* Use markdown footnotes on the `strftime` docs page (@qudlibetor #359)
* Migrate from `try!` -> `?` (question mark) because it is now emitting
deprecation warnings and has been stable since rustc 1.13.0
## 0.4.9 ## 0.4.9

View File

@ -1,6 +1,6 @@
[package] [package]
name = "chrono" name = "chrono"
version = "0.4.9" version = "0.4.10"
authors = [ authors = [
"Kang Seonghoon <public+rust@mearie.org>", "Kang Seonghoon <public+rust@mearie.org>",
"Brandon W Maister <quodlibetor@gmail.com>", "Brandon W Maister <quodlibetor@gmail.com>",

View File

@ -327,7 +327,7 @@ impl DateTime<FixedOffset> {
pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> { pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> {
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)]; const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_datetime() parsed.to_datetime()
} }
@ -339,7 +339,7 @@ impl DateTime<FixedOffset> {
pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> { pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)]; const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_datetime() parsed.to_datetime()
} }
@ -365,7 +365,7 @@ impl DateTime<FixedOffset> {
/// ``` /// ```
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>> { pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_datetime() parsed.to_datetime()
} }
} }
@ -639,7 +639,7 @@ impl str::FromStr for DateTime<FixedOffset> {
]; ];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_datetime() parsed.to_datetime()
} }
} }
@ -808,7 +808,7 @@ pub mod rustc_serialize {
} }
} }
// try!-like function to convert a LocalResult into a serde-ish Result // lik? function to convert a LocalResult into a serde-ish Result
fn from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error> fn from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error>
where D: Decoder, where D: Decoder,
T: fmt::Display, T: fmt::Display,
@ -943,7 +943,7 @@ pub mod serde {
#[derive(Debug)] #[derive(Debug)]
pub struct MilliSecondsTimestampVisitor; pub struct MilliSecondsTimestampVisitor;
// try!-like function to convert a LocalResult into a serde-ish Result // lik? function to convert a LocalResult into a serde-ish Result
fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E>
where where
E: de::Error, E: de::Error,
@ -1073,7 +1073,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(NanoSecondsTimestampVisitor))) Ok(d.deserialize_i64(NanoSecondsTimestampVisitor)?)
} }
impl<'de> de::Visitor<'de> for NanoSecondsTimestampVisitor { impl<'de> de::Visitor<'de> for NanoSecondsTimestampVisitor {
@ -1220,7 +1220,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_option(OptionNanoSecondsTimestampVisitor))) Ok(d.deserialize_option(OptionNanoSecondsTimestampVisitor)?)
} }
struct OptionNanoSecondsTimestampVisitor; struct OptionNanoSecondsTimestampVisitor;
@ -1364,7 +1364,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(MilliSecondsTimestampVisitor).map(|dt| dt.with_timezone(&Utc)))) Ok(d.deserialize_i64(MilliSecondsTimestampVisitor).map(|dt| dt.with_timezone(&Utc))?)
} }
impl<'de> de::Visitor<'de> for MilliSecondsTimestampVisitor { impl<'de> de::Visitor<'de> for MilliSecondsTimestampVisitor {
@ -1511,7 +1511,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_option(OptionMilliSecondsTimestampVisitor).map(|opt| opt.map(|dt| dt.with_timezone(&Utc))))) Ok(d.deserialize_option(OptionMilliSecondsTimestampVisitor).map(|opt| opt.map(|dt| dt.with_timezone(&Utc)))?)
} }
struct OptionMilliSecondsTimestampVisitor; struct OptionMilliSecondsTimestampVisitor;
@ -1655,7 +1655,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(SecondsTimestampVisitor))) Ok(d.deserialize_i64(SecondsTimestampVisitor)?)
} }
impl<'de> de::Visitor<'de> for SecondsTimestampVisitor { impl<'de> de::Visitor<'de> for SecondsTimestampVisitor {
@ -1798,7 +1798,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_option(OptionSecondsTimestampVisitor))) Ok(d.deserialize_option(OptionSecondsTimestampVisitor)?)
} }
struct OptionSecondsTimestampVisitor; struct OptionSecondsTimestampVisitor;

View File

@ -433,22 +433,20 @@ pub fn format<'a, I, B>(
if let Some(v) = v { if let Some(v) = v {
try!( if (spec == &Year || spec == &IsoYear) && !(0 <= v && v < 10_000) {
if (spec == &Year || spec == &IsoYear) && !(0 <= v && v < 10_000) { // non-four-digit years require an explicit sign as per ISO 8601
// non-four-digit years require an explicit sign as per ISO 8601 match pad {
match pad { &Pad::None => write!(result, "{:+}", v),
&Pad::None => write!(result, "{:+}", v), &Pad::Zero => write!(result, "{:+01$}", v, width + 1),
&Pad::Zero => write!(result, "{:+01$}", v, width + 1), &Pad::Space => write!(result, "{:+1$}", v, width + 1),
&Pad::Space => write!(result, "{:+1$}", v, width + 1),
}
} else {
match pad {
&Pad::None => write!(result, "{}", v),
&Pad::Zero => write!(result, "{:01$}", v, width),
&Pad::Space => write!(result, "{:1$}", v, width),
}
} }
) } else {
match pad {
&Pad::None => write!(result, "{}", v),
&Pad::Zero => write!(result, "{:01$}", v, width),
&Pad::Space => write!(result, "{:1$}", v, width),
}
}?
} else { } else {
return Err(fmt::Error) // insufficient arguments for given format return Err(fmt::Error) // insufficient arguments for given format
} }
@ -575,13 +573,13 @@ pub fn format<'a, I, B>(
&RFC2822 => // same to `%a, %e %b %Y %H:%M:%S %z` &RFC2822 => // same to `%a, %e %b %Y %H:%M:%S %z`
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
let sec = t.second() + t.nanosecond() / 1_000_000_000; let sec = t.second() + t.nanosecond() / 1_000_000_000;
try!(write!( write!(
result, result,
"{}, {:02} {} {:04} {:02}:{:02}:{:02} ", "{}, {:02} {} {:04} {:02}:{:02}:{:02} ",
SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize], SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize],
d.day(), SHORT_MONTHS[d.month0() as usize], d.year(), d.day(), SHORT_MONTHS[d.month0() as usize], d.year(),
t.hour(), t.minute(), sec t.hour(), t.minute(), sec
)); )?;
Some(write_local_minus_utc(&mut result, off, false, false)) Some(write_local_minus_utc(&mut result, off, false, false))
} else { } else {
None None
@ -590,7 +588,7 @@ pub fn format<'a, I, B>(
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
// reuse `Debug` impls which already print ISO 8601 format. // reuse `Debug` impls which already print ISO 8601 format.
// this is faster in this way. // this is faster in this way.
try!(write!(result, "{:?}T{:?}", d, t)); write!(result, "{:?}T{:?}", d, t)?;
Some(write_local_minus_utc(&mut result, off, false, true)) Some(write_local_minus_utc(&mut result, off, false, true))
} else { } else {
None None
@ -598,7 +596,7 @@ pub fn format<'a, I, B>(
}; };
match ret { match ret {
Some(ret) => try!(ret), Some(ret) => ret?,
None => return Err(fmt::Error), // insufficient arguments for given format None => return Err(fmt::Error), // insufficient arguments for given format
} }
}, },

View File

@ -33,7 +33,7 @@ fn set_weekday_with_number_from_monday(p: &mut Parsed, v: i64) -> ParseResult<()
fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> { fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> {
macro_rules! try_consume { macro_rules! try_consume {
($e:expr) => ({ let (s_, v) = try!($e); s = s_; v }) ($e:expr) => ({ let (s_, v) = $e?; s = s_; v })
} }
// an adapted RFC 2822 syntax from Section 3.3 and 4.3: // an adapted RFC 2822 syntax from Section 3.3 and 4.3:
@ -90,14 +90,14 @@ fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
if let Ok((s_, weekday)) = scan::short_weekday(s) { if let Ok((s_, weekday)) = scan::short_weekday(s) {
if !s_.starts_with(',') { return Err(INVALID); } if !s_.starts_with(',') { return Err(INVALID); }
s = &s_[1..]; s = &s_[1..];
try!(parsed.set_weekday(weekday)); parsed.set_weekday(weekday)?;
} }
s = s.trim_left(); s = s.trim_left();
try!(parsed.set_day(try_consume!(scan::number(s, 1, 2)))); parsed.set_day(try_consume!(scan::number(s, 1, 2)))?;
s = try!(scan::space(s)); // mandatory s = scan::space(s)?; // mandatory
try!(parsed.set_month(1 + i64::from(try_consume!(scan::short_month0(s))))); parsed.set_month(1 + i64::from(try_consume!(scan::short_month0(s))))?;
s = try!(scan::space(s)); // mandatory s = scan::space(s)?; // mandatory
// distinguish two- and three-digit years from four-digit years // distinguish two- and three-digit years from four-digit years
let prevlen = s.len(); let prevlen = s.len();
@ -109,20 +109,20 @@ fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
(3, _) => { year += 1900; } // 112 -> 2012, 009 -> 1909 (3, _) => { year += 1900; } // 112 -> 2012, 009 -> 1909
(_, _) => {} // 1987 -> 1987, 0654 -> 0654 (_, _) => {} // 1987 -> 1987, 0654 -> 0654
} }
try!(parsed.set_year(year)); parsed.set_year(year)?;
s = try!(scan::space(s)); // mandatory s = scan::space(s)?; // mandatory
try!(parsed.set_hour(try_consume!(scan::number(s, 2, 2)))); parsed.set_hour(try_consume!(scan::number(s, 2, 2)))?;
s = try!(scan::char(s.trim_left(), b':')).trim_left(); // *S ":" *S s = scan::char(s.trim_left(), b':')?.trim_left(); // *S ":" *S
try!(parsed.set_minute(try_consume!(scan::number(s, 2, 2)))); parsed.set_minute(try_consume!(scan::number(s, 2, 2)))?;
if let Ok(s_) = scan::char(s.trim_left(), b':') { // [ ":" *S 2DIGIT ] if let Ok(s_) = scan::char(s.trim_left(), b':') { // [ ":" *S 2DIGIT ]
try!(parsed.set_second(try_consume!(scan::number(s_, 2, 2)))); parsed.set_second(try_consume!(scan::number(s_, 2, 2)))?;
} }
s = try!(scan::space(s)); // mandatory s = scan::space(s)?; // mandatory
if let Some(offset) = try_consume!(scan::timezone_offset_2822(s)) { if let Some(offset) = try_consume!(scan::timezone_offset_2822(s)) {
// only set the offset when it is definitely known (i.e. not `-0000`) // only set the offset when it is definitely known (i.e. not `-0000`)
try!(parsed.set_offset(i64::from(offset))); parsed.set_offset(i64::from(offset))?;
} }
Ok((s, ())) Ok((s, ()))
@ -130,7 +130,7 @@ fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> { fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> {
macro_rules! try_consume { macro_rules! try_consume {
($e:expr) => ({ let (s_, v) = try!($e); s = s_; v }) ($e:expr) => ({ let (s_, v) = $e?; s = s_; v })
} }
// an adapted RFC 3339 syntax from Section 5.6: // an adapted RFC 3339 syntax from Section 5.6:
@ -160,11 +160,11 @@ fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
// note that this restriction is unique to RFC 3339 and not ISO 8601. // note that this restriction is unique to RFC 3339 and not ISO 8601.
// since this is not a typical Chrono behavior, we check it earlier. // since this is not a typical Chrono behavior, we check it earlier.
try!(parsed.set_year(try_consume!(scan::number(s, 4, 4)))); parsed.set_year(try_consume!(scan::number(s, 4, 4)))?;
s = try!(scan::char(s, b'-')); s = scan::char(s, b'-')?;
try!(parsed.set_month(try_consume!(scan::number(s, 2, 2)))); parsed.set_month(try_consume!(scan::number(s, 2, 2)))?;
s = try!(scan::char(s, b'-')); s = scan::char(s, b'-')?;
try!(parsed.set_day(try_consume!(scan::number(s, 2, 2)))); parsed.set_day(try_consume!(scan::number(s, 2, 2)))?;
s = match s.as_bytes().first() { s = match s.as_bytes().first() {
Some(&b't') | Some(&b'T') => &s[1..], Some(&b't') | Some(&b'T') => &s[1..],
@ -172,19 +172,19 @@ fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
None => return Err(TOO_SHORT), None => return Err(TOO_SHORT),
}; };
try!(parsed.set_hour(try_consume!(scan::number(s, 2, 2)))); parsed.set_hour(try_consume!(scan::number(s, 2, 2)))?;
s = try!(scan::char(s, b':')); s = scan::char(s, b':')?;
try!(parsed.set_minute(try_consume!(scan::number(s, 2, 2)))); parsed.set_minute(try_consume!(scan::number(s, 2, 2)))?;
s = try!(scan::char(s, b':')); s = scan::char(s, b':')?;
try!(parsed.set_second(try_consume!(scan::number(s, 2, 2)))); parsed.set_second(try_consume!(scan::number(s, 2, 2)))?;
if s.starts_with('.') { if s.starts_with('.') {
let nanosecond = try_consume!(scan::nanosecond(&s[1..])); let nanosecond = try_consume!(scan::nanosecond(&s[1..]));
try!(parsed.set_nanosecond(nanosecond)); parsed.set_nanosecond(nanosecond)?;
} }
let offset = try_consume!(scan::timezone_offset_zulu(s, |s| scan::char(s, b':'))); let offset = try_consume!(scan::timezone_offset_zulu(s, |s| scan::char(s, b':')));
if offset <= -86_400 || offset >= 86_400 { return Err(OUT_OF_RANGE); } if offset <= -86_400 || offset >= 86_400 { return Err(OUT_OF_RANGE); }
try!(parsed.set_offset(i64::from(offset))); parsed.set_offset(i64::from(offset))?;
Ok((s, ())) Ok((s, ()))
} }
@ -208,7 +208,7 @@ fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<()> pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<()>
where I: Iterator<Item=B>, B: Borrow<Item<'a>> { where I: Iterator<Item=B>, B: Borrow<Item<'a>> {
macro_rules! try_consume { macro_rules! try_consume {
($e:expr) => ({ let (s_, v) = try!($e); s = s_; v }) ($e:expr) => ({ let (s_, v) = $e?; s = s_; v })
} }
for item in items { for item in items {
@ -269,7 +269,7 @@ pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResul
let v = if signed { let v = if signed {
if s.starts_with('-') { if s.starts_with('-') {
let v = try_consume!(scan::number(&s[1..], 1, usize::MAX)); let v = try_consume!(scan::number(&s[1..], 1, usize::MAX));
try!(0i64.checked_sub(v).ok_or(OUT_OF_RANGE)) 0i64.checked_sub(v).ok_or(OUT_OF_RANGE)?
} else if s.starts_with('+') { } else if s.starts_with('+') {
try_consume!(scan::number(&s[1..], 1, usize::MAX)) try_consume!(scan::number(&s[1..], 1, usize::MAX))
} else { } else {
@ -279,7 +279,7 @@ pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResul
} else { } else {
try_consume!(scan::number(s, 1, width)) try_consume!(scan::number(s, 1, width))
}; };
try!(set(parsed, v)); set(parsed, v)?;
} }
&Item::Fixed(ref spec) => { &Item::Fixed(ref spec) => {
@ -288,22 +288,22 @@ pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResul
match spec { match spec {
&ShortMonthName => { &ShortMonthName => {
let month0 = try_consume!(scan::short_month0(s)); let month0 = try_consume!(scan::short_month0(s));
try!(parsed.set_month(i64::from(month0) + 1)); parsed.set_month(i64::from(month0) + 1)?;
} }
&LongMonthName => { &LongMonthName => {
let month0 = try_consume!(scan::short_or_long_month0(s)); let month0 = try_consume!(scan::short_or_long_month0(s));
try!(parsed.set_month(i64::from(month0) + 1)); parsed.set_month(i64::from(month0) + 1)?;
} }
&ShortWeekdayName => { &ShortWeekdayName => {
let weekday = try_consume!(scan::short_weekday(s)); let weekday = try_consume!(scan::short_weekday(s));
try!(parsed.set_weekday(weekday)); parsed.set_weekday(weekday)?;
} }
&LongWeekdayName => { &LongWeekdayName => {
let weekday = try_consume!(scan::short_or_long_weekday(s)); let weekday = try_consume!(scan::short_or_long_weekday(s));
try!(parsed.set_weekday(weekday)); parsed.set_weekday(weekday)?;
} }
&LowerAmPm | &UpperAmPm => { &LowerAmPm | &UpperAmPm => {
@ -313,33 +313,33 @@ pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResul
(b'p',b'm') => true, (b'p',b'm') => true,
_ => return Err(INVALID) _ => return Err(INVALID)
}; };
try!(parsed.set_ampm(ampm)); parsed.set_ampm(ampm)?;
s = &s[2..]; s = &s[2..];
} }
&Nanosecond | &Nanosecond3 | &Nanosecond6 | &Nanosecond9 => { &Nanosecond | &Nanosecond3 | &Nanosecond6 | &Nanosecond9 => {
if s.starts_with('.') { if s.starts_with('.') {
let nano = try_consume!(scan::nanosecond(&s[1..])); let nano = try_consume!(scan::nanosecond(&s[1..]));
try!(parsed.set_nanosecond(nano)); parsed.set_nanosecond(nano)?;
} }
} }
&Internal(InternalFixed { val: InternalInternal::Nanosecond3NoDot }) => { &Internal(InternalFixed { val: InternalInternal::Nanosecond3NoDot }) => {
if s.len() < 3 { return Err(TOO_SHORT); } if s.len() < 3 { return Err(TOO_SHORT); }
let nano = try_consume!(scan::nanosecond_fixed(s, 3)); let nano = try_consume!(scan::nanosecond_fixed(s, 3));
try!(parsed.set_nanosecond(nano)); parsed.set_nanosecond(nano)?;
} }
&Internal(InternalFixed { val: InternalInternal::Nanosecond6NoDot }) => { &Internal(InternalFixed { val: InternalInternal::Nanosecond6NoDot }) => {
if s.len() < 6 { return Err(TOO_SHORT); } if s.len() < 6 { return Err(TOO_SHORT); }
let nano = try_consume!(scan::nanosecond_fixed(s, 6)); let nano = try_consume!(scan::nanosecond_fixed(s, 6));
try!(parsed.set_nanosecond(nano)); parsed.set_nanosecond(nano)?;
} }
&Internal(InternalFixed { val: InternalInternal::Nanosecond9NoDot }) => { &Internal(InternalFixed { val: InternalInternal::Nanosecond9NoDot }) => {
if s.len() < 9 { return Err(TOO_SHORT); } if s.len() < 9 { return Err(TOO_SHORT); }
let nano = try_consume!(scan::nanosecond_fixed(s, 9)); let nano = try_consume!(scan::nanosecond_fixed(s, 9));
try!(parsed.set_nanosecond(nano)); parsed.set_nanosecond(nano)?;
} }
&TimezoneName => return Err(BAD_FORMAT), &TimezoneName => return Err(BAD_FORMAT),
@ -347,18 +347,18 @@ pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResul
&TimezoneOffsetColon | &TimezoneOffset => { &TimezoneOffsetColon | &TimezoneOffset => {
let offset = try_consume!(scan::timezone_offset(s.trim_left(), let offset = try_consume!(scan::timezone_offset(s.trim_left(),
scan::colon_or_space)); scan::colon_or_space));
try!(parsed.set_offset(i64::from(offset))); parsed.set_offset(i64::from(offset))?;
} }
&TimezoneOffsetColonZ | &TimezoneOffsetZ => { &TimezoneOffsetColonZ | &TimezoneOffsetZ => {
let offset = try_consume!(scan::timezone_offset_zulu(s.trim_left(), let offset = try_consume!(scan::timezone_offset_zulu(s.trim_left(),
scan::colon_or_space)); scan::colon_or_space));
try!(parsed.set_offset(i64::from(offset))); parsed.set_offset(i64::from(offset))?;
} }
&Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => { &Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => {
let offset = try_consume!(scan::timezone_offset_permissive( let offset = try_consume!(scan::timezone_offset_permissive(
s.trim_left(), scan::colon_or_space)); s.trim_left(), scan::colon_or_space));
try!(parsed.set_offset(i64::from(offset))); parsed.set_offset(i64::from(offset))?;
} }
&RFC2822 => try_consume!(parse_rfc2822(parsed, s)), &RFC2822 => try_consume!(parse_rfc2822(parsed, s)),
@ -389,7 +389,7 @@ fn test_parse() {
// workaround for Rust issue #22255 // workaround for Rust issue #22255
fn parse_all(s: &str, items: &[Item]) -> ParseResult<Parsed> { fn parse_all(s: &str, items: &[Item]) -> ParseResult<Parsed> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, items.iter())); parse(&mut parsed, s, items.iter())?;
Ok(parsed) Ok(parsed)
} }
@ -700,7 +700,7 @@ fn test_rfc2822() {
fn rfc2822_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> { fn rfc2822_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC2822)].iter())); parse(&mut parsed, date, [Item::Fixed(Fixed::RFC2822)].iter())?;
parsed.to_datetime() parsed.to_datetime()
} }
@ -781,7 +781,7 @@ fn test_rfc3339() {
fn rfc3339_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> { fn rfc3339_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC3339)].iter())); parse(&mut parsed, date, [Item::Fixed(Fixed::RFC3339)].iter())?;
parsed.to_datetime() parsed.to_datetime()
} }

View File

@ -144,65 +144,65 @@ impl Parsed {
/// Tries to set the [`year`](#structfield.year) field from given value. /// Tries to set the [`year`](#structfield.year) field from given value.
#[inline] #[inline]
pub fn set_year(&mut self, value: i64) -> ParseResult<()> { pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.year, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.year, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value. /// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value.
#[inline] #[inline]
pub fn set_year_div_100(&mut self, value: i64) -> ParseResult<()> { pub fn set_year_div_100(&mut self, value: i64) -> ParseResult<()> {
if value < 0 { return Err(OUT_OF_RANGE); } if value < 0 { return Err(OUT_OF_RANGE); }
set_if_consistent(&mut self.year_div_100, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.year_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value. /// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value.
#[inline] #[inline]
pub fn set_year_mod_100(&mut self, value: i64) -> ParseResult<()> { pub fn set_year_mod_100(&mut self, value: i64) -> ParseResult<()> {
if value < 0 { return Err(OUT_OF_RANGE); } if value < 0 { return Err(OUT_OF_RANGE); }
set_if_consistent(&mut self.year_mod_100, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.year_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`isoyear`](#structfield.isoyear) field from given value. /// Tries to set the [`isoyear`](#structfield.isoyear) field from given value.
#[inline] #[inline]
pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> { pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.isoyear, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.isoyear, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value. /// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value.
#[inline] #[inline]
pub fn set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()> { pub fn set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()> {
if value < 0 { return Err(OUT_OF_RANGE); } if value < 0 { return Err(OUT_OF_RANGE); }
set_if_consistent(&mut self.isoyear_div_100, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.isoyear_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value. /// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value.
#[inline] #[inline]
pub fn set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()> { pub fn set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()> {
if value < 0 { return Err(OUT_OF_RANGE); } if value < 0 { return Err(OUT_OF_RANGE); }
set_if_consistent(&mut self.isoyear_mod_100, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.isoyear_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`month`](#structfield.month) field from given value. /// Tries to set the [`month`](#structfield.month) field from given value.
#[inline] #[inline]
pub fn set_month(&mut self, value: i64) -> ParseResult<()> { pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.month, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.month, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value. /// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value.
#[inline] #[inline]
pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> { pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.week_from_sun, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.week_from_sun, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value. /// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value.
#[inline] #[inline]
pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> { pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.week_from_mon, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.week_from_mon, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`isoweek`](#structfield.isoweek) field from given value. /// Tries to set the [`isoweek`](#structfield.isoweek) field from given value.
#[inline] #[inline]
pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> { pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.isoweek, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.isoweek, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`weekday`](#structfield.weekday) field from given value. /// Tries to set the [`weekday`](#structfield.weekday) field from given value.
@ -214,13 +214,13 @@ impl Parsed {
/// Tries to set the [`ordinal`](#structfield.ordinal) field from given value. /// Tries to set the [`ordinal`](#structfield.ordinal) field from given value.
#[inline] #[inline]
pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> { pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.ordinal, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.ordinal, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`day`](#structfield.day) field from given value. /// Tries to set the [`day`](#structfield.day) field from given value.
#[inline] #[inline]
pub fn set_day(&mut self, value: i64) -> ParseResult<()> { pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.day, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.day, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value. /// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value.
@ -242,28 +242,28 @@ impl Parsed {
/// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value. /// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value.
#[inline] #[inline]
pub fn set_hour(&mut self, value: i64) -> ParseResult<()> { pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
let v = try!(value.to_u32().ok_or(OUT_OF_RANGE)); let v = value.to_u32().ok_or(OUT_OF_RANGE)?;
try!(set_if_consistent(&mut self.hour_div_12, v / 12)); set_if_consistent(&mut self.hour_div_12, v / 12)?;
try!(set_if_consistent(&mut self.hour_mod_12, v % 12)); set_if_consistent(&mut self.hour_mod_12, v % 12)?;
Ok(()) Ok(())
} }
/// Tries to set the [`minute`](#structfield.minute) field from given value. /// Tries to set the [`minute`](#structfield.minute) field from given value.
#[inline] #[inline]
pub fn set_minute(&mut self, value: i64) -> ParseResult<()> { pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.minute, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.minute, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`second`](#structfield.second) field from given value. /// Tries to set the [`second`](#structfield.second) field from given value.
#[inline] #[inline]
pub fn set_second(&mut self, value: i64) -> ParseResult<()> { pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.second, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.second, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value. /// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
#[inline] #[inline]
pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> { pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.nanosecond, try!(value.to_u32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.nanosecond, value.to_u32().ok_or(OUT_OF_RANGE)?)
} }
/// Tries to set the [`timestamp`](#structfield.timestamp) field from given value. /// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
@ -275,7 +275,7 @@ impl Parsed {
/// Tries to set the [`offset`](#structfield.offset) field from given value. /// Tries to set the [`offset`](#structfield.offset) field from given value.
#[inline] #[inline]
pub fn set_offset(&mut self, value: i64) -> ParseResult<()> { pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.offset, try!(value.to_i32().ok_or(OUT_OF_RANGE))) set_if_consistent(&mut self.offset, value.to_i32().ok_or(OUT_OF_RANGE)?)
} }
/// Returns a parsed naive date out of given fields. /// Returns a parsed naive date out of given fields.
@ -316,7 +316,7 @@ impl Parsed {
(None, Some(q), Some(r @ 0...99)) => { (None, Some(q), Some(r @ 0...99)) => {
if q < 0 { return Err(OUT_OF_RANGE); } if q < 0 { return Err(OUT_OF_RANGE); }
let y = q.checked_mul(100).and_then(|v| v.checked_add(r)); let y = q.checked_mul(100).and_then(|v| v.checked_add(r));
Ok(Some(try!(y.ok_or(OUT_OF_RANGE)))) Ok(Some(y.ok_or(OUT_OF_RANGE)?))
}, },
// we only have modulo. try to interpret a modulo as a conventional two-digit year. // we only have modulo. try to interpret a modulo as a conventional two-digit year.
@ -330,9 +330,9 @@ impl Parsed {
} }
let given_year = let given_year =
try!(resolve_year(self.year, self.year_div_100, self.year_mod_100)); resolve_year(self.year, self.year_div_100, self.year_mod_100)?;
let given_isoyear = let given_isoyear =
try!(resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100)); resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100)?;
// verify the normal year-month-day date. // verify the normal year-month-day date.
let verify_ymd = |date: NaiveDate| { let verify_ymd = |date: NaiveDate| {
@ -388,20 +388,20 @@ impl Parsed {
let (verified, parsed_date) = match (given_year, given_isoyear, self) { let (verified, parsed_date) = match (given_year, given_isoyear, self) {
(Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => { (Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => {
// year, month, day // year, month, day
let date = try!(NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE)); let date = NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE)?;
(verify_isoweekdate(date) && verify_ordinal(date), date) (verify_isoweekdate(date) && verify_ordinal(date), date)
}, },
(Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => { (Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
// year, day of the year // year, day of the year
let date = try!(NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE)); let date = NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE)?;
(verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date) (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
}, },
(Some(year), _, &Parsed { week_from_sun: Some(week_from_sun), (Some(year), _, &Parsed { week_from_sun: Some(week_from_sun),
weekday: Some(weekday), .. }) => { weekday: Some(weekday), .. }) => {
// year, week (starting at 1st Sunday), day of the week // year, week (starting at 1st Sunday), day of the week
let newyear = try!(NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)); let newyear = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
let firstweek = match newyear.weekday() { let firstweek = match newyear.weekday() {
Weekday::Sun => 0, Weekday::Sun => 0,
Weekday::Mon => 6, Weekday::Mon => 6,
@ -416,8 +416,8 @@ impl Parsed {
if week_from_sun > 53 { return Err(OUT_OF_RANGE); } // can it overflow? if week_from_sun > 53 { return Err(OUT_OF_RANGE); } // can it overflow?
let ndays = firstweek + (week_from_sun as i32 - 1) * 7 + let ndays = firstweek + (week_from_sun as i32 - 1) * 7 +
weekday.num_days_from_sunday() as i32; weekday.num_days_from_sunday() as i32;
let date = try!(newyear.checked_add_signed(OldDuration::days(i64::from(ndays))) let date = newyear.checked_add_signed(OldDuration::days(i64::from(ndays)))
.ok_or(OUT_OF_RANGE)); .ok_or(OUT_OF_RANGE)?;
if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error
(verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date) (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
@ -426,7 +426,7 @@ impl Parsed {
(Some(year), _, &Parsed { week_from_mon: Some(week_from_mon), (Some(year), _, &Parsed { week_from_mon: Some(week_from_mon),
weekday: Some(weekday), .. }) => { weekday: Some(weekday), .. }) => {
// year, week (starting at 1st Monday), day of the week // year, week (starting at 1st Monday), day of the week
let newyear = try!(NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)); let newyear = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
let firstweek = match newyear.weekday() { let firstweek = match newyear.weekday() {
Weekday::Sun => 1, Weekday::Sun => 1,
Weekday::Mon => 0, Weekday::Mon => 0,
@ -441,8 +441,8 @@ impl Parsed {
if week_from_mon > 53 { return Err(OUT_OF_RANGE); } // can it overflow? if week_from_mon > 53 { return Err(OUT_OF_RANGE); } // can it overflow?
let ndays = firstweek + (week_from_mon as i32 - 1) * 7 + let ndays = firstweek + (week_from_mon as i32 - 1) * 7 +
weekday.num_days_from_monday() as i32; weekday.num_days_from_monday() as i32;
let date = try!(newyear.checked_add_signed(OldDuration::days(i64::from(ndays))) let date = newyear.checked_add_signed(OldDuration::days(i64::from(ndays)))
.ok_or(OUT_OF_RANGE)); .ok_or(OUT_OF_RANGE)?;
if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error
(verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date) (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
@ -451,7 +451,7 @@ impl Parsed {
(_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => { (_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => {
// ISO year, week, day of the week // ISO year, week, day of the week
let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday); let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday);
let date = try!(date.ok_or(OUT_OF_RANGE)); let date = date.ok_or(OUT_OF_RANGE)?;
(verify_ymd(date) && verify_ordinal(date), date) (verify_ymd(date) && verify_ordinal(date), date)
}, },
@ -547,9 +547,9 @@ impl Parsed {
} }
// reconstruct date and time fields from timestamp // reconstruct date and time fields from timestamp
let ts = try!(timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE)); let ts = timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE)?;
let datetime = NaiveDateTime::from_timestamp_opt(ts, 0); let datetime = NaiveDateTime::from_timestamp_opt(ts, 0);
let mut datetime = try!(datetime.ok_or(OUT_OF_RANGE)); let mut datetime = datetime.ok_or(OUT_OF_RANGE)?;
// fill year, ordinal, hour, minute and second fields from timestamp. // fill year, ordinal, hour, minute and second fields from timestamp.
// if existing fields are consistent, this will allow the full date/time reconstruction. // if existing fields are consistent, this will allow the full date/time reconstruction.
@ -566,21 +566,21 @@ impl Parsed {
} }
// ...and we have the correct candidates for other fields. // ...and we have the correct candidates for other fields.
} else { } else {
try!(parsed.set_second(i64::from(datetime.second()))); parsed.set_second(i64::from(datetime.second()))?;
} }
try!(parsed.set_year (i64::from(datetime.year()))); parsed.set_year (i64::from(datetime.year()))?;
try!(parsed.set_ordinal(i64::from(datetime.ordinal()))); // more efficient than ymd parsed.set_ordinal(i64::from(datetime.ordinal()))?; // more efficient than ymd
try!(parsed.set_hour (i64::from(datetime.hour()))); parsed.set_hour (i64::from(datetime.hour()))?;
try!(parsed.set_minute (i64::from(datetime.minute()))); parsed.set_minute (i64::from(datetime.minute()))?;
// validate other fields (e.g. week) and return // validate other fields (e.g. week) and return
let date = try!(parsed.to_naive_date()); let date = parsed.to_naive_date()?;
let time = try!(parsed.to_naive_time()); let time = parsed.to_naive_time()?;
Ok(date.and_time(time)) Ok(date.and_time(time))
} else { } else {
// reproduce the previous error(s) // reproduce the previous error(s)
try!(date); date?;
try!(time); time?;
unreachable!() unreachable!()
} }
} }
@ -597,9 +597,9 @@ impl Parsed {
/// plus a time zone offset. /// plus a time zone offset.
/// Either way those fields have to be consistent to each other. /// Either way those fields have to be consistent to each other.
pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> { pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> {
let offset = try!(self.offset.ok_or(NOT_ENOUGH)); let offset = self.offset.ok_or(NOT_ENOUGH)?;
let datetime = try!(self.to_naive_datetime_with_offset(offset)); let datetime = self.to_naive_datetime_with_offset(offset)?;
let offset = try!(FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)); let offset = FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)?;
match offset.from_local_datetime(&datetime) { match offset.from_local_datetime(&datetime) {
LocalResult::None => Err(IMPOSSIBLE), LocalResult::None => Err(IMPOSSIBLE),
LocalResult::Single(t) => Ok(t), LocalResult::Single(t) => Ok(t),
@ -624,7 +624,7 @@ impl Parsed {
// an empty `nanosecond` is always equal to zero, so missing nanosecond is fine. // an empty `nanosecond` is always equal to zero, so missing nanosecond is fine.
let nanosecond = self.nanosecond.unwrap_or(0); let nanosecond = self.nanosecond.unwrap_or(0);
let dt = NaiveDateTime::from_timestamp_opt(timestamp, nanosecond); let dt = NaiveDateTime::from_timestamp_opt(timestamp, nanosecond);
let dt = try!(dt.ok_or(OUT_OF_RANGE)); let dt = dt.ok_or(OUT_OF_RANGE)?;
guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc(); guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc();
} }
@ -639,7 +639,7 @@ impl Parsed {
// `guessed_offset` should be correct when `self.timestamp` is given. // `guessed_offset` should be correct when `self.timestamp` is given.
// it will be 0 otherwise, but this is fine as the algorithm ignores offset for that case. // it will be 0 otherwise, but this is fine as the algorithm ignores offset for that case.
let datetime = try!(self.to_naive_datetime_with_offset(guessed_offset)); let datetime = self.to_naive_datetime_with_offset(guessed_offset)?;
match tz.from_local_datetime(&datetime) { match tz.from_local_datetime(&datetime) {
LocalResult::None => Err(IMPOSSIBLE), LocalResult::None => Err(IMPOSSIBLE),
LocalResult::Single(t) => if check_offset(&t) {Ok(t)} else {Err(IMPOSSIBLE)}, LocalResult::Single(t) => if check_offset(&t) {Ok(t)} else {Err(IMPOSSIBLE)},

View File

@ -66,13 +66,13 @@ pub fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> {
pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> { pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> {
// record the number of digits consumed for later scaling. // record the number of digits consumed for later scaling.
let origlen = s.len(); let origlen = s.len();
let (s, v) = try!(number(s, 1, 9)); let (s, v) = number(s, 1, 9)?;
let consumed = origlen - s.len(); let consumed = origlen - s.len();
// scale the number accordingly. // scale the number accordingly.
static SCALE: [i64; 10] = [0, 100_000_000, 10_000_000, 1_000_000, 100_000, 10_000, static SCALE: [i64; 10] = [0, 100_000_000, 10_000_000, 1_000_000, 100_000, 10_000,
1_000, 100, 10, 1]; 1_000, 100, 10, 1];
let v = try!(v.checked_mul(SCALE[consumed]).ok_or(OUT_OF_RANGE)); let v = v.checked_mul(SCALE[consumed]).ok_or(OUT_OF_RANGE)?;
// if there are more than 9 digits, skip next digits. // if there are more than 9 digits, skip next digits.
let s = s.trim_left_matches(|c: char| '0' <= c && c <= '9'); let s = s.trim_left_matches(|c: char| '0' <= c && c <= '9');
@ -84,12 +84,12 @@ pub fn nanosecond(s: &str) -> ParseResult<(&str, i64)> {
/// Returns the number of whole nanoseconds (0--999,999,999). /// Returns the number of whole nanoseconds (0--999,999,999).
pub fn nanosecond_fixed(s: &str, digits: usize) -> ParseResult<(&str, i64)> { pub fn nanosecond_fixed(s: &str, digits: usize) -> ParseResult<(&str, i64)> {
// record the number of digits consumed for later scaling. // record the number of digits consumed for later scaling.
let (s, v) = try!(number(s, digits, digits)); let (s, v) = number(s, digits, digits)?;
// scale the number accordingly. // scale the number accordingly.
static SCALE: [i64; 10] = [0, 100_000_000, 10_000_000, 1_000_000, 100_000, 10_000, static SCALE: [i64; 10] = [0, 100_000_000, 10_000_000, 1_000_000, 100_000, 10_000,
1_000, 100, 10, 1]; 1_000, 100, 10, 1];
let v = try!(v.checked_mul(SCALE[digits]).ok_or(OUT_OF_RANGE)); let v = v.checked_mul(SCALE[digits]).ok_or(OUT_OF_RANGE)?;
Ok((s, v)) Ok((s, v))
} }
@ -140,7 +140,7 @@ pub fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> {
static LONG_MONTH_SUFFIXES: [&'static str; 12] = static LONG_MONTH_SUFFIXES: [&'static str; 12] =
["uary", "ruary", "ch", "il", "", "e", "y", "ust", "tember", "ober", "ember", "ember"]; ["uary", "ruary", "ch", "il", "", "e", "y", "ust", "tember", "ober", "ember", "ember"];
let (mut s, month0) = try!(short_month0(s)); let (mut s, month0) = short_month0(s)?;
// tries to consume the suffix if possible // tries to consume the suffix if possible
let suffix = LONG_MONTH_SUFFIXES[month0 as usize]; let suffix = LONG_MONTH_SUFFIXES[month0 as usize];
@ -158,7 +158,7 @@ pub fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> {
static LONG_WEEKDAY_SUFFIXES: [&'static str; 7] = static LONG_WEEKDAY_SUFFIXES: [&'static str; 7] =
["day", "sday", "nesday", "rsday", "day", "urday", "day"]; ["day", "sday", "nesday", "rsday", "day", "urday", "day"];
let (mut s, weekday) = try!(short_weekday(s)); let (mut s, weekday) = short_weekday(s)?;
// tries to consume the suffix if possible // tries to consume the suffix if possible
let suffix = LONG_WEEKDAY_SUFFIXES[weekday.num_days_from_monday() as usize]; let suffix = LONG_WEEKDAY_SUFFIXES[weekday.num_days_from_monday() as usize];
@ -225,14 +225,14 @@ fn timezone_offset_internal<F>(mut s: &str, mut consume_colon: F, allow_missing_
s = &s[1..]; s = &s[1..];
// hours (00--99) // hours (00--99)
let hours = match try!(digits(s)) { let hours = match digits(s)? {
(h1 @ b'0'...b'9', h2 @ b'0'...b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')), (h1 @ b'0'...b'9', h2 @ b'0'...b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')),
_ => return Err(INVALID), _ => return Err(INVALID),
}; };
s = &s[2..]; s = &s[2..];
// colons (and possibly other separators) // colons (and possibly other separators)
s = try!(consume_colon(s)); s = consume_colon(s)?;
// minutes (00--59) // minutes (00--59)
// if the next two items are digits then we have to add minutes // if the next two items are digits then we have to add minutes
@ -307,7 +307,7 @@ pub fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> {
Ok((s, None)) // recommended by RFC 2822: consume but treat it as -0000 Ok((s, None)) // recommended by RFC 2822: consume but treat it as -0000
} }
} else { } else {
let (s_, offset) = try!(timezone_offset(s, |s| Ok(s))); let (s_, offset) = timezone_offset(s, |s| Ok(s))?;
if offset == 0 && s.starts_with('-') { // -0000 is not same to +0000 if offset == 0 && s.starts_with('-') { // -0000 is not same to +0000
Ok((s_, None)) Ok((s_, None))
} else { } else {

View File

@ -386,7 +386,6 @@
#![cfg_attr(feature = "bench", feature(test))] // lib stability features as per RFC #507 #![cfg_attr(feature = "bench", feature(test))] // lib stability features as per RFC #507
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(missing_debug_implementations)] #![deny(missing_debug_implementations)]
#![allow(deprecated)]
#![cfg_attr(not(any(feature = "std", test)), no_std)] #![cfg_attr(not(any(feature = "std", test)), no_std)]

View File

@ -455,7 +455,7 @@ impl NaiveDate {
/// ~~~~ /// ~~~~
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDate> { pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDate> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_naive_date() parsed.to_naive_date()
} }
@ -1518,7 +1518,7 @@ impl str::FromStr for NaiveDate {
]; ];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_naive_date() parsed.to_naive_date()
} }
} }

View File

@ -210,7 +210,7 @@ impl NaiveDateTime {
/// ~~~~ /// ~~~~
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDateTime> { pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDateTime> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_naive_datetime_with_offset(0) // no offset adjustment parsed.to_naive_datetime_with_offset(0) // no offset adjustment
} }
@ -1489,7 +1489,7 @@ impl str::FromStr for NaiveDateTime {
]; ];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_naive_datetime_with_offset(0) parsed.to_naive_datetime_with_offset(0)
} }
} }
@ -1834,7 +1834,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(NaiveDateTimeFromNanoSecondsVisitor))) Ok(d.deserialize_i64(NaiveDateTimeFromNanoSecondsVisitor)?)
} }
struct NaiveDateTimeFromNanoSecondsVisitor; struct NaiveDateTimeFromNanoSecondsVisitor;
@ -1979,7 +1979,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(NaiveDateTimeFromMilliSecondsVisitor))) Ok(d.deserialize_i64(NaiveDateTimeFromMilliSecondsVisitor)?)
} }
struct NaiveDateTimeFromMilliSecondsVisitor; struct NaiveDateTimeFromMilliSecondsVisitor;
@ -2124,7 +2124,7 @@ pub mod serde {
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error> pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where D: de::Deserializer<'de> where D: de::Deserializer<'de>
{ {
Ok(try!(d.deserialize_i64(NaiveDateTimeFromSecondsVisitor))) Ok(d.deserialize_i64(NaiveDateTimeFromSecondsVisitor)?)
} }
struct NaiveDateTimeFromSecondsVisitor; struct NaiveDateTimeFromSecondsVisitor;

View File

@ -496,7 +496,7 @@ impl NaiveTime {
/// ~~~~ /// ~~~~
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime> { pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveTime> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_naive_time() parsed.to_naive_time()
} }
@ -1236,7 +1236,7 @@ impl fmt::Debug for NaiveTime {
(sec, self.frac) (sec, self.frac)
}; };
try!(write!(f, "{:02}:{:02}:{:02}", hour, min, sec)); write!(f, "{:02}:{:02}:{:02}", hour, min, sec)?;
if nano == 0 { if nano == 0 {
Ok(()) Ok(())
} else if nano % 1_000_000 == 0 { } else if nano % 1_000_000 == 0 {
@ -1314,7 +1314,7 @@ impl str::FromStr for NaiveTime {
]; ];
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, ITEMS.iter())); parse(&mut parsed, s, ITEMS.iter())?;
parsed.to_naive_time() parsed.to_naive_time()
} }
} }

View File

@ -415,7 +415,7 @@ pub trait TimeZone: Sized + Clone {
/// with parsed `FixedOffset`. /// with parsed `FixedOffset`.
fn datetime_from_str(&self, s: &str, fmt: &str) -> ParseResult<DateTime<Self>> { fn datetime_from_str(&self, s: &str, fmt: &str) -> ParseResult<DateTime<Self>> {
let mut parsed = Parsed::new(); let mut parsed = Parsed::new();
try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_datetime_with_timezone(self) parsed.to_datetime_with_timezone(self)
} }

View File

@ -364,20 +364,20 @@ impl fmt::Display for Duration {
let hasdate = days != 0; let hasdate = days != 0;
let hastime = (secs != 0 || abs.nanos != 0) || !hasdate; let hastime = (secs != 0 || abs.nanos != 0) || !hasdate;
try!(write!(f, "{}P", sign)); write!(f, "{}P", sign)?;
if hasdate { if hasdate {
try!(write!(f, "{}D", days)); write!(f, "{}D", days)?;
} }
if hastime { if hastime {
if abs.nanos == 0 { if abs.nanos == 0 {
try!(write!(f, "T{}S", secs)); write!(f, "T{}S", secs)?;
} else if abs.nanos % NANOS_PER_MILLI == 0 { } else if abs.nanos % NANOS_PER_MILLI == 0 {
try!(write!(f, "T{}.{:03}S", secs, abs.nanos / NANOS_PER_MILLI)); write!(f, "T{}.{:03}S", secs, abs.nanos / NANOS_PER_MILLI)?;
} else if abs.nanos % NANOS_PER_MICRO == 0 { } else if abs.nanos % NANOS_PER_MICRO == 0 {
try!(write!(f, "T{}.{:06}S", secs, abs.nanos / NANOS_PER_MICRO)); write!(f, "T{}.{:06}S", secs, abs.nanos / NANOS_PER_MICRO)?;
} else { } else {
try!(write!(f, "T{}.{:09}S", secs, abs.nanos)); write!(f, "T{}.{:09}S", secs, abs.nanos)?;
} }
} }
Ok(()) Ok(())