chrono icon indicating copy to clipboard operation
chrono copied to clipboard

unexpected behavior of `duration_trunc` with `DateTime<FixedOffset>`

Open kkazuo opened this issue 4 years ago • 1 comments

extern crate chrono; // 0.4.19

use chrono::{FixedOffset, Utc, Duration, DurationRound, Timelike};

fn main() {
    let t = Utc::now();
    let t = t.with_timezone(&FixedOffset::east(9 * 3600));
    let t = t.duration_trunc(Duration::days(1)).unwrap();
    assert_eq!(t.second(), 0);
    assert_eq!(t.minute(), 0);
    assert_eq!(t.hour(), 0); // I expect 0, but got 9.
}
 Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.72s
     Running `target/debug/playground`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `9`,
 right: `0`', src/main.rs:11:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I want to get the truncated time with timezone aware.

kkazuo avatar Aug 14 '21 02:08 kkazuo

Copied the example from the docs https://docs.rs/chrono/0.4.13/chrono/trait.DurationRound.html#example-1 and changed to use Local vs Utc.

let dt = Local.ymd(2018, 1, 11).and_hms_milli(12, 0, 0, 154);
assert_eq!(
    dt.duration_trunc(Duration::milliseconds(10)).unwrap().to_string(),
    "2018-01-11 12:00:00.150 -08:00" // Seems like millisec truncation works just fine
);
assert_eq!(
    dt.duration_trunc(Duration::days(1)).unwrap().to_string(),
    "2018-01-11 00:00:00 -08:00" // got "2018-01-10 16:00:00 -08:00"
);
thread 'tests::duration_trunc' panicked at 'assertion failed: `(left == right)`
  left: `"2018-01-10 16:00:00 -08:00"`,
  right: `"2018-01-11 00:00:00 -08:00"`'

There's definitely an issue with timezone conversions and truncation duration_trunc seems to be converting to UTC then truncating and then converting back to TZ which is going to give unexpected results. Interestingly millisec seems to behave just fine.

stewartallen avatar Jun 07 '22 06:06 stewartallen