Skip to content

Commit

Permalink
Fix chrono::DurationRound is not TZ aware
Browse files Browse the repository at this point in the history
  • Loading branch information
robyoung authored and pickfire committed Jan 22, 2022
1 parent 5dfede9 commit 67627f8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,7 @@ Versions with only mechanical changes will be omitted from the following list.

* Add more formatting documentation and examples.
* Add support for microseconds timestamps serde serialization/deserialization (#304)
* Fix `DurationRound` is not TZ aware (#495)

## 0.4.19

Expand Down
56 changes: 52 additions & 4 deletions src/round.rs
Expand Up @@ -151,10 +151,12 @@ impl<Tz: TimeZone> DurationRound for DateTime<Tz> {

fn duration_round(self, duration: Duration) -> Result<Self, Self::Err> {
if let Some(span) = duration.num_nanoseconds() {
if self.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
let naive = self.naive_local();

if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
return Err(RoundingError::TimestampExceedsLimit);
}
let stamp = self.timestamp_nanos();
let stamp = naive.timestamp_nanos();
if span > stamp.abs() {
return Err(RoundingError::DurationExceedsTimestamp);
}
Expand All @@ -180,10 +182,12 @@ impl<Tz: TimeZone> DurationRound for DateTime<Tz> {

fn duration_trunc(self, duration: Duration) -> Result<Self, Self::Err> {
if let Some(span) = duration.num_nanoseconds() {
if self.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
let naive = self.naive_local();

if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
return Err(RoundingError::TimestampExceedsLimit);
}
let stamp = self.timestamp_nanos();
let stamp = naive.timestamp_nanos();
if span > stamp.abs() {
return Err(RoundingError::DurationExceedsTimestamp);
}
Expand Down Expand Up @@ -395,6 +399,28 @@ mod tests {
dt.duration_round(Duration::days(1)).unwrap().to_string(),
"2012-12-13 00:00:00 UTC"
);

// timezone east
let dt = FixedOffset::east(1 * 3600).ymd(2020, 10, 27).and_hms(15, 0, 0);
assert_eq!(
dt.duration_round(Duration::days(1)).unwrap().to_string(),
"2020-10-28 00:00:00 +01:00"
);
assert_eq!(
dt.duration_round(Duration::weeks(1)).unwrap().to_string(),
"2020-10-29 00:00:00 +01:00"
);

// timezone west
let dt = FixedOffset::west(1 * 3600).ymd(2020, 10, 27).and_hms(15, 0, 0);
assert_eq!(
dt.duration_round(Duration::days(1)).unwrap().to_string(),
"2020-10-28 00:00:00 -01:00"
);
assert_eq!(
dt.duration_round(Duration::weeks(1)).unwrap().to_string(),
"2020-10-29 00:00:00 -01:00"
);
}

#[test]
Expand Down Expand Up @@ -443,6 +469,28 @@ mod tests {
dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
"2012-12-12 00:00:00 UTC"
);

// timezone east
let dt = FixedOffset::east(1 * 3600).ymd(2020, 10, 27).and_hms(15, 0, 0);
assert_eq!(
dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
"2020-10-27 00:00:00 +01:00"
);
assert_eq!(
dt.duration_trunc(Duration::weeks(1)).unwrap().to_string(),
"2020-10-22 00:00:00 +01:00"
);

// timezone west
let dt = FixedOffset::west(1 * 3600).ymd(2020, 10, 27).and_hms(15, 0, 0);
assert_eq!(
dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
"2020-10-27 00:00:00 -01:00"
);
assert_eq!(
dt.duration_trunc(Duration::weeks(1)).unwrap().to_string(),
"2020-10-22 00:00:00 -01:00"
);
}

#[test]
Expand Down

0 comments on commit 67627f8

Please sign in to comment.