Skip to content

Commit

Permalink
Expose write_to for DelayedFormat
Browse files Browse the repository at this point in the history
Request for #1649
- renamed format to write-to and made it public.
- added unittests
- added benchmarks to compare and show  `Display` is slower than `write_to` in that
  specific use case.
  • Loading branch information
Steven Tang authored and djc committed Jan 23, 2025
1 parent 5f2f5a8 commit 4c42ee5
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
20 changes: 20 additions & 0 deletions bench/benches/chrono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,25 @@ fn bench_format_with_items(c: &mut Criterion) {
});
}

fn benches_delayed_format(c: &mut Criterion) {
let mut group = c.benchmark_group("delayed_format");
let dt = Local::now();
group.bench_function(BenchmarkId::new("with_display", dt), |b| {
b.iter_batched(
|| dt.format("%Y-%m-%dT%H:%M:%S%.f%:z"),
|df| black_box(df).to_string(),
criterion::BatchSize::SmallInput,
)
});
group.bench_function(BenchmarkId::new("with_string_buffer", dt), |b| {
b.iter_batched(
|| (dt.format("%Y-%m-%dT%H:%M:%S%.f%:z"), String::with_capacity(256)),
|(df, string)| black_box(df).write_to(&mut black_box(string)),
criterion::BatchSize::SmallInput,
)
});
}

fn bench_format_manual(c: &mut Criterion) {
let dt = Local::now();
c.bench_function("bench_format_manual", |b| {
Expand Down Expand Up @@ -237,6 +256,7 @@ criterion_group!(
bench_format,
bench_format_with_items,
bench_format_manual,
benches_delayed_format,
bench_naivedate_add_signed,
bench_datetime_with,
);
Expand Down
48 changes: 44 additions & 4 deletions src/format/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,19 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
DelayedFormat { date, time, off: Some(name_and_diff), items, locale }
}

fn format(&self, w: &mut impl Write) -> fmt::Result {
/// Formats `DelayedFormat` into a `core::fmt::Write` instance.
/// # Errors
/// This function returns a `core::fmt::Error` if formatting into the `core::fmt::Write` instance fails.
///
/// # Example
/// ### Writing to a String
/// ```
/// let dt = chrono::DateTime::from_timestamp(1643723400, 123456789).unwrap();
/// let df = dt.format("%Y-%m-%d %H:%M:%S%.9f");
/// let mut buffer = String::new();
/// let _ = df.write_to(&mut buffer);
/// ```
pub fn write_to(&self, w: &mut impl Write) -> fmt::Result {
for item in self.items.clone() {
match *item.borrow() {
Item::Literal(s) | Item::Space(s) => w.write_str(s),
Expand Down Expand Up @@ -321,15 +333,15 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> Display for DelayedFormat<I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
self.format(&mut result)?;
self.write_to(&mut result)?;
f.pad(&result)
}
}

/// Tries to format given arguments with given formatting items.
/// Internally used by `DelayedFormat`.
#[cfg(feature = "alloc")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt instead")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt or DelayedFormat::write_to instead")]
pub fn format<'a, I, B>(
w: &mut fmt::Formatter,
date: Option<&NaiveDate>,
Expand All @@ -353,7 +365,7 @@ where

/// Formats single formatting item
#[cfg(feature = "alloc")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt instead")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt or DelayedFormat::write_to instead")]
pub fn format_item(
w: &mut fmt::Formatter,
date: Option<&NaiveDate>,
Expand Down Expand Up @@ -611,6 +623,34 @@ mod tests {
#[cfg(feature = "alloc")]
use crate::{NaiveDate, NaiveTime, TimeZone, Timelike, Utc};

#[cfg(feature = "alloc")]
#[test]
fn test_delayed_write_to() {
let dt = crate::DateTime::from_timestamp(1643723400, 123456789).unwrap();
let df = dt.format("%Y-%m-%d %H:%M:%S%.9f");

let mut dt_str = String::new();

df.write_to(&mut dt_str).unwrap();
assert_eq!(dt_str, "2022-02-01 13:50:00.123456789");
}

#[cfg(all(feature = "std", feature = "unstable-locales", feature = "alloc"))]
#[test]
fn test_with_locale_delayed_write_to() {
use crate::format::locales::Locale;
use crate::DateTime;

let dt = DateTime::from_timestamp(1643723400, 123456789).unwrap();
let df = dt.format_localized("%A, %B %d, %Y", Locale::ja_JP);

let mut dt_str = String::new();

df.write_to(&mut dt_str).unwrap();

assert_eq!(dt_str, "火曜日, 2月 01, 2022");
}

#[test]
#[cfg(feature = "alloc")]
fn test_date_format() {
Expand Down

0 comments on commit 4c42ee5

Please sign in to comment.