From 2dbc11dcb150a2653456540370fd85af434d0746 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Fri, 27 Feb 2015 13:08:20 +0900 Subject: [PATCH] 0.2.3: Fixed a couple of outstanding bugs. - `DateTime` and `Date` is now `Copy`/`Send` when `Tz::Offset` is `Copy`/`Send`. The implementations for them were mistakenly omitted. Fixes #25. - `Local::from_utc_datetime` didn't set a correct offset. The tests for `Local` were lacking. Fixes #26. --- CHANGELOG.md | 11 +++++++++++ Cargo.toml | 2 +- README.md | 2 +- src/date.rs | 4 ++++ src/datetime.rs | 32 ++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/offset/local.rs | 16 ++++++++++------ 7 files changed, 60 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68c1b62..79d0670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,17 @@ Chrono obeys the principle of [Semantic Versioning](http://semver.org/). There were/are numerous minor versions before 1.0 due to the language changes. Versions with only mechnical changes will be omitted from the following list. +## 0.2.3 (2015-02-27) + +### Added + +- `DateTime` and `Date` is now `Copy`/`Send` when `Tz::Offset` is `Copy`/`Send`. + The implementations for them were mistakenly omitted. (#25) + +### Fixed + +- `Local::from_utc_datetime` didn't set a correct offset. (#26) + ## 0.2.1 (2015-02-21) ### Changed diff --git a/Cargo.toml b/Cargo.toml index 19d2226..525a32f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chrono" -version = "0.2.2" +version = "0.2.3" authors = ["Kang Seonghoon "] description = "Date and time library for Rust" diff --git a/README.md b/README.md index 783fc69..a8331a7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[Chrono][doc] 0.2.2 +[Chrono][doc] 0.2.3 =================== [![Chrono on Travis CI][travis-image]][travis] diff --git a/src/date.rs b/src/date.rs index a726ead..4347d4c 100644 --- a/src/date.rs +++ b/src/date.rs @@ -284,6 +284,10 @@ impl Datelike for Date { } } +// we need them as automatic impls cannot handle associated types +impl Copy for Date where ::Offset: Copy {} +unsafe impl Send for Date where ::Offset: Send {} + impl PartialEq> for Date { fn eq(&self, other: &Date) -> bool { self.date == other.date } } diff --git a/src/datetime.rs b/src/datetime.rs index de6d4bb..12c0687 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -259,6 +259,10 @@ impl Timelike for DateTime { } } +// we need them as automatic impls cannot handle associated types +impl Copy for DateTime where ::Offset: Copy {} +unsafe impl Send for DateTime where ::Offset: Send {} + impl PartialEq> for DateTime { fn eq(&self, other: &DateTime) -> bool { self.datetime == other.datetime } } @@ -403,6 +407,14 @@ mod tests { NaiveTime::from_hms(7, 8, 9)); } + #[test] + 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() { @@ -466,5 +478,25 @@ mod tests { let dt = Local::now().with_month(5).unwrap(); assert_eq!(dt.format("%Y").to_string(), dt.with_timezone(&UTC).format("%Y").to_string()); } + + #[test] + #[ignore] // XXX Rust issue #22818 + fn test_datetime_is_copy() { + // UTC is known to be `Copy`. + let a = UTC::now(); + let b = a; + assert_eq!(a, b); + } + + #[test] + fn test_datetime_is_send() { + use std::thread; + + // UTC is known to be `Send`. + let a = UTC::now(); + thread::scoped(move || { + let _ = a; + }).join(); + } } diff --git a/src/lib.rs b/src/lib.rs index 806ddca..600f020 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ /*! -# Chrono 0.2.2 +# Chrono 0.2.3 Date and time handling for Rust. (also known as `rust-chrono`) It aims to be a feature-complete superset of the [time](https://github.com/rust-lang/time) library. diff --git a/src/offset/local.rs b/src/offset/local.rs index a4ca05d..6cf1ec3 100644 --- a/src/offset/local.rs +++ b/src/offset/local.rs @@ -35,7 +35,12 @@ fn tm_to_datetime(mut tm: stdtime::Tm) -> DateTime { } /// Converts a local `NaiveDateTime` to the `time::Timespec`. -fn datetime_to_timespec(d: &NaiveDateTime) -> stdtime::Timespec { +fn datetime_to_timespec(d: &NaiveDateTime, local: bool) -> stdtime::Timespec { + // well, this exploits an undocumented `Tm::to_timespec` behavior + // to get the exact function we want (either `timegm` or `mktime`). + // the number 1 is arbitrary but should be non-zero to trigger `mktime`. + let tm_utcoff = if local {1} else {0}; + let tm = stdtime::Tm { tm_sec: d.second() as i32, tm_min: d.minute() as i32, @@ -46,8 +51,7 @@ fn datetime_to_timespec(d: &NaiveDateTime) -> stdtime::Timespec { tm_wday: 0, // to_local ignores this tm_yday: 0, // and this tm_isdst: -1, - tm_utcoff: 1, // this is arbitrary but should be nonzero - // in order to make `to_timespec` use `rust_mktime` internally. + tm_utcoff: tm_utcoff, tm_nsec: d.nanosecond() as i32, }; tm.to_timespec() @@ -94,7 +98,7 @@ impl TimeZone for Local { self.from_local_datetime(&local.and_hms(0, 0, 0)).map(|datetime| datetime.date()) } fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult> { - let timespec = datetime_to_timespec(local); + let timespec = datetime_to_timespec(local, true); LocalResult::Single(tm_to_datetime(stdtime::at(timespec))) } @@ -102,8 +106,8 @@ impl TimeZone for Local { self.from_utc_datetime(&utc.and_hms(0, 0, 0)).date() } fn from_utc_datetime(&self, utc: &NaiveDateTime) -> DateTime { - let timespec = datetime_to_timespec(utc); - tm_to_datetime(stdtime::at_utc(timespec)) + let timespec = datetime_to_timespec(utc, false); + tm_to_datetime(stdtime::at(timespec)) } }