Accept Borrow<Item> as items
The parse::parse and format::format functions accepted Iterator of owned Items. While it is sometimes convenient to pass in the owned values, neither of the functions really need to own them, so references would be enough. The Borrow trait allows us to pass in Iterator over values, references, boxes, etc. According to RFC 1105 this is a minor change, because it shouldn't break any existing code. And chrono is in pre-1.0 version anyway. This allows us to remove multiple cloned() calls which speeds up parsing and formating: name control ns/iter remove-cloned ns/iter diff ns/iter diff % speedup datetime::tests::bench_datetime_from_str 712 582 -130 -18.26% x 1.22 datetime::tests::bench_datetime_parse_from_rfc2822 252 244 -8 -3.17% x 1.03 datetime::tests::bench_datetime_parse_from_rfc3339 242 239 -3 -1.24% x 1.01
This commit is contained in:
parent
53ef941c3a
commit
05acc869b9
|
@ -8,6 +8,14 @@ Chrono obeys the principle of [Semantic Versioning](http://semver.org/).
|
|||
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.
|
||||
|
||||
## next
|
||||
|
||||
### Features
|
||||
|
||||
* Functions that were accepting `Iterator` of `Item`s (for example
|
||||
`format_with_items`) now accept `Iterator` of `Borrow<Item>`, so one can
|
||||
use values or references.
|
||||
|
||||
## 0.4.9
|
||||
|
||||
### Fixes
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//! ISO 8601 calendar date with time zone.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::{fmt, hash};
|
||||
use core::cmp::Ordering;
|
||||
use core::ops::{Add, Sub};
|
||||
|
@ -258,8 +259,8 @@ impl<Tz: TimeZone> Date<Tz> where Tz::Offset: fmt::Display {
|
|||
/// Formats the date with the specified formatting items.
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
#[inline]
|
||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=Item<'a>> + Clone {
|
||||
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>> {
|
||||
DelayedFormat::new_with_offset(Some(self.naive_local()), None, &self.offset, items)
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ use format::{Item, Numeric, Pad, Fixed};
|
|||
use format::{parse, Parsed, ParseError, ParseResult, StrftimeItems};
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
use format::DelayedFormat;
|
||||
use core::borrow::Borrow;
|
||||
|
||||
/// Specific formatting options for seconds. This may be extended in the
|
||||
/// future, so exhaustive matching in external code is not recommended.
|
||||
|
@ -326,7 +327,7 @@ impl DateTime<FixedOffset> {
|
|||
pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
|
||||
|
@ -338,7 +339,7 @@ impl DateTime<FixedOffset> {
|
|||
pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
|
||||
|
@ -374,14 +375,14 @@ impl<Tz: TimeZone> DateTime<Tz> where Tz::Offset: fmt::Display {
|
|||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
pub fn to_rfc2822(&self) -> String {
|
||||
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
|
||||
self.format_with_items(ITEMS.iter().cloned()).to_string()
|
||||
self.format_with_items(ITEMS.iter()).to_string()
|
||||
}
|
||||
|
||||
/// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
pub fn to_rfc3339(&self) -> String {
|
||||
const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
|
||||
self.format_with_items(ITEMS.iter().cloned()).to_string()
|
||||
self.format_with_items(ITEMS.iter()).to_string()
|
||||
}
|
||||
|
||||
/// Return an RFC 3339 and ISO 8601 date and time string with subseconds
|
||||
|
@ -450,11 +451,11 @@ impl<Tz: TimeZone> DateTime<Tz> where Tz::Offset: fmt::Display {
|
|||
match ssitem {
|
||||
None =>
|
||||
self.format_with_items(
|
||||
PREFIX.iter().chain([tzitem].iter()).cloned()
|
||||
PREFIX.iter().chain([tzitem].iter())
|
||||
).to_string(),
|
||||
Some(s) =>
|
||||
self.format_with_items(
|
||||
PREFIX.iter().chain([s, tzitem].iter()).cloned()
|
||||
PREFIX.iter().chain([s, tzitem].iter())
|
||||
).to_string(),
|
||||
}
|
||||
}
|
||||
|
@ -462,8 +463,8 @@ impl<Tz: TimeZone> DateTime<Tz> where Tz::Offset: fmt::Display {
|
|||
/// Formats the combined date and time with the specified formatting items.
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
#[inline]
|
||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=Item<'a>> + Clone {
|
||||
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>> {
|
||||
let local = self.naive_local();
|
||||
DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items)
|
||||
}
|
||||
|
@ -638,7 +639,7 @@ impl str::FromStr for DateTime<FixedOffset> {
|
|||
];
|
||||
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#![allow(ellipsis_inclusive_range_patterns)]
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::fmt;
|
||||
use core::str::FromStr;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
|
@ -356,14 +357,14 @@ const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat);
|
|||
/// Tries to format given arguments with given formatting items.
|
||||
/// Internally used by `DelayedFormat`.
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
pub fn format<'a, I>(
|
||||
pub fn format<'a, I, B>(
|
||||
w: &mut fmt::Formatter,
|
||||
date: Option<&NaiveDate>,
|
||||
time: Option<&NaiveTime>,
|
||||
off: Option<&(String, FixedOffset)>,
|
||||
items: I,
|
||||
) -> fmt::Result
|
||||
where I: Iterator<Item=Item<'a>>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>>
|
||||
{
|
||||
// full and abbreviated month and weekday names
|
||||
static SHORT_MONTHS: [&'static str; 12] =
|
||||
|
@ -380,7 +381,7 @@ pub fn format<'a, I>(
|
|||
let mut result = String::new();
|
||||
|
||||
for item in items {
|
||||
match item {
|
||||
match item.borrow() {
|
||||
Item::Literal(s) | Item::Space(s) => result.push_str(s),
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
Item::OwnedLiteral(ref s) | Item::OwnedSpace(ref s) => result.push_str(s),
|
||||
|
@ -433,7 +434,7 @@ pub fn format<'a, I>(
|
|||
|
||||
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
|
||||
match pad {
|
||||
Pad::None => write!(result, "{:+}", v),
|
||||
|
@ -633,7 +634,7 @@ pub struct DelayedFormat<I> {
|
|||
}
|
||||
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
impl<'a, I: Iterator<Item=Item<'a>> + Clone> DelayedFormat<I> {
|
||||
impl<'a, I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
|
||||
/// Makes a new `DelayedFormat` value out of local date and time.
|
||||
pub fn new(date: Option<NaiveDate>, time: Option<NaiveTime>, items: I) -> DelayedFormat<I> {
|
||||
DelayedFormat { date: date, time: time, off: None, items: items }
|
||||
|
@ -649,7 +650,7 @@ impl<'a, I: Iterator<Item=Item<'a>> + Clone> DelayedFormat<I> {
|
|||
}
|
||||
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
impl<'a, I: Iterator<Item=Item<'a>> + Clone> fmt::Display for DelayedFormat<I> {
|
||||
impl<'a, I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>>> fmt::Display for DelayedFormat<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone())
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::usize;
|
||||
|
||||
use Weekday;
|
||||
|
@ -204,14 +205,14 @@ fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st
|
|||
/// so one can prepend any number of whitespace then any number of zeroes before numbers.
|
||||
///
|
||||
/// - (Still) obeying the intrinsic parsing width. This allows, for example, parsing `HHMMSS`.
|
||||
pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<()>
|
||||
where I: Iterator<Item=Item<'a>> {
|
||||
pub fn parse<'a, I, B>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<()>
|
||||
where I: Iterator<Item=B>, B: Borrow<Item<'a>> {
|
||||
macro_rules! try_consume {
|
||||
($e:expr) => ({ let (s_, v) = try!($e); s = s_; v })
|
||||
}
|
||||
|
||||
for item in items {
|
||||
match item {
|
||||
match item.borrow() {
|
||||
Item::Literal(prefix) => {
|
||||
if s.len() < prefix.len() { return Err(TOO_SHORT); }
|
||||
if !s.starts_with(prefix) { return Err(INVALID); }
|
||||
|
@ -388,7 +389,7 @@ fn test_parse() {
|
|||
// workaround for Rust issue #22255
|
||||
fn parse_all(s: &str, items: &[Item]) -> ParseResult<Parsed> {
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, items.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, items.iter()));
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
|
@ -699,12 +700,12 @@ fn test_rfc2822() {
|
|||
|
||||
fn rfc2822_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC2822)].iter().cloned()));
|
||||
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC2822)].iter()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
|
||||
fn fmt_rfc2822_datetime(dt: DateTime<FixedOffset>) -> String {
|
||||
dt.format_with_items([Item::Fixed(Fixed::RFC2822)].iter().cloned()).to_string()
|
||||
dt.format_with_items([Item::Fixed(Fixed::RFC2822)].iter()).to_string()
|
||||
}
|
||||
|
||||
// Test against test data above
|
||||
|
@ -780,12 +781,12 @@ fn test_rfc3339() {
|
|||
|
||||
fn rfc3339_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC3339)].iter().cloned()));
|
||||
try!(parse(&mut parsed, date, [Item::Fixed(Fixed::RFC3339)].iter()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
|
||||
fn fmt_rfc3339_datetime(dt: DateTime<FixedOffset>) -> String {
|
||||
dt.format_with_items([Item::Fixed(Fixed::RFC3339)].iter().cloned()).to_string()
|
||||
dt.format_with_items([Item::Fixed(Fixed::RFC3339)].iter()).to_string()
|
||||
}
|
||||
|
||||
// Test against test data above
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//! ISO 8601 calendar date without timezone.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::{str, fmt};
|
||||
use core::ops::{Add, Sub, AddAssign, SubAssign};
|
||||
use num_traits::ToPrimitive;
|
||||
|
@ -920,8 +921,8 @@ impl NaiveDate {
|
|||
/// ~~~~
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
#[inline]
|
||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=Item<'a>> + Clone {
|
||||
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>> {
|
||||
DelayedFormat::new(Some(*self), None, items)
|
||||
}
|
||||
|
||||
|
@ -1516,7 +1517,7 @@ impl str::FromStr for NaiveDate {
|
|||
];
|
||||
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_naive_date()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//! ISO 8601 date and time without timezone.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::{str, fmt, hash};
|
||||
use core::ops::{Add, Sub, AddAssign, SubAssign};
|
||||
use num_traits::ToPrimitive;
|
||||
|
@ -649,8 +650,8 @@ impl NaiveDateTime {
|
|||
/// ~~~~
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
#[inline]
|
||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=Item<'a>> + Clone {
|
||||
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>> {
|
||||
DelayedFormat::new(Some(self.date), Some(self.time), items)
|
||||
}
|
||||
|
||||
|
@ -1487,7 +1488,7 @@ impl str::FromStr for NaiveDateTime {
|
|||
];
|
||||
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_naive_datetime_with_offset(0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//! ISO 8601 time without timezone.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::{str, fmt, hash};
|
||||
use core::ops::{Add, Sub, AddAssign, SubAssign};
|
||||
use oldtime::Duration as OldDuration;
|
||||
|
@ -727,8 +728,8 @@ impl NaiveTime {
|
|||
/// ~~~~
|
||||
#[cfg(any(feature = "alloc", feature = "std", test))]
|
||||
#[inline]
|
||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=Item<'a>> + Clone {
|
||||
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
|
||||
where I: Iterator<Item=B> + Clone, B: Borrow<Item<'a>> {
|
||||
DelayedFormat::new(None, Some(*self), items)
|
||||
}
|
||||
|
||||
|
@ -1312,7 +1313,7 @@ impl str::FromStr for NaiveTime {
|
|||
];
|
||||
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
try!(parse(&mut parsed, s, ITEMS.iter()));
|
||||
parsed.to_naive_time()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue