@@ -6,7 +6,7 @@ use crate::{
66 } ,
77} ;
88use anyhow:: { bail, Context , Result } ;
9- use chrono:: { DateTime , SecondsFormat , Utc } ;
9+ use chrono:: { DateTime , NaiveDateTime , SecondsFormat , TimeZone , Utc } ;
1010use itertools:: multizip;
1111use serde:: { Deserialize , Serialize } ;
1212use serde_json:: Value ;
@@ -27,13 +27,20 @@ pub fn transform_value(value: DBResponseValue, type_: &str) -> DBResponsePrimiti
2727 match value {
2828 DBResponseValue :: DateTime ( dt) if type_ == "time" || type_. is_empty ( ) => {
2929 let formatted = dt. to_rfc3339_opts ( SecondsFormat :: Millis , true ) ;
30- DBResponsePrimitive :: String ( formatted)
30+ DBResponsePrimitive :: String ( formatted. trim_end_matches ( 'Z' ) . to_string ( ) )
3131 }
3232 DBResponseValue :: Primitive ( DBResponsePrimitive :: String ( ref s) ) if type_ == "time" => {
3333 let formatted = DateTime :: parse_from_rfc3339 ( s)
3434 . map ( |dt| dt. to_rfc3339_opts ( SecondsFormat :: Millis , true ) )
35- . unwrap_or_else ( |_| s. clone ( ) ) ;
36- DBResponsePrimitive :: String ( formatted)
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 ( ) )
3744 }
3845 DBResponseValue :: Primitive ( p) => p,
3946 DBResponseValue :: Object { value } => value,
@@ -272,6 +279,8 @@ pub fn get_vanilla_row(
272279 . unwrap_or ( & "" . to_string ( ) ) ,
273280 ) ;
274281
282+ row. insert ( member_name. clone ( ) , transformed_value. clone ( ) ) ;
283+
275284 // Handle deprecated time dimensions without granularity
276285 let path: Vec < & str > = member_name. split ( MEMBER_SEPARATOR ) . collect ( ) ;
277286 let member_name_without_granularity =
@@ -284,8 +293,6 @@ pub fn get_vanilla_row(
284293 } )
285294 {
286295 row. insert ( member_name_without_granularity, transformed_value) ;
287- } else {
288- row. insert ( member_name. clone ( ) , transformed_value) ;
289296 }
290297 }
291298 }
@@ -605,12 +612,13 @@ impl Display for DBResponseValue {
605612#[ cfg( test) ]
606613mod tests {
607614 use super :: * ;
608- use chrono:: { TimeZone , Utc , Timelike } ;
609615 use anyhow:: Result ;
616+ use chrono:: { TimeZone , Timelike , Utc } ;
610617
611618 #[ test]
612619 fn test_transform_value_datetime_to_time ( ) {
613- let dt = Utc . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
620+ let dt = Utc
621+ . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
614622 . unwrap ( )
615623 . with_nanosecond ( 123_000_000 )
616624 . unwrap ( ) ;
@@ -619,13 +627,14 @@ mod tests {
619627
620628 assert_eq ! (
621629 result,
622- DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z " . to_string( ) )
630+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123 " . to_string( ) )
623631 ) ;
624632 }
625633
626634 #[ test]
627635 fn test_transform_value_datetime_empty_type ( ) {
628- let dt = Utc . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
636+ let dt = Utc
637+ . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
629638 . unwrap ( )
630639 . with_nanosecond ( 123_000_000 )
631640 . unwrap ( ) ;
@@ -634,30 +643,42 @@ mod tests {
634643
635644 assert_eq ! (
636645 result,
637- DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z " . to_string( ) )
646+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123 " . to_string( ) )
638647 ) ;
639648 }
640649
641650 #[ test]
642651 fn test_transform_value_string_to_time_valid_rfc3339 ( ) {
643652 let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
644- "2024-01-01T12:30:15.123Z " . to_string ( ) ,
653+ "2024-01-01T12:30:15.123 " . to_string ( ) ,
645654 ) ) ;
646655 let result = transform_value ( value, "time" ) ;
647656
648657 assert_eq ! (
649658 result,
650- DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z " . to_string( ) )
659+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123 " . to_string( ) )
651660 ) ;
652661 }
653662
654663 #[ test]
655- fn test_transform_value_string_to_time_invalid_rfc3339 ( ) {
664+ fn test_transform_value_string_wo_t_to_time_valid_rfc3339 ( ) {
656665 let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
657- "invalid-date " . to_string ( ) ,
666+ "2024-01-01 12:30:15.123 " . to_string ( ) ,
658667 ) ) ;
659668 let result = transform_value ( value, "time" ) ;
660669
670+ assert_eq ! (
671+ result,
672+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123" . to_string( ) )
673+ ) ;
674+ }
675+
676+ #[ test]
677+ fn test_transform_value_string_to_time_invalid_rfc3339 ( ) {
678+ let value =
679+ DBResponseValue :: Primitive ( DBResponsePrimitive :: String ( "invalid-date" . to_string ( ) ) ) ;
680+ let result = transform_value ( value, "time" ) ;
681+
661682 assert_eq ! (
662683 result,
663684 DBResponsePrimitive :: String ( "invalid-date" . to_string( ) )
@@ -666,9 +687,8 @@ mod tests {
666687
667688 #[ test]
668689 fn test_transform_value_primitive_string_type_not_time ( ) {
669- let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
670- "some-string" . to_string ( ) ,
671- ) ) ;
690+ let value =
691+ DBResponseValue :: Primitive ( DBResponsePrimitive :: String ( "some-string" . to_string ( ) ) ) ;
672692 let result = transform_value ( value, "other" ) ;
673693
674694 assert_eq ! (
@@ -680,7 +700,9 @@ mod tests {
680700 #[ test]
681701 fn test_transform_value_object ( ) {
682702 let obj_value = DBResponsePrimitive :: String ( "object-value" . to_string ( ) ) ;
683- let value = DBResponseValue :: Object { value : obj_value. clone ( ) } ;
703+ let value = DBResponseValue :: Object {
704+ value : obj_value. clone ( ) ,
705+ } ;
684706 let result = transform_value ( value, "time" ) ;
685707
686708 assert_eq ! ( result, obj_value) ;
@@ -891,5 +913,4 @@ mod tests {
891913 )
892914 ) ;
893915 }
894-
895916}
0 commit comments