@@ -265,8 +265,8 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
265265 }
266266 ( Timestamp ( _, _) , _) if to_type. is_numeric ( ) => true ,
267267 ( _, Timestamp ( _, _) ) if from_type. is_numeric ( ) => true ,
268- ( Date64 , Timestamp ( _, None ) ) => true ,
269- ( Date32 , Timestamp ( _, None ) ) => true ,
268+ ( Date64 , Timestamp ( _, _ ) ) => true ,
269+ ( Date32 , Timestamp ( _, _ ) ) => true ,
270270 (
271271 Timestamp ( _, _) ,
272272 Timestamp ( _, _)
@@ -1806,43 +1806,54 @@ pub fn cast_with_options(
18061806 } ) ?,
18071807 ) )
18081808 }
1809- ( Date64 , Timestamp ( TimeUnit :: Second , None ) ) => Ok ( Arc :: new (
1809+ ( Date64 , Timestamp ( TimeUnit :: Second , to_tz ) ) => Ok ( Arc :: new (
18101810 array
18111811 . as_primitive :: < Date64Type > ( )
1812- . unary :: < _ , TimestampSecondType > ( |x| x / MILLISECONDS ) ,
1812+ . unary :: < _ , TimestampSecondType > ( |x| x / MILLISECONDS )
1813+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18131814 ) ) ,
1814- ( Date64 , Timestamp ( TimeUnit :: Millisecond , None ) ) => {
1815- cast_reinterpret_arrays :: < Date64Type , TimestampMillisecondType > ( array)
1816- }
1817- ( Date64 , Timestamp ( TimeUnit :: Microsecond , None ) ) => Ok ( Arc :: new (
1815+ ( Date64 , Timestamp ( TimeUnit :: Millisecond , to_tz) ) => Ok ( Arc :: new (
1816+ array
1817+ . as_primitive :: < Date64Type > ( )
1818+ . reinterpret_cast :: < TimestampMillisecondType > ( )
1819+ . with_timezone_opt ( to_tz. clone ( ) ) ,
1820+ ) ) ,
1821+
1822+ ( Date64 , Timestamp ( TimeUnit :: Microsecond , to_tz) ) => Ok ( Arc :: new (
18181823 array
18191824 . as_primitive :: < Date64Type > ( )
1820- . unary :: < _ , TimestampMicrosecondType > ( |x| x * ( MICROSECONDS / MILLISECONDS ) ) ,
1825+ . unary :: < _ , TimestampMicrosecondType > ( |x| x * ( MICROSECONDS / MILLISECONDS ) )
1826+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18211827 ) ) ,
1822- ( Date64 , Timestamp ( TimeUnit :: Nanosecond , None ) ) => Ok ( Arc :: new (
1828+ ( Date64 , Timestamp ( TimeUnit :: Nanosecond , to_tz ) ) => Ok ( Arc :: new (
18231829 array
18241830 . as_primitive :: < Date64Type > ( )
1825- . unary :: < _ , TimestampNanosecondType > ( |x| x * ( NANOSECONDS / MILLISECONDS ) ) ,
1831+ . unary :: < _ , TimestampNanosecondType > ( |x| x * ( NANOSECONDS / MILLISECONDS ) )
1832+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18261833 ) ) ,
1827- ( Date32 , Timestamp ( TimeUnit :: Second , None ) ) => Ok ( Arc :: new (
1834+ ( Date32 , Timestamp ( TimeUnit :: Second , to_tz ) ) => Ok ( Arc :: new (
18281835 array
18291836 . as_primitive :: < Date32Type > ( )
1830- . unary :: < _ , TimestampSecondType > ( |x| ( x as i64 ) * SECONDS_IN_DAY ) ,
1837+ . unary :: < _ , TimestampSecondType > ( |x| ( x as i64 ) * SECONDS_IN_DAY )
1838+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18311839 ) ) ,
1832- ( Date32 , Timestamp ( TimeUnit :: Millisecond , None ) ) => Ok ( Arc :: new (
1840+ ( Date32 , Timestamp ( TimeUnit :: Millisecond , to_tz ) ) => Ok ( Arc :: new (
18331841 array
18341842 . as_primitive :: < Date32Type > ( )
1835- . unary :: < _ , TimestampMillisecondType > ( |x| ( x as i64 ) * MILLISECONDS_IN_DAY ) ,
1843+ . unary :: < _ , TimestampMillisecondType > ( |x| ( x as i64 ) * MILLISECONDS_IN_DAY )
1844+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18361845 ) ) ,
1837- ( Date32 , Timestamp ( TimeUnit :: Microsecond , None ) ) => Ok ( Arc :: new (
1846+ ( Date32 , Timestamp ( TimeUnit :: Microsecond , to_tz ) ) => Ok ( Arc :: new (
18381847 array
18391848 . as_primitive :: < Date32Type > ( )
1840- . unary :: < _ , TimestampMicrosecondType > ( |x| ( x as i64 ) * MICROSECONDS_IN_DAY ) ,
1849+ . unary :: < _ , TimestampMicrosecondType > ( |x| ( x as i64 ) * MICROSECONDS_IN_DAY )
1850+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18411851 ) ) ,
1842- ( Date32 , Timestamp ( TimeUnit :: Nanosecond , None ) ) => Ok ( Arc :: new (
1852+ ( Date32 , Timestamp ( TimeUnit :: Nanosecond , to_tz ) ) => Ok ( Arc :: new (
18431853 array
18441854 . as_primitive :: < Date32Type > ( )
1845- . unary :: < _ , TimestampNanosecondType > ( |x| ( x as i64 ) * NANOSECONDS_IN_DAY ) ,
1855+ . unary :: < _ , TimestampNanosecondType > ( |x| ( x as i64 ) * NANOSECONDS_IN_DAY )
1856+ . with_timezone_opt ( to_tz. clone ( ) ) ,
18461857 ) ) ,
18471858
18481859 ( _, Duration ( unit) ) if from_type. is_numeric ( ) => {
@@ -5217,6 +5228,52 @@ mod tests {
52175228 } } ;
52185229 }
52195230
5231+ #[ test]
5232+ fn test_cast_date64_to_timestamp_with_timezone ( ) {
5233+ let array = Date64Array :: from ( vec ! [ Some ( 864000000005 ) , Some ( 1545696000001 ) , None ] ) ;
5234+ let tz = "+0545" ; // UTC + 0545 is Asia/Kathmandu
5235+ let b = cast (
5236+ & array,
5237+ & DataType :: Timestamp ( TimeUnit :: Millisecond , Some ( tz. into ( ) ) ) ,
5238+ )
5239+ . unwrap ( ) ;
5240+
5241+ let c = b. as_primitive :: < TimestampMillisecondType > ( ) ;
5242+ assert_eq ! ( 864000000005 , c. value( 0 ) ) ;
5243+ assert_eq ! ( 1545696000001 , c. value( 1 ) ) ;
5244+ assert ! ( c. is_null( 2 ) ) ;
5245+
5246+ let expected = vec ! [
5247+ Some ( "1997-05-19 05:45:00.005000" ) ,
5248+ Some ( "2018-12-25 05:45:00.001000" ) ,
5249+ None ,
5250+ ] ;
5251+
5252+ let ts_format = "%Y-%m-%d %H:%M:%S%.6f" ;
5253+ let cast_options = CastOptions {
5254+ safe : true ,
5255+ format_options : FormatOptions :: default ( )
5256+ . with_timestamp_format ( Some ( ts_format) )
5257+ . with_timestamp_tz_format ( Some ( ts_format) ) ,
5258+ } ;
5259+
5260+ assert_cast_timestamp_to_string ! (
5261+ c,
5262+ DataType :: Utf8View ,
5263+ StringViewArray ,
5264+ cast_options,
5265+ expected
5266+ ) ;
5267+ assert_cast_timestamp_to_string ! ( c, DataType :: Utf8 , StringArray , cast_options, expected) ;
5268+ assert_cast_timestamp_to_string ! (
5269+ c,
5270+ DataType :: LargeUtf8 ,
5271+ LargeStringArray ,
5272+ cast_options,
5273+ expected
5274+ ) ;
5275+ }
5276+
52205277 #[ test]
52215278 fn test_cast_timestamp_to_strings ( ) {
52225279 // "2018-12-25T00:00:02.001", "1997-05-19T00:00:03.005", None
0 commit comments