From c7af4b1181d67a045b560ae4cddcdd5e30dfdf9f Mon Sep 17 00:00:00 2001 From: Matthew Kim <38759997+friendlymatthew@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:27:38 -0500 Subject: [PATCH 1/3] Date can cast to tz-aware timestamp --- arrow-cast/src/cast/mod.rs | 95 ++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs index f0e7de056ea2..b2d3c83e4729 100644 --- a/arrow-cast/src/cast/mod.rs +++ b/arrow-cast/src/cast/mod.rs @@ -265,8 +265,8 @@ pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool { } (Timestamp(_, _), _) if to_type.is_numeric() => true, (_, Timestamp(_, _)) if from_type.is_numeric() => true, - (Date64, Timestamp(_, None)) => true, - (Date32, Timestamp(_, None)) => true, + (Date64, Timestamp(_, _)) => true, + (Date32, Timestamp(_, _)) => true, ( Timestamp(_, _), Timestamp(_, _) @@ -1806,43 +1806,54 @@ pub fn cast_with_options( })?, )) } - (Date64, Timestamp(TimeUnit::Second, None)) => Ok(Arc::new( + (Date64, Timestamp(TimeUnit::Second, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampSecondType>(|x| x / MILLISECONDS), + .unary::<_, TimestampSecondType>(|x| x / MILLISECONDS) + .with_timezone_opt(to_tz.clone()), )), - (Date64, Timestamp(TimeUnit::Millisecond, None)) => { - cast_reinterpret_arrays::(array) - } - (Date64, Timestamp(TimeUnit::Microsecond, None)) => Ok(Arc::new( + (Date64, Timestamp(TimeUnit::Millisecond, to_tz)) => Ok(Arc::new( + array + .as_primitive::() + .reinterpret_cast::() + .with_timezone_opt(to_tz.clone()), + )), + + (Date64, Timestamp(TimeUnit::Microsecond, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampMicrosecondType>(|x| x * (MICROSECONDS / MILLISECONDS)), + .unary::<_, TimestampMicrosecondType>(|x| x * (MICROSECONDS / MILLISECONDS)) + .with_timezone_opt(to_tz.clone()), )), - (Date64, Timestamp(TimeUnit::Nanosecond, None)) => Ok(Arc::new( + (Date64, Timestamp(TimeUnit::Nanosecond, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampNanosecondType>(|x| x * (NANOSECONDS / MILLISECONDS)), + .unary::<_, TimestampNanosecondType>(|x| x * (NANOSECONDS / MILLISECONDS)) + .with_timezone_opt(to_tz.clone()), )), - (Date32, Timestamp(TimeUnit::Second, None)) => Ok(Arc::new( + (Date32, Timestamp(TimeUnit::Second, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampSecondType>(|x| (x as i64) * SECONDS_IN_DAY), + .unary::<_, TimestampSecondType>(|x| (x as i64) * SECONDS_IN_DAY) + .with_timezone_opt(to_tz.clone()), )), - (Date32, Timestamp(TimeUnit::Millisecond, None)) => Ok(Arc::new( + (Date32, Timestamp(TimeUnit::Millisecond, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampMillisecondType>(|x| (x as i64) * MILLISECONDS_IN_DAY), + .unary::<_, TimestampMillisecondType>(|x| (x as i64) * MILLISECONDS_IN_DAY) + .with_timezone_opt(to_tz.clone()), )), - (Date32, Timestamp(TimeUnit::Microsecond, None)) => Ok(Arc::new( + (Date32, Timestamp(TimeUnit::Microsecond, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampMicrosecondType>(|x| (x as i64) * MICROSECONDS_IN_DAY), + .unary::<_, TimestampMicrosecondType>(|x| (x as i64) * MICROSECONDS_IN_DAY) + .with_timezone_opt(to_tz.clone()), )), - (Date32, Timestamp(TimeUnit::Nanosecond, None)) => Ok(Arc::new( + (Date32, Timestamp(TimeUnit::Nanosecond, to_tz)) => Ok(Arc::new( array .as_primitive::() - .unary::<_, TimestampNanosecondType>(|x| (x as i64) * NANOSECONDS_IN_DAY), + .unary::<_, TimestampNanosecondType>(|x| (x as i64) * NANOSECONDS_IN_DAY) + .with_timezone_opt(to_tz.clone()), )), (_, Duration(unit)) if from_type.is_numeric() => { @@ -5217,6 +5228,52 @@ mod tests { }}; } + #[test] + fn test_cast_date64_to_timestamp_with_timezone() { + let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]); + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Millisecond, Some(tz.into())), + ) + .unwrap(); + + let c = b.as_primitive::(); + assert_eq!(864000000005, c.value(0)); + assert_eq!(1545696000001, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("1997-05-19 05:45:00.005000"), + Some("2018-12-25 05:45:00.001000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + #[test] fn test_cast_timestamp_to_strings() { // "2018-12-25T00:00:02.001", "1997-05-19T00:00:03.005", None From 1b47275e872bff2b3ca32341e415a4277ffa4f03 Mon Sep 17 00:00:00 2001 From: Matthew Kim <38759997+friendlymatthew@users.noreply.github.com> Date: Sun, 16 Feb 2025 12:28:33 -0500 Subject: [PATCH 2/3] Cover other Date x TimeUnit cases --- arrow-cast/src/cast/mod.rs | 322 +++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs index b2d3c83e4729..8c07e8c17c77 100644 --- a/arrow-cast/src/cast/mod.rs +++ b/arrow-cast/src/cast/mod.rs @@ -5228,8 +5228,238 @@ mod tests { }}; } + #[test] + fn test_cast_date32_to_timestamp_with_timezone() { + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1 + let array = Arc::new(a) as ArrayRef; + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Second, Some(tz.into())), + ) + .unwrap(); + let c = b.as_primitive::(); + assert_eq!(1609459200, c.value(0)); + assert_eq!(1640995200, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("2021-01-01 05:45:00.000000"), + Some("2022-01-01 05:45:00.000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + + #[test] + fn test_cast_date32_to_timestamp_with_timezone_ms() { + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1 + let array = Arc::new(a) as ArrayRef; + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Millisecond, Some(tz.into())), + ) + .unwrap(); + let c = b.as_primitive::(); + assert_eq!(1609459200000, c.value(0)); + assert_eq!(1640995200000, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("2021-01-01 05:45:00.000000"), + Some("2022-01-01 05:45:00.000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + + #[test] + fn test_cast_date32_to_timestamp_with_timezone_us() { + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1 + let array = Arc::new(a) as ArrayRef; + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Microsecond, Some(tz.into())), + ) + .unwrap(); + let c = b.as_primitive::(); + assert_eq!(1609459200000000, c.value(0)); + assert_eq!(1640995200000000, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("2021-01-01 05:45:00.000000000"), + Some("2022-01-01 05:45:00.000000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + + #[test] + fn test_cast_date32_to_timestamp_with_timezone_ns() { + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1 + let array = Arc::new(a) as ArrayRef; + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Nanosecond, Some(tz.into())), + ) + .unwrap(); + let c = b.as_primitive::(); + assert_eq!(1609459200000000000, c.value(0)); + assert_eq!(1640995200000000000, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("2021-01-01 05:45:00.000000000"), + Some("2022-01-01 05:45:00.000000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + #[test] fn test_cast_date64_to_timestamp_with_timezone() { + let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]); + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Second, Some(tz.into())), + ) + .unwrap(); + + let c = b.as_primitive::(); + assert_eq!(864000000, c.value(0)); + assert_eq!(1545696000, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("1997-05-19 05:45:00.000000"), + Some("2018-12-25 05:45:00.000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + + #[test] + fn test_cast_date64_to_timestamp_with_timezone_ms() { let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]); let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu let b = cast( @@ -5243,6 +5473,52 @@ mod tests { assert_eq!(1545696000001, c.value(1)); assert!(c.is_null(2)); + let expected = vec![ + Some("1997-05-19 05:45:00.005"), + Some("2018-12-25 05:45:00.001"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.3f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + + #[test] + fn test_cast_date64_to_timestamp_with_timezone_us() { + let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]); + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Microsecond, Some(tz.into())), + ) + .unwrap(); + + let c = b.as_primitive::(); + assert_eq!(864000000005000, c.value(0)); + assert_eq!(1545696000001000, c.value(1)); + assert!(c.is_null(2)); + let expected = vec![ Some("1997-05-19 05:45:00.005000"), Some("2018-12-25 05:45:00.001000"), @@ -5274,6 +5550,52 @@ mod tests { ); } + #[test] + fn test_cast_date64_to_timestamp_with_timezone_ns() { + let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]); + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Nanosecond, Some(tz.into())), + ) + .unwrap(); + + let c = b.as_primitive::(); + assert_eq!(864000000005000000, c.value(0)); + assert_eq!(1545696000001000000, c.value(1)); + assert!(c.is_null(2)); + + let expected = vec![ + Some("1997-05-19 05:45:00.005000000"), + Some("2018-12-25 05:45:00.001000000"), + None, + ]; + + let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; + let cast_options = CastOptions { + safe: true, + format_options: FormatOptions::default() + .with_timestamp_format(Some(ts_format)) + .with_timestamp_tz_format(Some(ts_format)), + }; + + assert_cast_timestamp_to_string!( + c, + DataType::Utf8View, + StringViewArray, + cast_options, + expected + ); + assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); + assert_cast_timestamp_to_string!( + c, + DataType::LargeUtf8, + LargeStringArray, + cast_options, + expected + ); + } + #[test] fn test_cast_timestamp_to_strings() { // "2018-12-25T00:00:02.001", "1997-05-19T00:00:03.005", None From 7828b6d27536de01b0498779ae1e3794267a1c76 Mon Sep 17 00:00:00 2001 From: Matthew Kim <38759997+friendlymatthew@users.noreply.github.com> Date: Wed, 19 Feb 2025 14:03:47 -0500 Subject: [PATCH 3/3] Preserve local time when casting date to timestamp --- arrow-cast/src/cast/mod.rs | 407 +++++++++++-------------------------- 1 file changed, 119 insertions(+), 288 deletions(-) diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs index 8c07e8c17c77..f96bd6eda4ea 100644 --- a/arrow-cast/src/cast/mod.rs +++ b/arrow-cast/src/cast/mod.rs @@ -1806,55 +1806,63 @@ pub fn cast_with_options( })?, )) } - (Date64, Timestamp(TimeUnit::Second, to_tz)) => Ok(Arc::new( - array + (Date64, Timestamp(TimeUnit::Second, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampSecondType>(|x| x / MILLISECONDS) - .with_timezone_opt(to_tz.clone()), - )), - (Date64, Timestamp(TimeUnit::Millisecond, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampSecondType>(|x| x / MILLISECONDS); + + cast_with_options(&array, to_type, cast_options) + } + (Date64, Timestamp(TimeUnit::Millisecond, _)) => { + let array = array .as_primitive::() - .reinterpret_cast::() - .with_timezone_opt(to_tz.clone()), - )), + .reinterpret_cast::(); - (Date64, Timestamp(TimeUnit::Microsecond, to_tz)) => Ok(Arc::new( - array + cast_with_options(&array, to_type, cast_options) + } + + (Date64, Timestamp(TimeUnit::Microsecond, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampMicrosecondType>(|x| x * (MICROSECONDS / MILLISECONDS)) - .with_timezone_opt(to_tz.clone()), - )), - (Date64, Timestamp(TimeUnit::Nanosecond, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampMicrosecondType>(|x| x * (MICROSECONDS / MILLISECONDS)); + + cast_with_options(&array, to_type, cast_options) + } + (Date64, Timestamp(TimeUnit::Nanosecond, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampNanosecondType>(|x| x * (NANOSECONDS / MILLISECONDS)) - .with_timezone_opt(to_tz.clone()), - )), - (Date32, Timestamp(TimeUnit::Second, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampNanosecondType>(|x| x * (NANOSECONDS / MILLISECONDS)); + + cast_with_options(&array, to_type, cast_options) + } + (Date32, Timestamp(TimeUnit::Second, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampSecondType>(|x| (x as i64) * SECONDS_IN_DAY) - .with_timezone_opt(to_tz.clone()), - )), - (Date32, Timestamp(TimeUnit::Millisecond, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampSecondType>(|x| (x as i64) * SECONDS_IN_DAY); + + cast_with_options(&array, to_type, cast_options) + } + (Date32, Timestamp(TimeUnit::Millisecond, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampMillisecondType>(|x| (x as i64) * MILLISECONDS_IN_DAY) - .with_timezone_opt(to_tz.clone()), - )), - (Date32, Timestamp(TimeUnit::Microsecond, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampMillisecondType>(|x| (x as i64) * MILLISECONDS_IN_DAY); + + cast_with_options(&array, to_type, cast_options) + } + (Date32, Timestamp(TimeUnit::Microsecond, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampMicrosecondType>(|x| (x as i64) * MICROSECONDS_IN_DAY) - .with_timezone_opt(to_tz.clone()), - )), - (Date32, Timestamp(TimeUnit::Nanosecond, to_tz)) => Ok(Arc::new( - array + .unary::<_, TimestampMicrosecondType>(|x| (x as i64) * MICROSECONDS_IN_DAY); + + cast_with_options(&array, to_type, cast_options) + } + (Date32, Timestamp(TimeUnit::Nanosecond, _)) => { + let array = array .as_primitive::() - .unary::<_, TimestampNanosecondType>(|x| (x as i64) * NANOSECONDS_IN_DAY) - .with_timezone_opt(to_tz.clone()), - )), + .unary::<_, TimestampNanosecondType>(|x| (x as i64) * NANOSECONDS_IN_DAY); + + cast_with_options(&array, to_type, cast_options) + } (_, Duration(unit)) if from_type.is_numeric() => { let array = cast_with_options(array, &Int64, cast_options)?; @@ -5228,6 +5236,29 @@ mod tests { }}; } + #[test] + fn test_cast_date32_to_timestamp_and_timestamp_with_timezone() { + let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu + let a = Date32Array::from(vec![Some(18628), None, None]); // 2021-1-1, 2022-1-1 + let array = Arc::new(a) as ArrayRef; + + let b = cast( + &array, + &DataType::Timestamp(TimeUnit::Second, Some(tz.into())), + ) + .unwrap(); + let c = b.as_primitive::(); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00+05:45", result.value(0)); + + let b = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap(); + let c = b.as_primitive::(); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00", result.value(0)); + } + #[test] fn test_cast_date32_to_timestamp_with_timezone() { let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu @@ -5239,39 +5270,14 @@ mod tests { ) .unwrap(); let c = b.as_primitive::(); - assert_eq!(1609459200, c.value(0)); - assert_eq!(1640995200, c.value(1)); + assert_eq!(1609438500, c.value(0)); + assert_eq!(1640974500, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("2021-01-01 05:45:00.000000"), - Some("2022-01-01 05:45:00.000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00+05:45", result.value(0)); + assert_eq!("2022-01-01T00:00:00+05:45", result.value(1)); } #[test] @@ -5285,39 +5291,14 @@ mod tests { ) .unwrap(); let c = b.as_primitive::(); - assert_eq!(1609459200000, c.value(0)); - assert_eq!(1640995200000, c.value(1)); + assert_eq!(1609438500000, c.value(0)); + assert_eq!(1640974500000, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("2021-01-01 05:45:00.000000"), - Some("2022-01-01 05:45:00.000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00+05:45", result.value(0)); + assert_eq!("2022-01-01T00:00:00+05:45", result.value(1)); } #[test] @@ -5331,39 +5312,14 @@ mod tests { ) .unwrap(); let c = b.as_primitive::(); - assert_eq!(1609459200000000, c.value(0)); - assert_eq!(1640995200000000, c.value(1)); + assert_eq!(1609438500000000, c.value(0)); + assert_eq!(1640974500000000, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("2021-01-01 05:45:00.000000000"), - Some("2022-01-01 05:45:00.000000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00+05:45", result.value(0)); + assert_eq!("2022-01-01T00:00:00+05:45", result.value(1)); } #[test] @@ -5377,39 +5333,14 @@ mod tests { ) .unwrap(); let c = b.as_primitive::(); - assert_eq!(1609459200000000000, c.value(0)); - assert_eq!(1640995200000000000, c.value(1)); + assert_eq!(1609438500000000000, c.value(0)); + assert_eq!(1640974500000000000, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("2021-01-01 05:45:00.000000000"), - Some("2022-01-01 05:45:00.000000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("2021-01-01T00:00:00+05:45", result.value(0)); + assert_eq!("2022-01-01T00:00:00+05:45", result.value(1)); } #[test] @@ -5423,39 +5354,14 @@ mod tests { .unwrap(); let c = b.as_primitive::(); - assert_eq!(864000000, c.value(0)); - assert_eq!(1545696000, c.value(1)); + assert_eq!(863979300, c.value(0)); + assert_eq!(1545675300, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("1997-05-19 05:45:00.000000"), - Some("2018-12-25 05:45:00.000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("1997-05-19T00:00:00+05:45", result.value(0)); + assert_eq!("2018-12-25T00:00:00+05:45", result.value(1)); } #[test] @@ -5469,39 +5375,14 @@ mod tests { .unwrap(); let c = b.as_primitive::(); - assert_eq!(864000000005, c.value(0)); - assert_eq!(1545696000001, c.value(1)); + assert_eq!(863979300005, c.value(0)); + assert_eq!(1545675300001, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("1997-05-19 05:45:00.005"), - Some("2018-12-25 05:45:00.001"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.3f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0)); + assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1)); } #[test] @@ -5515,39 +5396,14 @@ mod tests { .unwrap(); let c = b.as_primitive::(); - assert_eq!(864000000005000, c.value(0)); - assert_eq!(1545696000001000, c.value(1)); + assert_eq!(863979300005000, c.value(0)); + assert_eq!(1545675300001000, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("1997-05-19 05:45:00.005000"), - Some("2018-12-25 05:45:00.001000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.6f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0)); + assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1)); } #[test] @@ -5561,39 +5417,14 @@ mod tests { .unwrap(); let c = b.as_primitive::(); - assert_eq!(864000000005000000, c.value(0)); - assert_eq!(1545696000001000000, c.value(1)); + assert_eq!(863979300005000000, c.value(0)); + assert_eq!(1545675300001000000, c.value(1)); assert!(c.is_null(2)); - let expected = vec![ - Some("1997-05-19 05:45:00.005000000"), - Some("2018-12-25 05:45:00.001000000"), - None, - ]; - - let ts_format = "%Y-%m-%d %H:%M:%S%.9f"; - let cast_options = CastOptions { - safe: true, - format_options: FormatOptions::default() - .with_timestamp_format(Some(ts_format)) - .with_timestamp_tz_format(Some(ts_format)), - }; - - assert_cast_timestamp_to_string!( - c, - DataType::Utf8View, - StringViewArray, - cast_options, - expected - ); - assert_cast_timestamp_to_string!(c, DataType::Utf8, StringArray, cast_options, expected); - assert_cast_timestamp_to_string!( - c, - DataType::LargeUtf8, - LargeStringArray, - cast_options, - expected - ); + let string_array = cast(&c, &DataType::Utf8).unwrap(); + let result = string_array.as_string::(); + assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0)); + assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1)); } #[test]