@@ -6,7 +6,7 @@ use crate::{
66 } ,
77} ;
88use anyhow:: { bail, Context , Result } ;
9- use chrono:: { DateTime , NaiveDateTime , SecondsFormat , TimeZone , Utc } ;
9+ use chrono:: { DateTime , NaiveDateTime , TimeZone , Utc } ;
1010use itertools:: multizip;
1111use serde:: { Deserialize , Serialize } ;
1212use serde_json:: Value ;
@@ -26,21 +26,25 @@ pub const MEMBER_SEPARATOR: &str = ".";
2626pub fn transform_value ( value : DBResponseValue , type_ : & str ) -> DBResponsePrimitive {
2727 match value {
2828 DBResponseValue :: DateTime ( dt) if type_ == "time" || type_. is_empty ( ) => {
29- let formatted = dt. to_rfc3339_opts ( SecondsFormat :: Millis , true ) ;
30- DBResponsePrimitive :: String ( formatted. trim_end_matches ( 'Z' ) . to_string ( ) )
29+ DBResponsePrimitive :: String ( dt. with_timezone ( & Utc ) . format ( "%Y-%m-%dT%H:%M:%S%.3f" ) . to_string ( ) )
3130 }
3231 DBResponseValue :: Primitive ( DBResponsePrimitive :: String ( ref s) ) if type_ == "time" => {
3332 let formatted = DateTime :: parse_from_rfc3339 ( s)
34- . map ( |dt| dt. to_rfc3339_opts ( SecondsFormat :: Millis , true ) )
35- . unwrap_or_else ( |_| {
36- match NaiveDateTime :: parse_from_str ( s, "%Y-%m-%d %H:%M:%S%.3f" ) {
37- Ok ( dt) => Utc
38- . from_utc_datetime ( & dt)
39- . to_rfc3339_opts ( SecondsFormat :: Millis , true ) ,
40- Err ( _) => s. clone ( ) ,
41- }
42- } ) ;
43- DBResponsePrimitive :: String ( formatted. trim_end_matches ( 'Z' ) . to_string ( ) )
33+ . map ( |dt| dt. format ( "%Y-%m-%dT%H:%M:%S%.3f" ) . to_string ( ) )
34+ . or_else ( |_| {
35+ NaiveDateTime :: parse_from_str ( s, "%Y-%m-%d %H:%M:%S%.3f" )
36+ . map ( |dt| Utc . from_utc_datetime ( & dt) . format ( "%Y-%m-%dT%H:%M:%S%.3f" ) . to_string ( ) )
37+ } )
38+ . or_else ( |_| {
39+ NaiveDateTime :: parse_from_str ( s, "%Y-%m-%d %H:%M:%S%.3f %Z" )
40+ . map ( |dt| Utc . from_utc_datetime ( & dt) . format ( "%Y-%m-%dT%H:%M:%S%.3f" ) . to_string ( ) )
41+ } )
42+ . or_else ( |_| {
43+ NaiveDateTime :: parse_from_str ( s, "%Y-%m-%d %H:%M:%S%.3f %:z" )
44+ . map ( |dt| Utc . from_utc_datetime ( & dt) . format ( "%Y-%m-%dT%H:%M:%S%.3f" ) . to_string ( ) )
45+ } )
46+ . unwrap_or_else ( |_| s. clone ( ) ) ;
47+ DBResponsePrimitive :: String ( formatted)
4448 }
4549 DBResponseValue :: Primitive ( p) => p,
4650 DBResponseValue :: Object { value } => value,
@@ -673,6 +677,32 @@ mod tests {
673677 ) ;
674678 }
675679
680+ #[ test]
681+ fn test_transform_value_string_with_tz_offset_to_time_valid_rfc3339 ( ) {
682+ let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
683+ "2024-01-01 12:30:15.123 +00:00" . to_string ( ) ,
684+ ) ) ;
685+ let result = transform_value ( value, "time" ) ;
686+
687+ assert_eq ! (
688+ result,
689+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123" . to_string( ) )
690+ ) ;
691+ }
692+
693+ #[ test]
694+ fn test_transform_value_string_with_tz_to_time_valid_rfc3339 ( ) {
695+ let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
696+ "2024-01-01 12:30:15.123 UTC" . to_string ( ) ,
697+ ) ) ;
698+ let result = transform_value ( value, "time" ) ;
699+
700+ assert_eq ! (
701+ result,
702+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123" . to_string( ) )
703+ ) ;
704+ }
705+
676706 #[ test]
677707 fn test_transform_value_string_to_time_invalid_rfc3339 ( ) {
678708 let value =
0 commit comments