1515// specific language governing permissions and limitations
1616// under the License.
1717
18- use crate :: utils:: array_with_timezone;
1918use arrow:: compute:: { date_part, DatePart } ;
2019use arrow:: datatypes:: { DataType , TimeUnit :: Microsecond } ;
2120use datafusion:: common:: { internal_datafusion_err, DataFusionError } ;
@@ -24,6 +23,8 @@ use datafusion::logical_expr::{
2423} ;
2524use std:: { any:: Any , fmt:: Debug } ;
2625
26+ use crate :: utils:: array_with_timezone;
27+
2728macro_rules! extract_date_part {
2829 ( $struct_name: ident, $fn_name: expr, $date_part_variant: ident) => {
2930 #[ derive( Debug , PartialEq , Eq , Hash ) ]
@@ -75,14 +76,28 @@ macro_rules! extract_date_part {
7576
7677 match args {
7778 [ ColumnarValue :: Array ( array) ] => {
78- let array = array_with_timezone(
79- array,
80- self . timezone. clone( ) ,
81- Some ( & DataType :: Timestamp (
82- Microsecond ,
83- Some ( self . timezone. clone( ) . into( ) ) ,
84- ) ) ,
85- ) ?;
79+ let array = match array. data_type( ) {
80+ // TimestampNTZ → DO NOT apply timezone conversion
81+ DataType :: Timestamp ( _, None ) => array. clone( ) ,
82+
83+ // Timestamp with timezone → convert from UTC to session timezone
84+ DataType :: Timestamp ( _, Some ( _) ) => array_with_timezone(
85+ array,
86+ self . timezone. clone( ) ,
87+ Some ( & DataType :: Timestamp (
88+ Microsecond ,
89+ Some ( self . timezone. clone( ) . into( ) ) ,
90+ ) ) ,
91+ ) ?,
92+
93+ other => {
94+ return Err ( DataFusionError :: Execution ( format!(
95+ "extract_date_part expects a Timestamp input, got {:?}" ,
96+ other
97+ ) ) ) ;
98+ }
99+ } ;
100+
86101 let result = date_part( & array, DatePart :: $date_part_variant) ?;
87102 Ok ( ColumnarValue :: Array ( result) )
88103 }
0 commit comments