Merge pull request #45 from tomgco/f-parse-2

New formatters %.3f, %.6f, %.9f
This commit is contained in:
Kang Seonghoon 2015-09-05 19:18:23 +09:00
commit 37c7f78670
3 changed files with 59 additions and 2 deletions

View File

@ -125,6 +125,12 @@ pub enum Fixed {
/// May print nothing, 3, 6 or 9 digits according to the available accuracy. /// May print nothing, 3, 6 or 9 digits according to the available accuracy.
/// See also `Numeric::Nanosecond`. /// See also `Numeric::Nanosecond`.
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. /// Timezone name.
/// ///
/// It does not support parsing, its use in the parser is an immediate failure. /// 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) 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 => TimezoneName =>
off.map(|&(ref name, _)| write!(w, "{}", *name)), off.map(|&(ref name, _)| write!(w, "{}", *name)),
TimezoneOffsetColon => TimezoneOffsetColon =>

View File

@ -300,7 +300,7 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<(
s = &s[2..]; s = &s[2..];
} }
Nanosecond => { 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)); try!(parsed.set_nanosecond(nano));

View File

@ -56,6 +56,9 @@ Spec. | Example | Description
`%S` | `60` | Second number (00--60), zero-padded to 2 digits. [5] `%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` | `026490000` | The fractional seconds (in nanoseconds) since last whole second. [8]
`%.f` | `.026490` | Similar to `.%f` but left-aligned. [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`. `%R` | `00:34` | Hour-minute format. Same to `%H:%M`.
`%T` | `00:34:60` | Hour-minute-second format. Same to `%H:%M:%S`. `%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 For the purpose of Chrono, it only accounts for non-leap seconds
so it slightly differs from ISO C `strftime` behavior. 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 The default `%f` is right-aligned and always zero-padded to 9 digits
for the compatibility with glibc and others, 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 Note that they can print or read nothing if the fractional part is zero or
the next character is not `.`. 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}; use super::{Item, Numeric, Fixed, Pad};
@ -254,6 +263,18 @@ impl<'a> Iterator for StrftimeItems<'a> {
_ => Item::Error, _ => Item::Error,
}, },
'.' => match next!() { '.' => 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), 'f' => fix!(Nanosecond),
_ => Item::Error, _ => Item::Error,
}, },
@ -389,6 +410,9 @@ fn test_strftime_docs() {
assert_eq!(dt.format("%S").to_string(), "60"); assert_eq!(dt.format("%S").to_string(), "60");
assert_eq!(dt.format("%f").to_string(), "026490000"); assert_eq!(dt.format("%f").to_string(), "026490000");
assert_eq!(dt.format("%.f").to_string(), ".026490"); 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("%R").to_string(), "00:34");
assert_eq!(dt.format("%T").to_string(), "00:34:60"); assert_eq!(dt.format("%T").to_string(), "00:34:60");
assert_eq!(dt.format("%X").to_string(), "00:34:60"); assert_eq!(dt.format("%X").to_string(), "00:34:60");