mirror of
https://github.com/chronotope/chrono.git
synced 2025-09-28 21:42:01 +00:00
Split datetime module into different files
This commit is contained in:
parent
2368e37f8e
commit
947914917e
3033
src/datetime.rs
3033
src/datetime.rs
File diff suppressed because it is too large
Load Diff
1094
src/datetime/mod.rs
Normal file
1094
src/datetime/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
119
src/datetime/rustc_serialize.rs
Normal file
119
src/datetime/rustc_serialize.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use super::DateTime;
|
||||
#[cfg(feature = "clock")]
|
||||
use crate::offset::Local;
|
||||
use crate::offset::{FixedOffset, LocalResult, TimeZone, Utc};
|
||||
use core::fmt;
|
||||
use core::ops::Deref;
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
|
||||
impl<Tz: TimeZone> Encodable for DateTime<Tz> {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
format!("{:?}", self).encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
// lik? function to convert a LocalResult into a serde-ish Result
|
||||
fn from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error>
|
||||
where
|
||||
D: Decoder,
|
||||
T: fmt::Display,
|
||||
{
|
||||
match me {
|
||||
LocalResult::None => Err(d.error("value is not a legal timestamp")),
|
||||
LocalResult::Ambiguous(..) => Err(d.error("value is an ambiguous timestamp")),
|
||||
LocalResult::Single(val) => Ok(val),
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for DateTime<FixedOffset> {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<FixedOffset>, D::Error> {
|
||||
d.read_str()?.parse::<DateTime<FixedOffset>>().map_err(|_| d.error("invalid date and time"))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Decodable for TsSeconds<FixedOffset> {
|
||||
#[allow(deprecated)]
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<FixedOffset>, D::Error> {
|
||||
from(FixedOffset::east(0).timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for DateTime<Utc> {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Utc>, D::Error> {
|
||||
d.read_str()?
|
||||
.parse::<DateTime<FixedOffset>>()
|
||||
.map(|dt| dt.with_timezone(&Utc))
|
||||
.map_err(|_| d.error("invalid date and time"))
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`DateTime`] that can be deserialized from a timestamp
|
||||
///
|
||||
/// A timestamp here is seconds since the epoch
|
||||
#[derive(Debug)]
|
||||
pub struct TsSeconds<Tz: TimeZone>(DateTime<Tz>);
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<Tz: TimeZone> From<TsSeconds<Tz>> for DateTime<Tz> {
|
||||
/// Pull the inner DateTime<Tz> out
|
||||
#[allow(deprecated)]
|
||||
fn from(obj: TsSeconds<Tz>) -> DateTime<Tz> {
|
||||
obj.0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<Tz: TimeZone> Deref for TsSeconds<Tz> {
|
||||
type Target = DateTime<Tz>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Decodable for TsSeconds<Utc> {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Utc>, D::Error> {
|
||||
from(Utc.timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "clock")]
|
||||
impl Decodable for DateTime<Local> {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Local>, D::Error> {
|
||||
match d.read_str()?.parse::<DateTime<FixedOffset>>() {
|
||||
Ok(dt) => Ok(dt.with_timezone(&Local)),
|
||||
Err(_) => Err(d.error("invalid date and time")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "clock")]
|
||||
#[allow(deprecated)]
|
||||
impl Decodable for TsSeconds<Local> {
|
||||
#[allow(deprecated)]
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Local>, D::Error> {
|
||||
from(Utc.timestamp_opt(d.read_i64()?, 0), d).map(|dt| TsSeconds(dt.with_timezone(&Local)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use rustc_serialize::json;
|
||||
|
||||
#[test]
|
||||
fn test_encodable() {
|
||||
super::test_encodable_json(json::encode, json::encode);
|
||||
}
|
||||
|
||||
#[cfg(feature = "clock")]
|
||||
#[test]
|
||||
fn test_decodable() {
|
||||
super::test_decodable_json(json::decode, json::decode, json::decode);
|
||||
}
|
||||
|
||||
#[cfg(feature = "clock")]
|
||||
#[test]
|
||||
fn test_decodable_timestamps() {
|
||||
super::test_decodable_json_timestamps(json::decode, json::decode, json::decode);
|
||||
}
|
1368
src/datetime/serde.rs
Normal file
1368
src/datetime/serde.rs
Normal file
File diff suppressed because it is too large
Load Diff
437
src/datetime/tests.rs
Normal file
437
src/datetime/tests.rs
Normal file
@ -0,0 +1,437 @@
|
||||
use super::DateTime;
|
||||
use crate::naive::{NaiveDate, NaiveTime};
|
||||
#[cfg(feature = "clock")]
|
||||
use crate::offset::Local;
|
||||
use crate::offset::{FixedOffset, TimeZone, Utc};
|
||||
use crate::oldtime::Duration;
|
||||
#[cfg(feature = "clock")]
|
||||
use crate::Datelike;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn test_datetime_offset() {
|
||||
let Est = FixedOffset::west(5 * 60 * 60);
|
||||
let Edt = FixedOffset::west(4 * 60 * 60);
|
||||
let Kst = FixedOffset::east(9 * 60 * 60);
|
||||
|
||||
assert_eq!(format!("{}", Utc.ymd(2014, 5, 6).and_hms(7, 8, 9)), "2014-05-06 07:08:09 UTC");
|
||||
assert_eq!(
|
||||
format!("{}", Edt.ymd(2014, 5, 6).and_hms(7, 8, 9)),
|
||||
"2014-05-06 07:08:09 -04:00"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{}", Kst.ymd(2014, 5, 6).and_hms(7, 8, 9)),
|
||||
"2014-05-06 07:08:09 +09:00"
|
||||
);
|
||||
assert_eq!(format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(7, 8, 9)), "2014-05-06T07:08:09Z");
|
||||
assert_eq!(
|
||||
format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(7, 8, 9)),
|
||||
"2014-05-06T07:08:09-04:00"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(7, 8, 9)),
|
||||
"2014-05-06T07:08:09+09:00"
|
||||
);
|
||||
|
||||
// edge cases
|
||||
assert_eq!(format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(0, 0, 0)), "2014-05-06T00:00:00Z");
|
||||
assert_eq!(
|
||||
format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(0, 0, 0)),
|
||||
"2014-05-06T00:00:00-04:00"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(0, 0, 0)),
|
||||
"2014-05-06T00:00:00+09:00"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(23, 59, 59)),
|
||||
"2014-05-06T23:59:59Z"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(23, 59, 59)),
|
||||
"2014-05-06T23:59:59-04:00"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(23, 59, 59)),
|
||||
"2014-05-06T23:59:59+09:00"
|
||||
);
|
||||
|
||||
let dt = Utc.ymd(2014, 5, 6).and_hms(7, 8, 9);
|
||||
assert_eq!(dt, Edt.ymd(2014, 5, 6).and_hms(3, 8, 9));
|
||||
assert_eq!(dt + Duration::seconds(3600 + 60 + 1), Utc.ymd(2014, 5, 6).and_hms(8, 9, 10));
|
||||
assert_eq!(
|
||||
dt.signed_duration_since(Edt.ymd(2014, 5, 6).and_hms(10, 11, 12)),
|
||||
Duration::seconds(-7 * 3600 - 3 * 60 - 3)
|
||||
);
|
||||
|
||||
assert_eq!(*Utc.ymd(2014, 5, 6).and_hms(7, 8, 9).offset(), Utc);
|
||||
assert_eq!(*Edt.ymd(2014, 5, 6).and_hms(7, 8, 9).offset(), Edt);
|
||||
assert!(*Edt.ymd(2014, 5, 6).and_hms(7, 8, 9).offset() != Est);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_date_and_time() {
|
||||
let tz = FixedOffset::east(5 * 60 * 60);
|
||||
let d = tz.ymd(2014, 5, 6).and_hms(7, 8, 9);
|
||||
assert_eq!(d.time(), NaiveTime::from_hms(7, 8, 9));
|
||||
assert_eq!(d.date(), tz.ymd(2014, 5, 6));
|
||||
assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2014, 5, 6));
|
||||
assert_eq!(d.date().and_time(d.time()), Some(d));
|
||||
|
||||
let tz = FixedOffset::east(4 * 60 * 60);
|
||||
let d = tz.ymd(2016, 5, 4).and_hms(3, 2, 1);
|
||||
assert_eq!(d.time(), NaiveTime::from_hms(3, 2, 1));
|
||||
assert_eq!(d.date(), tz.ymd(2016, 5, 4));
|
||||
assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2016, 5, 4));
|
||||
assert_eq!(d.date().and_time(d.time()), Some(d));
|
||||
|
||||
let tz = FixedOffset::west(13 * 60 * 60);
|
||||
let d = tz.ymd(2017, 8, 9).and_hms(12, 34, 56);
|
||||
assert_eq!(d.time(), NaiveTime::from_hms(12, 34, 56));
|
||||
assert_eq!(d.date(), tz.ymd(2017, 8, 9));
|
||||
assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2017, 8, 9));
|
||||
assert_eq!(d.date().and_time(d.time()), Some(d));
|
||||
|
||||
let utc_d = Utc.ymd(2017, 8, 9).and_hms(12, 34, 56);
|
||||
assert!(utc_d < d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "clock")]
|
||||
fn test_datetime_with_timezone() {
|
||||
let local_now = Local::now();
|
||||
let utc_now = local_now.with_timezone(&Utc);
|
||||
let local_now2 = utc_now.with_timezone(&Local);
|
||||
assert_eq!(local_now, local_now2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn test_datetime_rfc2822_and_rfc3339() {
|
||||
let EDT = FixedOffset::east(5 * 60 * 60);
|
||||
assert_eq!(
|
||||
Utc.ymd(2015, 2, 18).and_hms(23, 16, 9).to_rfc2822(),
|
||||
"Wed, 18 Feb 2015 23:16:09 +0000"
|
||||
);
|
||||
assert_eq!(
|
||||
Utc.ymd(2015, 2, 18).and_hms(23, 16, 9).to_rfc3339(),
|
||||
"2015-02-18T23:16:09+00:00"
|
||||
);
|
||||
assert_eq!(
|
||||
EDT.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150).to_rfc2822(),
|
||||
"Wed, 18 Feb 2015 23:16:09 +0500"
|
||||
);
|
||||
assert_eq!(
|
||||
EDT.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150).to_rfc3339(),
|
||||
"2015-02-18T23:16:09.150+05:00"
|
||||
);
|
||||
assert_eq!(
|
||||
EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567).to_rfc2822(),
|
||||
"Wed, 18 Feb 2015 23:59:60 +0500"
|
||||
);
|
||||
assert_eq!(
|
||||
EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567).to_rfc3339(),
|
||||
"2015-02-18T23:59:60.234567+05:00"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 +0000"),
|
||||
Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 -0000"),
|
||||
Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::parse_from_rfc3339("2015-02-18T23:16:09Z"),
|
||||
Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:59:60 +0500"),
|
||||
Ok(EDT.ymd(2015, 2, 18).and_hms_milli(23, 59, 59, 1_000))
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::parse_from_rfc3339("2015-02-18T23:59:60.234567+05:00"),
|
||||
Ok(EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rfc3339_opts() {
|
||||
use crate::SecondsFormat::*;
|
||||
let pst = FixedOffset::east(8 * 60 * 60);
|
||||
let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 84_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]
|
||||
#[should_panic]
|
||||
fn test_rfc3339_opts_nonexhaustive() {
|
||||
use crate::SecondsFormat;
|
||||
let dt = Utc.ymd(1999, 10, 9).and_hms(1, 2, 3);
|
||||
dt.to_rfc3339_opts(SecondsFormat::__NonExhaustive, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_from_str() {
|
||||
assert_eq!(
|
||||
"2015-02-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-02-18T23:16:9.15Z".parse::<DateTime<Utc>>(),
|
||||
Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
|
||||
);
|
||||
assert_eq!(
|
||||
"2015-02-18T23:16:9.15 UTC".parse::<DateTime<Utc>>(),
|
||||
Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
|
||||
);
|
||||
assert_eq!(
|
||||
"2015-02-18T23:16:9.15UTC".parse::<DateTime<Utc>>(),
|
||||
Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
|
||||
);
|
||||
|
||||
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());
|
||||
|
||||
// no test for `DateTime<Local>`, we cannot verify that much.
|
||||
}
|
||||
|
||||
#[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);
|
||||
assert_eq!(
|
||||
DateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
|
||||
Ok(ymdhms(2014, 5, 7, 12, 34, 56, 570 * 60))
|
||||
); // ignore offset
|
||||
assert!(DateTime::parse_from_str("20140507000000", "%Y%m%d%H%M%S").is_err()); // no offset
|
||||
assert!(DateTime::parse_from_str(
|
||||
"Fri, 09 Aug 2013 23:54:35 GMT",
|
||||
"%a, %d %b %Y %H:%M:%S GMT"
|
||||
)
|
||||
.is_err());
|
||||
assert_eq!(
|
||||
Utc.datetime_from_str("Fri, 09 Aug 2013 23:54:35 GMT", "%a, %d %b %Y %H:%M:%S GMT"),
|
||||
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_string_round_trip() {
|
||||
let dt = Utc.ymd(2000, 1, 1).and_hms(0, 0, 0);
|
||||
let _dt: DateTime<Utc> = dt.to_string().parse().unwrap();
|
||||
|
||||
let ndt_fixed = dt.with_timezone(&FixedOffset::east(3600));
|
||||
let _dt: DateTime<FixedOffset> = ndt_fixed.to_string().parse().unwrap();
|
||||
|
||||
let ndt_fixed = dt.with_timezone(&FixedOffset::east(0));
|
||||
let _dt: DateTime<FixedOffset> = ndt_fixed.to_string().parse().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "clock")]
|
||||
fn test_to_string_round_trip_with_local() {
|
||||
let ndt = Local::now();
|
||||
let _dt: DateTime<FixedOffset> = ndt.to_string().parse().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "clock")]
|
||||
fn test_datetime_format_with_local() {
|
||||
// if we are not around the year boundary, local and UTC date should have the same year
|
||||
let dt = Local::now().with_month(5).unwrap();
|
||||
assert_eq!(dt.format("%Y").to_string(), dt.with_timezone(&Utc).format("%Y").to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "clock")]
|
||||
fn test_datetime_is_copy() {
|
||||
// UTC is known to be `Copy`.
|
||||
let a = Utc::now();
|
||||
let b = a;
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "clock")]
|
||||
fn test_datetime_is_send() {
|
||||
use std::thread;
|
||||
|
||||
// UTC is known to be `Send`.
|
||||
let a = Utc::now();
|
||||
thread::spawn(move || {
|
||||
let _ = a;
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subsecond_part() {
|
||||
let datetime = Utc.ymd(2014, 7, 8).and_hms_nano(9, 10, 11, 1234567);
|
||||
|
||||
assert_eq!(1, datetime.timestamp_subsec_millis());
|
||||
assert_eq!(1234, datetime.timestamp_subsec_micros());
|
||||
assert_eq!(1234567, datetime.timestamp_subsec_nanos());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn test_from_system_time() {
|
||||
use std::time::Duration;
|
||||
|
||||
let epoch = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
|
||||
let nanos = 999_999_999;
|
||||
|
||||
// SystemTime -> DateTime<Utc>
|
||||
assert_eq!(DateTime::<Utc>::from(UNIX_EPOCH), epoch);
|
||||
assert_eq!(
|
||||
DateTime::<Utc>::from(UNIX_EPOCH + Duration::new(999_999_999, nanos)),
|
||||
Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::<Utc>::from(UNIX_EPOCH - Duration::new(999_999_999, nanos)),
|
||||
Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1)
|
||||
);
|
||||
|
||||
// DateTime<Utc> -> SystemTime
|
||||
assert_eq!(SystemTime::from(epoch), UNIX_EPOCH);
|
||||
assert_eq!(
|
||||
SystemTime::from(Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)),
|
||||
UNIX_EPOCH + Duration::new(999_999_999, nanos)
|
||||
);
|
||||
assert_eq!(
|
||||
SystemTime::from(Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1)),
|
||||
UNIX_EPOCH - Duration::new(999_999_999, 999_999_999)
|
||||
);
|
||||
|
||||
// DateTime<any tz> -> SystemTime (via `with_timezone`)
|
||||
#[cfg(feature = "clock")]
|
||||
{
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&Local)), UNIX_EPOCH);
|
||||
}
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::east(32400))), UNIX_EPOCH);
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::west(28800))), UNIX_EPOCH);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "windows")]
|
||||
fn test_from_system_time() {
|
||||
use std::time::Duration;
|
||||
|
||||
let nanos = 999_999_000;
|
||||
|
||||
let epoch = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
|
||||
|
||||
// SystemTime -> DateTime<Utc>
|
||||
assert_eq!(DateTime::<Utc>::from(UNIX_EPOCH), epoch);
|
||||
assert_eq!(
|
||||
DateTime::<Utc>::from(UNIX_EPOCH + Duration::new(999_999_999, nanos)),
|
||||
Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)
|
||||
);
|
||||
assert_eq!(
|
||||
DateTime::<Utc>::from(UNIX_EPOCH - Duration::new(999_999_999, nanos)),
|
||||
Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1_000)
|
||||
);
|
||||
|
||||
// DateTime<Utc> -> SystemTime
|
||||
assert_eq!(SystemTime::from(epoch), UNIX_EPOCH);
|
||||
assert_eq!(
|
||||
SystemTime::from(Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)),
|
||||
UNIX_EPOCH + Duration::new(999_999_999, nanos)
|
||||
);
|
||||
assert_eq!(
|
||||
SystemTime::from(Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1_000)),
|
||||
UNIX_EPOCH - Duration::new(999_999_999, nanos)
|
||||
);
|
||||
|
||||
// DateTime<any tz> -> SystemTime (via `with_timezone`)
|
||||
#[cfg(feature = "clock")]
|
||||
{
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&Local)), UNIX_EPOCH);
|
||||
}
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::east(32400))), UNIX_EPOCH);
|
||||
assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::west(28800))), UNIX_EPOCH);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_format_alignment() {
|
||||
let datetime = Utc.ymd(2007, 1, 2);
|
||||
|
||||
// Item::Literal
|
||||
let percent = datetime.format("%%");
|
||||
assert_eq!(" %", format!("{:>3}", percent));
|
||||
assert_eq!("% ", format!("{:<3}", percent));
|
||||
assert_eq!(" % ", format!("{:^3}", percent));
|
||||
|
||||
// Item::Numeric
|
||||
let year = datetime.format("%Y");
|
||||
assert_eq!(" 2007", format!("{:>6}", year));
|
||||
assert_eq!("2007 ", format!("{:<6}", year));
|
||||
assert_eq!(" 2007 ", format!("{:^6}", year));
|
||||
|
||||
// Item::Fixed
|
||||
let tz = datetime.format("%Z");
|
||||
assert_eq!(" UTC", format!("{:>5}", tz));
|
||||
assert_eq!("UTC ", format!("{:<5}", tz));
|
||||
assert_eq!(" UTC ", format!("{:^5}", tz));
|
||||
|
||||
// [Item::Numeric, Item::Space, Item::Literal, Item::Space, Item::Numeric]
|
||||
let ymd = datetime.format("%Y %B %d");
|
||||
let ymd_formatted = "2007 January 02";
|
||||
assert_eq!(format!(" {}", ymd_formatted), format!("{:>17}", ymd));
|
||||
assert_eq!(format!("{} ", ymd_formatted), format!("{:<17}", ymd));
|
||||
assert_eq!(format!(" {} ", ymd_formatted), format!("{:^17}", ymd));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_from_local() {
|
||||
// 2000-01-12T02:00:00Z
|
||||
let naivedatetime_utc = NaiveDate::from_ymd(2000, 1, 12).and_hms(2, 0, 0);
|
||||
let datetime_utc = DateTime::<Utc>::from_utc(naivedatetime_utc, Utc);
|
||||
|
||||
// 2000-01-12T10:00:00+8:00:00
|
||||
let timezone_east = FixedOffset::east(8 * 60 * 60);
|
||||
let naivedatetime_east = NaiveDate::from_ymd(2000, 1, 12).and_hms(10, 0, 0);
|
||||
let datetime_east = DateTime::<FixedOffset>::from_local(naivedatetime_east, timezone_east);
|
||||
|
||||
// 2000-01-11T19:00:00-7:00:00
|
||||
let timezone_west = FixedOffset::west(7 * 60 * 60);
|
||||
let naivedatetime_west = NaiveDate::from_ymd(2000, 1, 11).and_hms(19, 0, 0);
|
||||
let datetime_west = DateTime::<FixedOffset>::from_local(naivedatetime_west, timezone_west);
|
||||
|
||||
assert_eq!(datetime_east, datetime_utc.with_timezone(&timezone_east));
|
||||
assert_eq!(datetime_west, datetime_utc.with_timezone(&timezone_west));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user