From 7b316094180fcb5efb789fbf9e183d02f60c11d8 Mon Sep 17 00:00:00 2001 From: Tom Gallacher Date: Thu, 3 Sep 2015 13:40:34 +0100 Subject: [PATCH 1/3] Adding fixed precision for Nanosecond3, 6 and 9 --- src/format/mod.rs | 33 +++++++++++++++++++++++++++++++++ src/format/parse.rs | 21 +++++++++++++++++++++ src/format/strftime.rs | 15 +++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/format/mod.rs b/src/format/mod.rs index e20ecaf..939ad37 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -125,6 +125,12 @@ pub enum Fixed { /// May print nothing, 3, 6 or 9 digits according to the available accuracy. /// See also `Numeric::Nanosecond`. Nanosecond, + /// Fixed prescision at Nanosecond3 where 3 is the left aligned accuracy. + Nanosecond3, + /// Fixed prescision at Nanosecond6 where 6 is the left aligned accuracy. + Nanosecond6, + /// Fixed prescision at Nanosecond9 where 9 is the left aligned accuracy. + Nanosecond9, /// Timezone name. /// /// It does not support parsing, its use in the parser is an immediate failure. @@ -366,6 +372,33 @@ pub fn format<'a, I>(w: &mut fmt::Formatter, date: Option<&NaiveDate>, time: Opt write!(w, ".{:09}", nano) } }), + 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) + } + }), + 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) + } + }), + Nanosecond9 => + time.map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + if nano == 0 { + write!(w, ".000") + } else { + write!(w, ".{:09}", nano) + } + }), TimezoneName => off.map(|&(ref name, _)| write!(w, "{}", *name)), TimezoneOffsetColon => diff --git a/src/format/parse.rs b/src/format/parse.rs index fbdda4e..fb135dd 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -307,6 +307,27 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( } } + Nanosecond3 => { + if s.starts_with(".") { + let nano = try_consume!(scan::nanosecond(&s[1..])); + try!(parsed.set_nanosecond(nano)); + } + } + + Nanosecond6 => { + if s.starts_with(".") { + let nano = try_consume!(scan::nanosecond(&s[1..])); + try!(parsed.set_nanosecond(nano)); + } + } + + Nanosecond9 => { + if s.starts_with(".") { + let nano = try_consume!(scan::nanosecond(&s[1..])); + try!(parsed.set_nanosecond(nano)); + } + } + TimezoneName => return Err(BAD_FORMAT), TimezoneOffsetColon | TimezoneOffset => { diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 802a4cd..0efd8d6 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -254,6 +254,18 @@ impl<'a> Iterator for StrftimeItems<'a> { _ => Item::Error, }, '.' => match next!() { + '3' => match next!() { + 'f' => fix!(Nanosecond3), + _ => Item::Error, + }, + '6' => match next!() { + 'f' => fix!(Nanosecond6), + _ => Item::Error, + }, + '9' => match next!() { + 'f' => fix!(Nanosecond9), + _ => Item::Error, + }, 'f' => fix!(Nanosecond), _ => Item::Error, }, @@ -389,6 +401,9 @@ fn test_strftime_docs() { assert_eq!(dt.format("%S").to_string(), "60"); assert_eq!(dt.format("%f").to_string(), "026490000"); assert_eq!(dt.format("%.f").to_string(), ".026490"); + assert_eq!(dt.format("%.3f").to_string(), ".026"); + assert_eq!(dt.format("%.6f").to_string(), ".026490"); + assert_eq!(dt.format("%.9f").to_string(), ".026490000"); assert_eq!(dt.format("%R").to_string(), "00:34"); assert_eq!(dt.format("%T").to_string(), "00:34:60"); assert_eq!(dt.format("%X").to_string(), "00:34:60"); From b53e9d940ffc5c1ea099bf7c5fed7817f253149b Mon Sep 17 00:00:00 2001 From: Tom Gallacher Date: Thu, 3 Sep 2015 13:43:36 +0100 Subject: [PATCH 2/3] Refactoring matching --- src/format/parse.rs | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/format/parse.rs b/src/format/parse.rs index fb135dd..41ab298 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -300,28 +300,7 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( s = &s[2..]; } - Nanosecond => { - if s.starts_with(".") { - let nano = try_consume!(scan::nanosecond(&s[1..])); - try!(parsed.set_nanosecond(nano)); - } - } - - Nanosecond3 => { - if s.starts_with(".") { - let nano = try_consume!(scan::nanosecond(&s[1..])); - try!(parsed.set_nanosecond(nano)); - } - } - - Nanosecond6 => { - if s.starts_with(".") { - let nano = try_consume!(scan::nanosecond(&s[1..])); - try!(parsed.set_nanosecond(nano)); - } - } - - Nanosecond9 => { + Nanosecond | Nanosecond3 | Nanosecond6 | Nanosecond9=> { if s.starts_with(".") { let nano = try_consume!(scan::nanosecond(&s[1..])); try!(parsed.set_nanosecond(nano)); From c44de1d38874adb99cdb28c63bb17b4543148677 Mon Sep 17 00:00:00 2001 From: Tom Gallacher Date: Thu, 3 Sep 2015 13:53:18 +0100 Subject: [PATCH 3/3] Updating docs --- src/format/strftime.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 0efd8d6..c9c4728 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -56,6 +56,9 @@ Spec. | Example | Description `%S` | `60` | Second number (00--60), zero-padded to 2 digits. [5] `%f` | `026490000` | The fractional seconds (in nanoseconds) since last whole second. [8] `%.f` | `.026490` | Similar to `.%f` but left-aligned. [8] +`%.3f`| `.026` | Similar to `.%f` but left-aligned but fixed to a length of 3. [8] +`%.6f`| `.026490` | Similar to `.%f` but left-aligned but fixed to a length of 6. [8] +`%.9f`| `.026490000` | Similar to `.%f` but left-aligned but fixed to a length of 9. [8] | | `%R` | `00:34` | Hour-minute format. Same to `%H:%M`. `%T` | `00:34:60` | Hour-minute-second format. Same to `%H:%M:%S`. @@ -115,7 +118,7 @@ Notes: For the purpose of Chrono, it only accounts for non-leap seconds so it slightly differs from ISO C `strftime` behavior. -8. `%f`, `%.f`: +8. `%f`, `%.f`, `%.3f`, `%.6f`, `%.9f`: The default `%f` is right-aligned and always zero-padded to 9 digits for the compatibility with glibc and others, @@ -128,6 +131,12 @@ Notes: 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. + 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. + */ use super::{Item, Numeric, Fixed, Pad};