@@ -19,10 +19,10 @@ use chrono::Datelike;
1919use chrono:: NaiveDate ;
2020use chrono:: NaiveDateTime ;
2121use chrono:: Timelike ;
22+ use chrono_tz:: Tz ;
2223use databend_common_exception:: ErrorCode ;
2324use databend_common_exception:: Result ;
2425use databend_common_exception:: ToErrorCode ;
25- use databend_common_timezone:: Tz ;
2626use databend_common_timezone:: fast_utc_from_local;
2727
2828use crate :: cursor_ext:: cursor_read_bytes_ext:: ReadBytesExt ;
@@ -65,7 +65,23 @@ fn days_from_epoch(date: &NaiveDate) -> i32 {
6565 . num_days ( ) as i32
6666}
6767
68- fn local_to_micros ( tz : & Tz , local : & NaiveDateTime , micro : u32 ) -> Option < i64 > {
68+ fn local_to_micros_checked (
69+ tz : & Tz ,
70+ local : & NaiveDateTime ,
71+ micro : u32 ,
72+ provided_offset : Option < i32 > ,
73+ ) -> Result < i64 > {
74+ // Explicit offsets are independent of the session timezone and its DST gaps.
75+ if let Some ( offset) = provided_offset {
76+ return local
77+ . and_utc ( )
78+ . timestamp ( )
79+ . checked_sub ( i64:: from ( offset) )
80+ . and_then ( |seconds| seconds. checked_mul ( MICROS_PER_SEC ) )
81+ . and_then ( |micros| micros. checked_add ( i64:: from ( micro) ) )
82+ . ok_or_else ( || ErrorCode :: BadBytes ( "Datetime offset adjustment overflowed" ) ) ;
83+ }
84+
6985 fast_utc_from_local (
7086 tz,
7187 local. year ( ) ,
@@ -76,28 +92,14 @@ fn local_to_micros(tz: &Tz, local: &NaiveDateTime, micro: u32) -> Option<i64> {
7692 local. second ( ) as u8 ,
7793 micro,
7894 )
79- }
80-
81- fn local_to_micros_checked ( tz : & Tz , local : & NaiveDateTime , micro : u32 ) -> Result < i64 > {
82- local_to_micros ( tz, local, micro) . ok_or_else ( || {
95+ . ok_or_else ( || {
8396 ErrorCode :: BadBytes ( format ! (
8497 "Invalid local datetime {} for timezone {tz}" ,
8598 local. format( "%Y-%m-%d %H:%M:%S" )
8699 ) )
87100 } )
88101}
89102
90- /// Explicit offsets are independent of the session timezone and its DST gaps.
91- fn micros_with_offset ( local : & NaiveDateTime , micro : u32 , offset : i32 ) -> Result < i64 > {
92- local
93- . and_utc ( )
94- . timestamp ( )
95- . checked_sub ( i64:: from ( offset) )
96- . and_then ( |seconds| seconds. checked_mul ( MICROS_PER_SEC ) )
97- . and_then ( |micros| micros. checked_add ( i64:: from ( micro) ) )
98- . ok_or_else ( || ErrorCode :: BadBytes ( "Datetime offset adjustment overflowed" ) )
99- }
100-
101103fn try_read_standard_timestamp < T : AsRef < [ u8 ] > > (
102104 cursor : & mut Cursor < T > ,
103105 tz : & Tz ,
@@ -183,11 +185,7 @@ fn build_best_effort_result(
183185 ) )
184186 } ) ?;
185187
186- let micros = if let Some ( offset) = provided_offset {
187- micros_with_offset ( & local, micro, offset) ?
188- } else {
189- local_to_micros_checked ( tz, & local, micro) ?
190- } ;
188+ let micros = local_to_micros_checked ( tz, & local, micro, provided_offset) ?;
191189 Ok ( DateTimeResType :: Datetime ( micros) )
192190}
193191
@@ -306,15 +304,14 @@ where T: AsRef<[u8]>
306304 v = "1970-01-01" ;
307305 }
308306
309- let d = NaiveDate :: parse_from_str ( v , "%Y-%m-%d" ) . map_err_to_code (
310- ErrorCode :: BadBytes ,
311- || {
307+ let d = v
308+ . parse :: < NaiveDate > ( )
309+ . map_err_to_code ( ErrorCode :: BadBytes , || {
312310 format ! (
313311 "Date Parsing Error: The value '{}' could not be parsed into a valid Date" ,
314312 v
315313 )
316- } ,
317- ) ?;
314+ } ) ?;
318315 check_input_year ( d. year ( ) ) ?;
319316
320317 buf. clear ( ) ;
@@ -325,7 +322,7 @@ where T: AsRef<[u8]>
325322 }
326323 let midnight = d. and_hms_opt ( 0 , 0 , 0 ) . expect ( "midnight is valid" ) ;
327324 return Ok ( DateTimeResType :: Datetime ( local_to_micros_checked (
328- tz, & midnight, 0 ,
325+ tz, & midnight, 0 , None ,
329326 ) ?) ) ;
330327 }
331328
@@ -360,7 +357,7 @@ where T: AsRef<[u8]>
360357 return Ok ( DateTimeResType :: Date ( days_from_epoch ( & d) ) ) ;
361358 }
362359 return Ok ( DateTimeResType :: Datetime ( local_to_micros_checked (
363- tz, & local, 0 ,
360+ tz, & local, 0 , None ,
364361 ) ?) ) ;
365362 }
366363
@@ -402,11 +399,7 @@ where T: AsRef<[u8]>
402399 return Ok ( DateTimeResType :: Date ( days_from_epoch ( & d) ) ) ;
403400 }
404401
405- let micros = if let Some ( offset) = explicit_offset {
406- micros_with_offset ( & local, micro, offset) ?
407- } else {
408- local_to_micros_checked ( tz, & local, micro) ?
409- } ;
402+ let micros = local_to_micros_checked ( tz, & local, micro, explicit_offset) ?;
410403 Ok ( DateTimeResType :: Datetime ( micros) )
411404 }
412405}
0 commit comments