Merge pull request #205 from dekellum/rfc3339pz
Add DateTime to_rfc3339p(z) methods, tests
This commit is contained in:
commit
ff962d452c
118
src/datetime.rs
118
src/datetime.rs
|
@ -16,6 +16,31 @@ use Date;
|
||||||
use format::{Item, Numeric, Pad, Fixed};
|
use format::{Item, Numeric, Pad, Fixed};
|
||||||
use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
|
use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
|
||||||
|
|
||||||
|
/// Specific formatting options for seconds. This may be extended in the
|
||||||
|
/// future, so exhaustive matching in external code is not recommended.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum SecondsFormat {
|
||||||
|
/// Format whole seconds only, with no decimal point nor subseconds.
|
||||||
|
Secs,
|
||||||
|
|
||||||
|
/// Use fixed 3 subsecond digits. This corresponds to
|
||||||
|
/// [Fixed::Nanosecond3](format/enum.Fixed.html#variant.Nanosecond3).
|
||||||
|
Millis,
|
||||||
|
|
||||||
|
/// Use fixed 6 subsecond digits. This corresponds to
|
||||||
|
/// [Fixed::Nanosecond6](format/enum.Fixed.html#variant.Nanosecond6).
|
||||||
|
Micros,
|
||||||
|
|
||||||
|
/// Use fixed 9 subsecond digits. This corresponds to
|
||||||
|
/// [Fixed::Nanosecond9](format/enum.Fixed.html#variant.Nanosecond9).
|
||||||
|
Nanos,
|
||||||
|
|
||||||
|
/// Automatically select one of `Secs`, `Millis`, `Micros`, or `Nanos` to
|
||||||
|
/// display all available non-zero sub-second digits. This corresponds to
|
||||||
|
/// [Fixed::Nanosecond](format/enum.Fixed.html#variant.Nanosecond).
|
||||||
|
AutoSi,
|
||||||
|
}
|
||||||
|
|
||||||
/// ISO 8601 combined date and time with time zone.
|
/// ISO 8601 combined date and time with time zone.
|
||||||
///
|
///
|
||||||
/// There are some constructors implemented here (the `from_*` methods), but
|
/// There are some constructors implemented here (the `from_*` methods), but
|
||||||
|
@ -246,6 +271,77 @@ impl<Tz: TimeZone> DateTime<Tz> where Tz::Offset: fmt::Display {
|
||||||
self.format_with_items(ITEMS.iter().cloned()).to_string()
|
self.format_with_items(ITEMS.iter().cloned()).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return an RFC 3339 and ISO 8601 date and time string with subseconds
|
||||||
|
/// formatted as per a `SecondsFormat`. If passed `use_z` true and the
|
||||||
|
/// timezone is UTC (offset 0), use 'Z', as per
|
||||||
|
/// [Fixed::TimezoneOffsetColonZ](format/enum.Fixed.html#variant.TimezoneOffsetColonZ).
|
||||||
|
/// If passed `use_z` false, use
|
||||||
|
/// [Fixed::TimezoneOffsetColon](format/enum.Fixed.html#variant.TimezoneOffsetColon).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use chrono::{DateTime, FixedOffset, SecondsFormat, TimeZone, Utc};
|
||||||
|
/// let dt = Utc.ymd(2018, 1, 26).and_hms_micro(18, 30, 9, 453_829);
|
||||||
|
/// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false),
|
||||||
|
/// "2018-01-26T18:30:09.453+00:00");
|
||||||
|
/// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, true),
|
||||||
|
/// "2018-01-26T18:30:09.453Z");
|
||||||
|
/// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||||
|
/// "2018-01-26T18:30:09Z");
|
||||||
|
///
|
||||||
|
/// let pst = FixedOffset::east(8 * 60 * 60);
|
||||||
|
/// let dt = pst.ymd(2018, 1, 26).and_hms_micro(10, 30, 9, 453_829);
|
||||||
|
/// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||||
|
/// "2018-01-26T10:30:09+08:00");
|
||||||
|
/// ```
|
||||||
|
pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String {
|
||||||
|
use format::Numeric::*;
|
||||||
|
use format::Pad::Zero;
|
||||||
|
use SecondsFormat::*;
|
||||||
|
|
||||||
|
const PREFIX: &'static [Item<'static>] = &[
|
||||||
|
Item::Numeric(Year, Zero),
|
||||||
|
Item::Literal("-"),
|
||||||
|
Item::Numeric(Month, Zero),
|
||||||
|
Item::Literal("-"),
|
||||||
|
Item::Numeric(Day, Zero),
|
||||||
|
Item::Literal("T"),
|
||||||
|
Item::Numeric(Hour, Zero),
|
||||||
|
Item::Literal(":"),
|
||||||
|
Item::Numeric(Minute, Zero),
|
||||||
|
Item::Literal(":"),
|
||||||
|
Item::Numeric(Second, Zero),
|
||||||
|
];
|
||||||
|
|
||||||
|
let ssitem = match secform {
|
||||||
|
Secs => None,
|
||||||
|
Millis => Some(Item::Fixed(Fixed::Nanosecond3)),
|
||||||
|
Micros => Some(Item::Fixed(Fixed::Nanosecond6)),
|
||||||
|
Nanos => Some(Item::Fixed(Fixed::Nanosecond9)),
|
||||||
|
AutoSi => Some(Item::Fixed(Fixed::Nanosecond)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tzitem = Item::Fixed(
|
||||||
|
if use_z {
|
||||||
|
Fixed::TimezoneOffsetColonZ
|
||||||
|
} else {
|
||||||
|
Fixed::TimezoneOffsetColon
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
match ssitem {
|
||||||
|
None =>
|
||||||
|
self.format_with_items(
|
||||||
|
PREFIX.iter().chain([tzitem].iter()).cloned()
|
||||||
|
).to_string(),
|
||||||
|
Some(s) =>
|
||||||
|
self.format_with_items(
|
||||||
|
PREFIX.iter().chain([s, tzitem].iter()).cloned()
|
||||||
|
).to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Formats the combined date and time with the specified formatting items.
|
/// Formats the combined date and time with the specified formatting items.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat<I>
|
||||||
|
@ -1059,6 +1155,28 @@ mod tests {
|
||||||
Ok(EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567)));
|
Ok(EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rfc3339_opts() {
|
||||||
|
use SecondsFormat::*;
|
||||||
|
let pst = FixedOffset::east(8 * 60 * 60);
|
||||||
|
let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_000);
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(Secs, false), "2018-01-11T10:05:13+08:00");
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(Secs, true), "2018-01-11T10:05:13+08:00");
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(Millis, false), "2018-01-11T10:05:13.084+08:00");
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(Micros, false), "2018-01-11T10:05:13.084660+08:00");
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(Nanos, false), "2018-01-11T10:05:13.084660000+08:00");
|
||||||
|
assert_eq!(dt.to_rfc3339_opts(AutoSi, false), "2018-01-11T10:05:13.084660+08:00");
|
||||||
|
|
||||||
|
let ut = DateTime::<Utc>::from_utc(dt.naive_utc(), Utc);
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Secs, false), "2018-01-11T02:05:13+00:00");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Secs, true), "2018-01-11T02:05:13Z");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Millis, false), "2018-01-11T02:05:13.084+00:00");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Millis, true), "2018-01-11T02:05:13.084Z");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Micros, true), "2018-01-11T02:05:13.084660Z");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(Nanos, true), "2018-01-11T02:05:13.084660000Z");
|
||||||
|
assert_eq!(ut.to_rfc3339_opts(AutoSi, true), "2018-01-11T02:05:13.084660Z");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_datetime_from_str() {
|
fn test_datetime_from_str() {
|
||||||
assert_eq!("2015-2-18T23:16:9.15Z".parse::<DateTime<FixedOffset>>(),
|
assert_eq!("2015-2-18T23:16:9.15Z".parse::<DateTime<FixedOffset>>(),
|
||||||
|
|
|
@ -406,7 +406,7 @@ pub use oldtime::Duration;
|
||||||
#[doc(no_inline)] pub use offset::{TimeZone, Offset, LocalResult, Utc, FixedOffset, Local};
|
#[doc(no_inline)] pub use offset::{TimeZone, Offset, LocalResult, Utc, FixedOffset, Local};
|
||||||
#[doc(no_inline)] pub use naive::{NaiveDate, IsoWeek, NaiveTime, NaiveDateTime};
|
#[doc(no_inline)] pub use naive::{NaiveDate, IsoWeek, NaiveTime, NaiveDateTime};
|
||||||
pub use date::{Date, MIN_DATE, MAX_DATE};
|
pub use date::{Date, MIN_DATE, MAX_DATE};
|
||||||
pub use datetime::DateTime;
|
pub use datetime::{DateTime, SecondsFormat};
|
||||||
#[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds;
|
#[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds;
|
||||||
pub use format::{ParseError, ParseResult};
|
pub use format::{ParseError, ParseResult};
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ pub mod prelude {
|
||||||
#[doc(no_inline)] pub use {Utc, FixedOffset, Local};
|
#[doc(no_inline)] pub use {Utc, FixedOffset, Local};
|
||||||
#[doc(no_inline)] pub use {NaiveDate, NaiveTime, NaiveDateTime};
|
#[doc(no_inline)] pub use {NaiveDate, NaiveTime, NaiveDateTime};
|
||||||
#[doc(no_inline)] pub use Date;
|
#[doc(no_inline)] pub use Date;
|
||||||
#[doc(no_inline)] pub use DateTime;
|
#[doc(no_inline)] pub use {DateTime, SecondsFormat};
|
||||||
}
|
}
|
||||||
|
|
||||||
// useful throughout the codebase
|
// useful throughout the codebase
|
||||||
|
|
Loading…
Reference in New Issue