implemented `FromStr` for `DateTime<FixedOffset/UTC>`.
This commit is contained in:
parent
76b0873722
commit
46996e35e1
|
@ -6,17 +6,18 @@
|
|||
* ISO 8601 date and time.
|
||||
*/
|
||||
|
||||
use std::{fmt, hash};
|
||||
use std::{str, fmt, hash};
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
use {Weekday, Timelike, Datelike};
|
||||
use offset::{Offset, FixedOffset};
|
||||
use offset::{Offset, FixedOffset, UTC};
|
||||
use duration::Duration;
|
||||
use naive::datetime::NaiveDateTime;
|
||||
use time::Time;
|
||||
use date::Date;
|
||||
use format::{parse, Item, Parsed, ParseResult, DelayedFormat, StrftimeItems};
|
||||
use format::{Item, Numeric, Pad, Fixed};
|
||||
use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
|
||||
|
||||
/// ISO 8601 combined date and time with timezone.
|
||||
#[derive(Clone)]
|
||||
|
@ -261,6 +262,45 @@ impl<Off: Offset + fmt::Display> fmt::Display for DateTime<Off> {
|
|||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for DateTime<FixedOffset> {
|
||||
type Err = ParseError;
|
||||
|
||||
fn from_str(s: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||
const ITEMS: &'static [Item<'static>] = &[
|
||||
Item::Space(""), Item::Numeric(Numeric::Year, Pad::Zero),
|
||||
Item::Space(""), Item::Literal("-"),
|
||||
Item::Space(""), Item::Numeric(Numeric::Month, Pad::Zero),
|
||||
Item::Space(""), Item::Literal("-"),
|
||||
Item::Space(""), Item::Numeric(Numeric::Day, Pad::Zero),
|
||||
Item::Space(""), Item::Literal("T"), // XXX shouldn't this be case-insensitive?
|
||||
Item::Space(""), Item::Numeric(Numeric::Hour, Pad::Zero),
|
||||
Item::Space(""), Item::Literal(":"),
|
||||
Item::Space(""), Item::Numeric(Numeric::Minute, Pad::Zero),
|
||||
Item::Space(""), Item::Literal(":"),
|
||||
Item::Space(""), Item::Numeric(Numeric::Second, Pad::Zero),
|
||||
Item::Fixed(Fixed::Nanosecond),
|
||||
Item::Space(""), Item::Fixed(Fixed::TimezoneOffsetZ),
|
||||
Item::Space(""),
|
||||
];
|
||||
|
||||
let mut parsed = Parsed::new();
|
||||
try!(parse(&mut parsed, s, ITEMS.iter().cloned()));
|
||||
parsed.to_datetime()
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for DateTime<UTC> {
|
||||
type Err = ParseError;
|
||||
|
||||
fn from_str(s: &str) -> ParseResult<DateTime<UTC>> {
|
||||
// we parse non-UTC time zones then convert them into UTC
|
||||
let dt: DateTime<FixedOffset> = try!(s.parse());
|
||||
Ok(dt.with_offset(UTC))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: FromStr for DateTime<Local> is quite hard without a new offset design
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DateTime;
|
||||
|
@ -294,6 +334,21 @@ mod tests {
|
|||
assert!(*EDT.ymd(2014, 5, 6).and_hms(7, 8, 9).offset() != EST);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_from_str() {
|
||||
assert_eq!("2015-2-18T23:16:9.15Z".parse::<DateTime<FixedOffset>>(),
|
||||
Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150)));
|
||||
assert_eq!("2015-2-18T13:16:9.15-10:00".parse::<DateTime<FixedOffset>>(),
|
||||
Ok(FixedOffset::west(10 * 3600).ymd(2015, 2, 18).and_hms_milli(13, 16, 9, 150)));
|
||||
assert!("2015-2-18T23:16:9.15".parse::<DateTime<FixedOffset>>().is_err());
|
||||
|
||||
assert_eq!("2015-2-18T23:16:9.15Z".parse::<DateTime<UTC>>(),
|
||||
Ok(UTC.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150)));
|
||||
assert_eq!("2015-2-18T13:16:9.15-10:00".parse::<DateTime<UTC>>(),
|
||||
Ok(UTC.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150)));
|
||||
assert!("2015-2-18T23:16:9.15".parse::<DateTime<UTC>>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_parse_from_str() {
|
||||
let ymdhms = |&: y,m,d,h,n,s,off| FixedOffset::east(off).ymd(y,m,d).and_hms(h,n,s);
|
||||
|
|
29
src/lib.rs
29
src/lib.rs
|
@ -146,16 +146,21 @@ assert_eq!(dt.to_string(), "2014-11-28 12:00:09 UTC");
|
|||
assert_eq!(format!("{:?}", dt), "2014-11-28T12:00:09Z");
|
||||
~~~~
|
||||
|
||||
Parsing can be done with two methods:
|
||||
Parsing can be done with three methods:
|
||||
|
||||
- `DateTime::parse_from_str` parses a date and time with offsets and
|
||||
returns `DateTime<FixedOffset>`.
|
||||
This should be used when the offset is a part of input and the caller cannot guess that.
|
||||
It *cannot* be used when the offset can be missing.
|
||||
1. The standard `FromStr` trait (and `parse` method on a string) can be used for
|
||||
parsing `DateTime<FixedOffset>` and `DateTime<UTC>` values.
|
||||
This parses what the `{:?}` (`std::fmt::Debug`) format specifier prints,
|
||||
and requires the offset to be present.
|
||||
|
||||
- `Offset::datetime_from_str` is similar but returns `DateTime` of given offset.
|
||||
When the explicit offset is missing from the input, it simply uses given offset.
|
||||
It issues an error when the input contains an explicit offset different from the current offset.
|
||||
2. `DateTime::parse_from_str` parses a date and time with offsets and
|
||||
returns `DateTime<FixedOffset>`.
|
||||
This should be used when the offset is a part of input and the caller cannot guess that.
|
||||
It *cannot* be used when the offset can be missing.
|
||||
|
||||
3. `Offset::datetime_from_str` is similar but returns `DateTime` of given offset.
|
||||
When the explicit offset is missing from the input, it simply uses given offset.
|
||||
It issues an error when the input contains an explicit offset different from the current offset.
|
||||
|
||||
More detailed control over the parsing process is available via `format` module.
|
||||
|
||||
|
@ -163,8 +168,16 @@ More detailed control over the parsing process is available via `format` module.
|
|||
use chrono::{UTC, Offset, DateTime};
|
||||
|
||||
let dt = UTC.ymd(2014, 11, 28).and_hms(12, 0, 9);
|
||||
|
||||
// method 1
|
||||
assert_eq!("2014-11-28T12:00:09Z".parse::<DateTime<UTC>>(), Ok(dt.clone()));
|
||||
assert_eq!("2014-11-28T21:00:09+09:00".parse::<DateTime<UTC>>(), Ok(dt.clone()));
|
||||
|
||||
// method 2
|
||||
assert_eq!(UTC.datetime_from_str("2014-11-28 12:00:09", "%Y-%m-%d %H:%M:%S"), Ok(dt.clone()));
|
||||
assert_eq!(UTC.datetime_from_str("Fri Nov 28 12:00:09 2014", "%a %b %e %T %Y"), Ok(dt.clone()));
|
||||
|
||||
// method 3
|
||||
assert_eq!(DateTime::parse_from_str("2014-11-28 21:00:09 +09:00",
|
||||
"%Y-%m-%d %H:%M:%S %z").map(|dt| dt.with_offset(UTC)), Ok(dt));
|
||||
|
||||
|
|
Loading…
Reference in New Issue