From 66d585635487855b6af853d5130367da64ce89bc Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Fri, 22 Apr 2016 00:47:01 +0900 Subject: [PATCH] Fixed `%.[369]f` on the whole seconds and misleading docs. Fixes #71. --- src/format/mod.rs | 20 ++++---------------- src/format/strftime.rs | 24 ++++++++++++++++-------- src/naive/time.rs | 15 ++++++++++++++- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 939ad37..ff9162a 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -375,29 +375,17 @@ pub fn format<'a, I>(w: &mut fmt::Formatter, date: Option<&NaiveDate>, time: Opt Nanosecond3 => time.map(|t| { let nano = t.nanosecond() % 1_000_000_000; - if nano == 0 { - write!(w, ".000") - } else { - write!(w, ".{:03}", nano / 1_000_000) - } + write!(w, ".{:03}", nano / 1_000_000) }), Nanosecond6 => time.map(|t| { let nano = t.nanosecond() % 1_000_000_000; - if nano == 0 { - write!(w, ".000") - } else { - write!(w, ".{:06}", nano / 1_000) - } + write!(w, ".{:06}", nano / 1_000) }), Nanosecond9 => time.map(|t| { let nano = t.nanosecond() % 1_000_000_000; - if nano == 0 { - write!(w, ".000") - } else { - write!(w, ".{:09}", nano) - } + write!(w, ".{:09}", nano) }), TimezoneName => off.map(|&(ref name, _)| write!(w, "{}", *name)), @@ -420,7 +408,7 @@ pub fn format<'a, I>(w: &mut fmt::Formatter, date: Option<&NaiveDate>, time: Opt } else { None }, - RFC3339 => // (almost) same to `%Y-%m-%dT%H:%M:%S.%f%z` + RFC3339 => // same to `%Y-%m-%dT%H:%M:%S%.f%:z` if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { // reuse `Debug` impls which already print ISO 8601 format. // this is faster in this way. diff --git a/src/format/strftime.rs b/src/format/strftime.rs index c9c4728..a4acfdb 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -110,8 +110,13 @@ Notes: It accounts for leap seconds, so `60` is possible. 6. `%+`: - This one is close to, but not identical to, `%Y-%m-%dT%H:%M:%S%.f%z`. - The main differences are a colon in `%z`. + Same to `%Y-%m-%dT%H:%M:%S%.f%:z`, + i.e. 0, 3, 6 or 9 fractional digits for seconds and colons in the time zone offset. + + The typical `strftime` implementations have + different (and locale-dependent) formats for this specifier. + While Chrono's format for `%+` is far more stable, + it is best to avoid this specifier if you want to control the exact output. 7. `%s`: This is not padded and can be negative. @@ -123,17 +128,20 @@ Notes: The default `%f` is right-aligned and always zero-padded to 9 digits for the compatibility with glibc and others, so it always counts the number of nanoseconds since the last whole second. - E.g. 7ms after the last second will print `007000000`, and parsing `7000000` will yield the same. + E.g. 7ms after the last second will print `007000000`, + and parsing `7000000` will yield the same. The variant `%.f` is left-aligned and print 0, 3, 6 or 9 fractional digits - according to the precision. E.g. 70ms after the last second under `%.f` will print `.070` - (note: not `.07`), and parsing `.07`, `.070000` etc. will yield the same. + according to the precision. + E.g. 70ms after the last second under `%.f` will print `.070` (note: not `.07`), + and parsing `.07`, `.070000` etc. will yield the same. Note that they can print or read nothing if the fractional part is zero or the next character is not `.`. - The variant `%.3f`, `%.3f` and `%.3f` are left-aligned and print 3, 6 or 9 fractional digits - according to the number preceding `f`. E.g. 70ms after the last second under `%.3f` will print `.070` - (note: not `.07`), and parsing `.07`, `.070000` etc. will yield the same. + The variant `%.3f`, `%.6f` and `%.9f` are left-aligned and print 3, 6 or 9 fractional digits + according to the number preceding `f`. + E.g. 70ms after the last second under `%.3f` will print `.070` (note: not `.07`), + and parsing `.07`, `.070000` etc. will yield the same. Note that they can read nothing if the fractional part is zero or the next character is not `.` however will print with the specified length. diff --git a/src/naive/time.rs b/src/naive/time.rs index e4209c7..6537c55 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -787,12 +787,25 @@ mod tests { let t = NaiveTime::from_hms_nano(3, 5, 7, 98765432); assert_eq!(t.format("%H,%k,%I,%l,%P,%p").to_string(), "03, 3,03, 3,am,AM"); assert_eq!(t.format("%M").to_string(), "05"); - assert_eq!(t.format("%S,%f").to_string(), "07,098765432"); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,098765432,.098765432"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".098,.098765,.098765432"); assert_eq!(t.format("%R").to_string(), "03:05"); assert_eq!(t.format("%T,%X").to_string(), "03:05:07,03:05:07"); assert_eq!(t.format("%r").to_string(), "03:05:07 AM"); assert_eq!(t.format("%t%n%%%n%t").to_string(), "\t\n%\n\t"); + let t = NaiveTime::from_hms_micro(3, 5, 7, 432100); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,432100000,.432100"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".432,.432100,.432100000"); + + let t = NaiveTime::from_hms_milli(3, 5, 7, 210); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,210000000,.210"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".210,.210000,.210000000"); + + let t = NaiveTime::from_hms(3, 5, 7); + assert_eq!(t.format("%S,%f,%.f").to_string(), "07,000000000,"); + assert_eq!(t.format("%.3f,%.6f,%.9f").to_string(), ".000,.000000,.000000000"); + // corner cases assert_eq!(NaiveTime::from_hms(13, 57, 9).format("%r").to_string(), "01:57:09 PM"); assert_eq!(NaiveTime::from_hms_milli(23, 59, 59, 1_000).format("%X").to_string(),