@@ -219,42 +219,51 @@ fn quarter_month(date: &NaiveDateTime) -> u32 {
219
219
/// account that some granularities are not uniform durations of time
220
220
/// (e.g. months are not always the same lengths, leap seconds, etc)
221
221
fn date_trunc_coarse ( granularity : & str , value : i64 ) -> Result < i64 > {
222
- if granularity == "millisecond" || granularity == "microsecond" {
223
- return Ok ( value) ;
224
- }
222
+ // Use chrono NaiveDateTime to clear the various fields
223
+ // correctly accounting for non uniform granularities
224
+ let value = timestamp_ns_to_datetime ( value) . ok_or_else ( || {
225
+ DataFusionError :: Execution ( format ! ( "Timestamp {value} out of range" ) )
226
+ } ) ?;
227
+
228
+ let value = Some ( value) ;
225
229
226
- let value = timestamp_ns_to_datetime ( value)
227
- . ok_or_else ( || {
228
- DataFusionError :: Execution ( format ! ( "Timestamp {value} out of range" ) )
229
- } ) ?
230
- . with_nanosecond ( 0 ) ;
231
230
let value = match granularity {
232
- "second" => value,
233
- "minute" => value. and_then ( |d| d. with_second ( 0 ) ) ,
231
+ "millisecond" => value,
232
+ "microsecond" => value,
233
+ "second" => value. and_then ( |d| d. with_nanosecond ( 0 ) ) ,
234
+ "minute" => value
235
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
236
+ . and_then ( |d| d. with_second ( 0 ) ) ,
234
237
"hour" => value
238
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
235
239
. and_then ( |d| d. with_second ( 0 ) )
236
240
. and_then ( |d| d. with_minute ( 0 ) ) ,
237
241
"day" => value
242
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
238
243
. and_then ( |d| d. with_second ( 0 ) )
239
244
. and_then ( |d| d. with_minute ( 0 ) )
240
245
. and_then ( |d| d. with_hour ( 0 ) ) ,
241
246
"week" => value
247
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
242
248
. and_then ( |d| d. with_second ( 0 ) )
243
249
. and_then ( |d| d. with_minute ( 0 ) )
244
250
. and_then ( |d| d. with_hour ( 0 ) )
245
251
. map ( |d| d - Duration :: seconds ( 60 * 60 * 24 * d. weekday ( ) as i64 ) ) ,
246
252
"month" => value
253
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
247
254
. and_then ( |d| d. with_second ( 0 ) )
248
255
. and_then ( |d| d. with_minute ( 0 ) )
249
256
. and_then ( |d| d. with_hour ( 0 ) )
250
257
. and_then ( |d| d. with_day0 ( 0 ) ) ,
251
258
"quarter" => value
259
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
252
260
. and_then ( |d| d. with_second ( 0 ) )
253
261
. and_then ( |d| d. with_minute ( 0 ) )
254
262
. and_then ( |d| d. with_hour ( 0 ) )
255
263
. and_then ( |d| d. with_day0 ( 0 ) )
256
264
. and_then ( |d| d. with_month ( quarter_month ( & d) ) ) ,
257
265
"year" => value
266
+ . and_then ( |d| d. with_nanosecond ( 0 ) )
258
267
. and_then ( |d| d. with_second ( 0 ) )
259
268
. and_then ( |d| d. with_minute ( 0 ) )
260
269
. and_then ( |d| d. with_hour ( 0 ) )
0 commit comments