From 897a50f4d5bc2a80e4ff9d8d361ebf4bf083e2a4 Mon Sep 17 00:00:00 2001 From: yuankunzhang Date: Wed, 23 Jul 2025 15:33:15 +0000 Subject: [PATCH] fix base datetime handling in the builder --- src/items/builder.rs | 42 +++++++++++++++++++++++------------------- src/items/mod.rs | 6 ++++++ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/items/builder.rs b/src/items/builder.rs index 2d2db7f..9fb76ef 100644 --- a/src/items/builder.rs +++ b/src/items/builder.rs @@ -105,16 +105,28 @@ impl DateTimeBuilder { pub(super) fn build(self) -> Option> { let base = self.base.unwrap_or_else(|| chrono::Local::now().into()); - let mut dt = new_date( - base.year(), - base.month(), - base.day(), - 0, - 0, - 0, - 0, - *base.offset(), - )?; + + // If any of the following items are set, we truncate the time portion + // of the base date to zero; otherwise, we use the base date as is. + let mut dt = if self.timestamp.is_none() + && self.date.is_none() + && self.time.is_none() + && self.weekday.is_none() + && self.timezone.is_none() + { + base + } else { + new_date( + base.year(), + base.month(), + base.day(), + 0, + 0, + 0, + 0, + *base.offset(), + )? + }; if let Some(ts) = self.timestamp { // TODO: How to make the fract -> nanosecond conversion more precise? @@ -221,14 +233,6 @@ impl DateTimeBuilder { } for rel in self.relative { - if self.timestamp.is_none() - && self.date.is_none() - && self.time.is_none() - && self.weekday.is_none() - { - dt = base; - } - match rel { relative::Relative::Years(x) => { dt = dt.with_year(dt.year() + x)?; @@ -254,7 +258,7 @@ impl DateTimeBuilder { relative::Relative::Minutes(x) => { dt += chrono::Duration::try_minutes(x.into())?; } - // Seconds are special because they can be given as a float + // Seconds are special because they can be given as a float. relative::Relative::Seconds(x) => { dt += chrono::Duration::try_seconds(x as i64)?; } diff --git a/src/items/mod.rs b/src/items/mod.rs index 4259664..6ace7a0 100644 --- a/src/items/mod.rs +++ b/src/items/mod.rs @@ -446,6 +446,12 @@ mod tests { assert_eq!(result.minute(), now.minute()); assert_eq!(result.second(), now.second()); + let result = at_date(parse(&mut "2 days 3 days ago").unwrap(), now).unwrap(); + assert_eq!(result, now - chrono::Duration::days(1)); + assert_eq!(result.hour(), now.hour()); + assert_eq!(result.minute(), now.minute()); + assert_eq!(result.second(), now.second()); + let result = at_date(parse(&mut "2025-01-01 2 days ago").unwrap(), now).unwrap(); assert_eq!(result.hour(), 0); assert_eq!(result.minute(), 0);