@@ -1064,8 +1064,19 @@ impl Unparser<'_> {
10641064 where
10651065 i64 : From < T :: Native > ,
10661066 {
1067+ let time_unit = match T :: DATA_TYPE {
1068+ DataType :: Timestamp ( unit, _) => unit,
1069+ _ => {
1070+ return Err ( internal_datafusion_err ! (
1071+ "Expected Timestamp, got {:?}" ,
1072+ T :: DATA_TYPE
1073+ ) )
1074+ }
1075+ } ;
1076+
10671077 let ts = if let Some ( tz) = tz {
1068- v. to_array ( ) ?
1078+ let dt = v
1079+ . to_array ( ) ?
10691080 . as_any ( )
10701081 . downcast_ref :: < PrimitiveArray < T > > ( )
10711082 . ok_or ( internal_datafusion_err ! (
@@ -1074,8 +1085,8 @@ impl Unparser<'_> {
10741085 . value_as_datetime_with_tz ( 0 , tz. parse ( ) ?)
10751086 . ok_or ( internal_datafusion_err ! (
10761087 "Unable to convert {v:?} to DateTime"
1077- ) ) ?
1078- . to_string ( )
1088+ ) ) ?;
1089+ self . dialect . timestamp_with_tz_to_string ( dt , time_unit )
10791090 } else {
10801091 v. to_array ( ) ?
10811092 . as_any ( )
@@ -1090,16 +1101,6 @@ impl Unparser<'_> {
10901101 . to_string ( )
10911102 } ;
10921103
1093- let time_unit = match T :: DATA_TYPE {
1094- DataType :: Timestamp ( unit, _) => unit,
1095- _ => {
1096- return Err ( internal_datafusion_err ! (
1097- "Expected Timestamp, got {:?}" ,
1098- T :: DATA_TYPE
1099- ) )
1100- }
1101- } ;
1102-
11031104 Ok ( ast:: Expr :: Cast {
11041105 kind : ast:: CastKind :: Cast ,
11051106 expr : Box :: new ( ast:: Expr :: value ( SingleQuotedString ( ts) ) ) ,
@@ -3219,4 +3220,81 @@ mod tests {
32193220
32203221 Ok ( ( ) )
32213222 }
3223+
3224+ #[ test]
3225+ fn test_timestamp_with_tz_format ( ) -> Result < ( ) > {
3226+ let default_dialect: Arc < dyn Dialect > =
3227+ Arc :: new ( CustomDialectBuilder :: new ( ) . build ( ) ) ;
3228+
3229+ let duckdb_dialect: Arc < dyn Dialect > = Arc :: new ( DuckDBDialect :: new ( ) ) ;
3230+
3231+ for ( dialect, scalar, expected) in [
3232+ (
3233+ Arc :: clone ( & default_dialect) ,
3234+ ScalarValue :: TimestampSecond ( Some ( 1757934000 ) , Some ( "+00:00" . into ( ) ) ) ,
3235+ "CAST('2025-09-15 11:00:00 +00:00' AS TIMESTAMP)" ,
3236+ ) ,
3237+ (
3238+ Arc :: clone ( & default_dialect) ,
3239+ ScalarValue :: TimestampMillisecond (
3240+ Some ( 1757934000123 ) ,
3241+ Some ( "+01:00" . into ( ) ) ,
3242+ ) ,
3243+ "CAST('2025-09-15 12:00:00.123 +01:00' AS TIMESTAMP)" ,
3244+ ) ,
3245+ (
3246+ Arc :: clone ( & default_dialect) ,
3247+ ScalarValue :: TimestampMicrosecond (
3248+ Some ( 1757934000123456 ) ,
3249+ Some ( "-01:00" . into ( ) ) ,
3250+ ) ,
3251+ "CAST('2025-09-15 10:00:00.123456 -01:00' AS TIMESTAMP)" ,
3252+ ) ,
3253+ (
3254+ Arc :: clone ( & default_dialect) ,
3255+ ScalarValue :: TimestampNanosecond (
3256+ Some ( 1757934000123456789 ) ,
3257+ Some ( "+00:00" . into ( ) ) ,
3258+ ) ,
3259+ "CAST('2025-09-15 11:00:00.123456789 +00:00' AS TIMESTAMP)" ,
3260+ ) ,
3261+ (
3262+ Arc :: clone ( & duckdb_dialect) ,
3263+ ScalarValue :: TimestampSecond ( Some ( 1757934000 ) , Some ( "+00:00" . into ( ) ) ) ,
3264+ "CAST('2025-09-15 11:00:00+00:00' AS TIMESTAMP)" ,
3265+ ) ,
3266+ (
3267+ Arc :: clone ( & duckdb_dialect) ,
3268+ ScalarValue :: TimestampMillisecond (
3269+ Some ( 1757934000123 ) ,
3270+ Some ( "+01:00" . into ( ) ) ,
3271+ ) ,
3272+ "CAST('2025-09-15 12:00:00.123+01:00' AS TIMESTAMP)" ,
3273+ ) ,
3274+ (
3275+ Arc :: clone ( & duckdb_dialect) ,
3276+ ScalarValue :: TimestampMicrosecond (
3277+ Some ( 1757934000123456 ) ,
3278+ Some ( "-01:00" . into ( ) ) ,
3279+ ) ,
3280+ "CAST('2025-09-15 10:00:00.123456-01:00' AS TIMESTAMP)" ,
3281+ ) ,
3282+ (
3283+ Arc :: clone ( & duckdb_dialect) ,
3284+ ScalarValue :: TimestampNanosecond (
3285+ Some ( 1757934000123456789 ) ,
3286+ Some ( "+00:00" . into ( ) ) ,
3287+ ) ,
3288+ "CAST('2025-09-15 11:00:00.123456789+00:00' AS TIMESTAMP)" ,
3289+ ) ,
3290+ ] {
3291+ let unparser = Unparser :: new ( dialect. as_ref ( ) ) ;
3292+
3293+ let expr = Expr :: Literal ( scalar, None ) ;
3294+
3295+ let actual = format ! ( "{}" , unparser. expr_to_sql( & expr) ?) ;
3296+ assert_eq ! ( actual, expected) ;
3297+ }
3298+ Ok ( ( ) )
3299+ }
32223300}
0 commit comments