Skip to main content

arrow_cast/cast/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5//! Cast kernels to convert [`ArrayRef`]  between supported datatypes.
6//!
7//! See [`cast_with_options`] for more information on specific conversions.
8//!
9//! Example:
10//!
11//! ```
12//! # use arrow_array::*;
13//! # use arrow_cast::cast;
14//! # use arrow_schema::DataType;
15//! # use std::sync::Arc;
16//! # use arrow_array::types::Float64Type;
17//! # use arrow_array::cast::AsArray;
18//! // int32 to float64
19//! let a = Int32Array::from(vec![5, 6, 7]);
20//! let b = cast(&a, &DataType::Float64).unwrap();
21//! let c = b.as_primitive::<Float64Type>();
22//! assert_eq!(5.0, c.value(0));
23//! assert_eq!(6.0, c.value(1));
24//! assert_eq!(7.0, c.value(2));
25//! ```
26
27mod binary;
28mod decimal;
29mod dictionary;
30mod list;
31mod map;
32mod numeric;
33mod run_array;
34mod string;
35mod structs;
36mod temporal;
37mod union;
38
39use crate::cast::binary::*;
40use crate::cast::decimal::*;
41use crate::cast::dictionary::*;
42use crate::cast::list::*;
43use crate::cast::map::*;
44pub(crate) use crate::cast::numeric::{
45    cast_bool_to_numeric, cast_numeric_arrays, cast_numeric_to_bool,
46};
47pub use crate::cast::numeric::{cast_num_to_bool, num_cast, single_bool_to_numeric};
48use crate::cast::run_array::*;
49use crate::cast::string::*;
50use crate::cast::structs::*;
51use crate::cast::temporal::*;
52pub use crate::cast::union::*;
53
54use chrono::{TimeZone, Utc};
55use std::cmp::Ordering;
56use std::sync::Arc;
57
58use crate::display::{ArrayFormatter, FormatOptions};
59use crate::parse::{
60    Parser, parse_interval_day_time, parse_interval_month_day_nano, parse_interval_year_month,
61    string_to_datetime,
62};
63use arrow_array::{builder::*, cast::*, temporal_conversions::*, timezone::Tz, types::*, *};
64use arrow_buffer::{ArrowNativeType, OffsetBuffer, i256};
65use arrow_data::ArrayData;
66use arrow_data::transform::MutableArrayData;
67use arrow_schema::*;
68use arrow_select::take::take;
69use num_traits::{NumCast, ToPrimitive, cast::AsPrimitive};
70
71pub use decimal::{DecimalCast, float_to_decimal, float_to_decimal_opt, rescale_decimal};
72#[expect(deprecated)]
73pub use decimal::{parse_string_to_decimal_native, single_float_to_decimal};
74pub use string::cast_single_string_to_boolean_default;
75
76/// Integers below 2^53 convert to an `f64` exactly.
77const F64_EXACT_INT_LIMIT: f64 = 9_007_199_254_740_992.0;
78/// Integers below 2^24 convert to an `f32` exactly.
79const F32_EXACT_INT_LIMIT: f64 = 16_777_216.0;
80
81/// Lossy conversion from decimal to float.
82///
83/// Returns the `f64` nearest to the decimal's exact value, rounding once, for any
84/// scale that fits in an `i8` -- as every Arrow decimal's does.
85///
86/// Conversion is lossy and follows standard floating point semantics. Values
87/// that exceed the representable range become `INFINITY` or `-INFINITY` without
88/// returning an error.
89#[inline(always)]
90pub fn single_decimal_to_float_lossy<D, F>(f: &F, x: D::Native, scale: i32) -> f64
91where
92    D: DecimalType,
93    F: Fn(D::Native) -> f64,
94{
95    let unscaled = f(x);
96    // Both operands are exact in this range, so this rounds once. A negative scale
97    // multiplies, since `10^-scale` is the exact power of ten there.
98    if (-22..=22).contains(&scale) && unscaled.abs() < F64_EXACT_INT_LIMIT {
99        return if scale >= 0 {
100            unscaled / 10_f64.powi(scale)
101        } else {
102            unscaled * 10_f64.powi(-scale)
103        };
104    }
105    match i8::try_from(scale) {
106        Ok(scale) => decimal_to_f64_rounded_once::<D>(x, scale, unscaled),
107        Err(_) => unscaled / 10_f64.powi(scale),
108    }
109}
110
111/// Rounds once for the values the arithmetic cannot convert exactly, by parsing
112/// the decimal's own text.
113#[cold]
114#[inline(never)]
115fn decimal_to_f64_rounded_once<D: DecimalType>(x: D::Native, scale: i8, unscaled: f64) -> f64 {
116    // `format_decimal` always writes a decimal literal, so the parse cannot fail.
117    // The fallback is there to keep that from being a panic, not because it runs.
118    D::format_decimal(x, u8::MAX, scale)
119        .parse::<f64>()
120        .unwrap_or_else(|_| unscaled / 10_f64.powi(scale.into()))
121}
122
123/// As [`decimal_to_f64_rounded_once`], but narrowing to `f32` in one step.
124/// Rounding to `f64` first and then to `f32` rounds twice: a decimal just above an
125/// `f32` midpoint can collapse onto that midpoint in `f64`, and round-half-even
126/// then sends it the wrong way.
127#[cold]
128#[inline(never)]
129fn decimal_to_f32_rounded_once<D: DecimalType>(x: D::Native, scale: i8, unscaled: f64) -> f32 {
130    // Unreachable, as in [`decimal_to_f64_rounded_once`].
131    D::format_decimal(x, u8::MAX, scale)
132        .parse::<f32>()
133        .unwrap_or_else(|_| unscaled as f32 / 10_f32.powi(scale.into()))
134}
135
136/// Casts a decimal array to `Float64`, rounding each value once.
137fn cast_decimal_to_f64<D, F>(
138    array: &dyn Array,
139    as_float: &F,
140    scale: i8,
141) -> Result<ArrayRef, ArrowError>
142where
143    D: DecimalType + ArrowPrimitiveType,
144    F: Fn(D::Native) -> f64,
145{
146    let array = array.as_primitive::<D>();
147    // No power of ten outside this range is exactly representable.
148    if !(-22..=22).contains(&scale) {
149        let values = array
150            .unary::<_, Float64Type>(|x| decimal_to_f64_rounded_once::<D>(x, scale, as_float(x)));
151        return Ok(Arc::new(values));
152    }
153    let pow = 10_f64.powi(scale.unsigned_abs().into());
154    let values = if scale >= 0 {
155        array.unary::<_, Float64Type>(|x| {
156            let unscaled = as_float(x);
157            if unscaled.abs() < F64_EXACT_INT_LIMIT {
158                unscaled / pow
159            } else {
160                decimal_to_f64_rounded_once::<D>(x, scale, unscaled)
161            }
162        })
163    } else {
164        array.unary::<_, Float64Type>(|x| {
165            let unscaled = as_float(x);
166            if unscaled.abs() < F64_EXACT_INT_LIMIT {
167                unscaled * pow
168            } else {
169                decimal_to_f64_rounded_once::<D>(x, scale, unscaled)
170            }
171        })
172    };
173    Ok(Arc::new(values))
174}
175
176/// Casts a decimal array to `Float32`, rounding each value once. Same shape as
177/// [`cast_decimal_to_f64`], with the smaller bounds an `f32` allows: integers are
178/// exact below 2^24, and `10^k` only up to `k = 10`.
179fn cast_decimal_to_f32<D, F>(
180    array: &dyn Array,
181    as_float: &F,
182    scale: i8,
183) -> Result<ArrayRef, ArrowError>
184where
185    D: DecimalType + ArrowPrimitiveType,
186    F: Fn(D::Native) -> f64,
187{
188    let array = array.as_primitive::<D>();
189    // No power of ten outside this range is exactly representable.
190    if !(-10..=10).contains(&scale) {
191        let values = array
192            .unary::<_, Float32Type>(|x| decimal_to_f32_rounded_once::<D>(x, scale, as_float(x)));
193        return Ok(Arc::new(values));
194    }
195    let pow = 10_f32.powi(scale.unsigned_abs().into());
196    let values = if scale >= 0 {
197        array.unary::<_, Float32Type>(|x| {
198            let unscaled = as_float(x);
199            if unscaled.abs() < F32_EXACT_INT_LIMIT {
200                unscaled as f32 / pow
201            } else {
202                decimal_to_f32_rounded_once::<D>(x, scale, unscaled)
203            }
204        })
205    } else {
206        array.unary::<_, Float32Type>(|x| {
207            let unscaled = as_float(x);
208            if unscaled.abs() < F32_EXACT_INT_LIMIT {
209                unscaled as f32 * pow
210            } else {
211                decimal_to_f32_rounded_once::<D>(x, scale, unscaled)
212            }
213        })
214    };
215    Ok(Arc::new(values))
216}
217
218/// CastOptions provides a way to override the default cast behaviors
219#[derive(Debug, Clone, PartialEq, Eq, Hash)]
220pub struct CastOptions<'a> {
221    /// how to handle cast failures, either return NULL (safe=true) or return ERR (safe=false)
222    pub safe: bool,
223    /// Formatting options when casting from temporal types to string
224    pub format_options: FormatOptions<'a>,
225}
226
227impl Default for CastOptions<'_> {
228    fn default() -> Self {
229        Self {
230            safe: true,
231            format_options: FormatOptions::default(),
232        }
233    }
234}
235
236/// Return true if a value of type `from_type` can be cast into a value of `to_type`.
237///
238/// See [`cast_with_options`] for more information
239pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
240    use self::DataType::*;
241    use self::IntervalUnit::*;
242    use self::TimeUnit::*;
243    if from_type == to_type {
244        return true;
245    }
246
247    match (from_type, to_type) {
248        (Null, _) => true,
249        // Dictionary/List conditions should be put in front of others
250        (Dictionary(_, from_value_type), Dictionary(_, to_value_type)) => {
251            can_cast_types(from_value_type, to_value_type)
252        }
253        (Dictionary(_, value_type), _) => can_cast_types(value_type, to_type),
254        (Union(fields, _), _) => union::resolve_child_array(fields, to_type).is_some(),
255        (_, Union(_, _)) => false,
256        (RunEndEncoded(_, value_type), _) => can_cast_types(value_type.data_type(), to_type),
257        (_, RunEndEncoded(_, value_type)) => can_cast_types(from_type, value_type.data_type()),
258        (_, Dictionary(_, value_type)) => can_cast_types(from_type, value_type),
259        (
260            List(list_from) | LargeList(list_from) | ListView(list_from) | LargeListView(list_from),
261            List(list_to) | LargeList(list_to) | ListView(list_to) | LargeListView(list_to),
262        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
263        (
264            List(list_from) | LargeList(list_from) | ListView(list_from) | LargeListView(list_from),
265            Utf8 | LargeUtf8 | Utf8View,
266        ) => can_cast_types(list_from.data_type(), to_type),
267        (
268            FixedSizeList(list_from, _),
269            List(list_to) | LargeList(list_to) | ListView(list_to) | LargeListView(list_to),
270        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
271        (
272            List(list_from) | LargeList(list_from) | ListView(list_from) | LargeListView(list_from),
273            FixedSizeList(list_to, _),
274        ) => can_cast_types(list_from.data_type(), list_to.data_type()),
275        (FixedSizeList(inner, size), FixedSizeList(inner_to, size_to)) if size == size_to => {
276            can_cast_types(inner.data_type(), inner_to.data_type())
277        }
278        (_, List(list_to) | LargeList(list_to) | ListView(list_to) | LargeListView(list_to)) => {
279            can_cast_types(from_type, list_to.data_type())
280        }
281        (_, FixedSizeList(list_to, size)) if *size == 1 => {
282            can_cast_types(from_type, list_to.data_type())
283        }
284        (FixedSizeList(list_from, size), _) if *size == 1 => {
285            can_cast_types(list_from.data_type(), to_type)
286        }
287        (Map(from_entries, ordered_from), Map(to_entries, ordered_to))
288            if ordered_from == ordered_to =>
289        {
290            match (
291                key_field(from_entries),
292                key_field(to_entries),
293                value_field(from_entries),
294                value_field(to_entries),
295            ) {
296                (Some(from_key), Some(to_key), Some(from_value), Some(to_value)) => {
297                    can_cast_types(from_key.data_type(), to_key.data_type())
298                        && can_cast_types(from_value.data_type(), to_value.data_type())
299                }
300                _ => false,
301            }
302        }
303        // cast one decimal type to another decimal type
304        (
305            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
306            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
307        ) => true,
308        // unsigned integer to decimal
309        (
310            UInt8 | UInt16 | UInt32 | UInt64,
311            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
312        ) => true,
313        // signed numeric to decimal
314        (
315            Int8 | Int16 | Int32 | Int64 | Float16 | Float32 | Float64,
316            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
317        ) => true,
318        // decimal to unsigned numeric
319        (
320            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
321            UInt8 | UInt16 | UInt32 | UInt64,
322        ) => true,
323        // decimal to signed numeric
324        (
325            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
326            Null | Int8 | Int16 | Int32 | Int64 | Float16 | Float32 | Float64,
327        ) => true,
328        // decimal to string
329        (
330            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
331            Utf8View | Utf8 | LargeUtf8,
332        ) => true,
333        // string to decimal
334        (
335            Utf8View | Utf8 | LargeUtf8,
336            Decimal32(_, _) | Decimal64(_, _) | Decimal128(_, _) | Decimal256(_, _),
337        ) => true,
338        (Struct(from_fields), Struct(to_fields)) => {
339            if from_fields.len() != to_fields.len() {
340                return false;
341            }
342
343            // fast path, all field names are in the same order and same number of fields
344            if from_fields
345                .iter()
346                .zip(to_fields.iter())
347                .all(|(f1, f2)| f1.name() == f2.name())
348            {
349                return from_fields.iter().zip(to_fields.iter()).all(|(f1, f2)| {
350                    // Assume that nullability between two structs are compatible, if not,
351                    // cast kernel will return error.
352                    can_cast_types(f1.data_type(), f2.data_type())
353                });
354            }
355
356            // slow path, we match the fields by name
357            if to_fields.iter().all(|to_field| {
358                from_fields
359                    .iter()
360                    .find(|from_field| from_field.name() == to_field.name())
361                    .is_some_and(|from_field| {
362                        // Assume that nullability between two structs are compatible, if not,
363                        // cast kernel will return error.
364                        can_cast_types(from_field.data_type(), to_field.data_type())
365                    })
366            }) {
367                return true;
368            }
369
370            // if we couldn't match by name, we try to see if they can be matched by position
371            from_fields
372                .iter()
373                .zip(to_fields.iter())
374                .all(|(f1, f2)| can_cast_types(f1.data_type(), f2.data_type()))
375        }
376        (Struct(_), _) => false,
377        (_, Struct(_)) => false,
378        (_, Boolean) => from_type.is_integer() || from_type.is_floating() || from_type.is_string(),
379        (Boolean, _) => to_type.is_integer() || to_type.is_floating() || to_type.is_string(),
380
381        (Binary, LargeBinary | Utf8 | LargeUtf8 | FixedSizeBinary(_) | BinaryView | Utf8View) => {
382            true
383        }
384        (LargeBinary, Binary | Utf8 | LargeUtf8 | FixedSizeBinary(_) | BinaryView | Utf8View) => {
385            true
386        }
387        (FixedSizeBinary(_), Binary | LargeBinary | BinaryView) => true,
388        (
389            Utf8 | LargeUtf8 | Utf8View,
390            Binary
391            | LargeBinary
392            | Utf8
393            | LargeUtf8
394            | Date32
395            | Date64
396            | Time32(Second | Millisecond)
397            | Time64(Microsecond | Nanosecond)
398            | Timestamp(Second | Millisecond | Microsecond | Nanosecond, _)
399            | Interval(_)
400            | BinaryView,
401        ) => true,
402        (Utf8 | LargeUtf8, Utf8View) => true,
403        (BinaryView, Binary | LargeBinary | Utf8 | LargeUtf8 | Utf8View) => true,
404        (Utf8View | Utf8 | LargeUtf8, _) => to_type.is_numeric(),
405        (_, Utf8 | Utf8View | LargeUtf8) => from_type.is_primitive(),
406
407        (_, Binary | LargeBinary) => from_type.is_integer(),
408
409        // start numeric casts
410        (
411            UInt8 | UInt16 | UInt32 | UInt64 | Int8 | Int16 | Int32 | Int64 | Float16 | Float32
412            | Float64,
413            UInt8 | UInt16 | UInt32 | UInt64 | Int8 | Int16 | Int32 | Int64 | Float16 | Float32
414            | Float64,
415        ) => true,
416        // end numeric casts
417
418        // temporal casts
419        (Int32, Date32 | Date64 | Time32(_)) => true,
420        (Date32, Int32 | Int64) => true,
421        (Time32(_), Int32 | Int64) => true,
422        (Int64, Date64 | Date32 | Time64(_)) => true,
423        (Date64, Int64 | Int32) => true,
424        (Time64(_), Int64) => true,
425        (Date32 | Date64, Date32 | Date64) => true,
426        // time casts
427        (Time32(_), Time32(_)) => true,
428        (Time32(_), Time64(_)) => true,
429        (Time64(_), Time64(_)) => true,
430        (Time64(_), Time32(to_unit)) => {
431            matches!(to_unit, Second | Millisecond)
432        }
433        (Timestamp(_, _), _) if to_type.is_numeric() => true,
434        (_, Timestamp(_, _)) if from_type.is_numeric() => true,
435        (Date64, Timestamp(_, _)) => true,
436        (Date32, Timestamp(_, _)) => true,
437        (
438            Timestamp(_, _),
439            Timestamp(_, _)
440            | Date32
441            | Date64
442            | Time32(Second | Millisecond)
443            | Time64(Microsecond | Nanosecond),
444        ) => true,
445        (_, Duration(_)) if from_type.is_numeric() => true,
446        (Duration(_), _) if to_type.is_numeric() => true,
447        (Duration(_), Duration(_)) => true,
448        // No `(Interval(_), Int64)` arm: `cast_with_options` implements no such cast.
449        (Int32, Interval(to_type)) => match to_type {
450            YearMonth => true,
451            DayTime => false,
452            MonthDayNano => false,
453        },
454        (Duration(_), Interval(MonthDayNano)) => true,
455        (Interval(MonthDayNano), Duration(_)) => true,
456        (Interval(YearMonth), Interval(MonthDayNano)) => true,
457        (Interval(DayTime), Interval(MonthDayNano)) => true,
458        (_, _) => false,
459    }
460}
461
462/// Cast `array` to the provided data type and return a new Array with type `to_type`, if possible.
463///
464/// See [`cast_with_options`] for more information.
465///
466/// # Errors
467///
468/// See [cast_with_options](cast_with_options#errors) for error conditions.
469pub fn cast(array: &dyn Array, to_type: &DataType) -> Result<ArrayRef, ArrowError> {
470    cast_with_options(array, to_type, &CastOptions::default())
471}
472
473/// Cast the primitive array using [`PrimitiveArray::reinterpret_cast`]
474fn cast_reinterpret_arrays<I: ArrowPrimitiveType, O: ArrowPrimitiveType<Native = I::Native>>(
475    array: &dyn Array,
476) -> Result<ArrayRef, ArrowError> {
477    Ok(Arc::new(array.as_primitive::<I>().reinterpret_cast::<O>()))
478}
479
480/// Try to cast `array` to `to_type` if possible.
481///
482/// Returns a new Array with type `to_type` if possible.
483///
484/// Accepts [`CastOptions`] to specify cast behavior. See also [`cast()`].
485///
486/// # Behavior
487/// * `Boolean` to `Utf8`, `LargeUtf8`, or `Utf8View`: `true` => `"true"`, `false` => `"false"`
488/// * `Utf8` to `Boolean`: `true`, `yes`, `on`, `1` => `true`, `false`, `no`, `off`, `0` => `false`,
489///   short variants are accepted, other strings return null or error
490/// * `Utf8` to Numeric: strings that can't be parsed to numbers return null, float strings
491///   in integer casts return null
492/// * Numeric to `Boolean`: 0 returns `false`, any other value returns `true`
493/// * `List` to `List`: the underlying data type is cast
494/// * `List` to `FixedSizeList`: the underlying data type is cast. If safe is true and a list element
495///   has the wrong length it will be replaced with NULL, otherwise an error will be returned
496/// * Primitive to `List`: a list array with 1 value per slot is created
497/// * `Date32` and `Date64`: precision lost when going to higher interval
498/// * `Time32` and `Time64`: precision lost when going to higher interval
499/// * `Timestamp` and `Date{32|64}`: precision lost when going to higher interval
500/// * `Timestamp` to `Date32`, `Time32`, or `Time64`: timestamps without a timezone
501///   support the full `i64` range; timestamps with a timezone must lie within Chrono's
502///   date range. If safe is true, a timestamp outside that range or a `Date32` day
503///   count that does not fit in `i32` becomes NULL, otherwise an error is returned
504/// * Temporal to/from backing Primitive: zero-copy with data type change
505/// * `Float16/Float32/Float64` to `Decimal(precision, scale)` rounds to the `scale` decimals
506///   (i.e. casting `6.4999` to `Decimal(10, 1)` becomes `6.5`).
507/// * `Decimal` to `Float16/Float32/Float64` is lossy and values outside the representable
508///   range become `INFINITY` or `-INFINITY` without error.
509///
510/// Unsupported Casts (check with `can_cast_types` before calling):
511/// * To or from `StructArray`
512/// * `List` to `Primitive`
513/// * `Interval` and `Duration`
514///
515/// # Errors
516///
517/// Returns [`ArrowError::InvalidArgumentError`] when the conversion between the
518/// source and target types is unsupported, regardless of [`CastOptions::safe`].
519/// Use [`can_cast_types`] to check whether a conversion is supported.
520///
521/// [`ArrowError::CastError`] reports failures to convert input values, such as
522/// numeric overflow or invalid strings. See [`CastOptions::safe`] for whether
523/// failed conversions produce nulls or errors.
524///
525/// # Durations and Intervals
526///
527/// Casting integer types directly to interval types such as
528/// [`IntervalMonthDayNano`] is not supported because the meaning of the integer
529/// is ambiguous. For example, the integer  could represent either nanoseconds
530/// or months.
531///
532/// To cast an integer type to an interval type, first convert to a Duration
533/// type, and then cast that to the desired interval type.
534///
535/// For example, to convert an `Int64` representing nanoseconds to an
536/// `IntervalMonthDayNano` you would first convert the `Int64` to a
537/// `DurationNanoseconds`, and then cast that to `IntervalMonthDayNano`.
538///
539/// # Timestamps and Timezones
540///
541/// Timestamps are stored with an optional timezone in Arrow.
542///
543/// ## Casting timestamps to a timestamp without timezone / UTC
544/// ```
545/// # use arrow_array::Int64Array;
546/// # use arrow_array::types::TimestampSecondType;
547/// # use arrow_cast::{cast, display};
548/// # use arrow_array::cast::AsArray;
549/// # use arrow_schema::{DataType, TimeUnit};
550/// // can use "UTC" if chrono-tz feature is enabled, here use offset based timezone
551/// let data_type = DataType::Timestamp(TimeUnit::Second, None);
552/// let a = Int64Array::from(vec![1_000_000_000, 2_000_000_000, 3_000_000_000]);
553/// let b = cast(&a, &data_type).unwrap();
554/// let b = b.as_primitive::<TimestampSecondType>(); // downcast to result type
555/// assert_eq!(2_000_000_000, b.value(1)); // values are the same as the type has no timezone
556/// // use display to show them (note has no trailing Z)
557/// assert_eq!("2033-05-18T03:33:20", display::array_value_to_string(&b, 1).unwrap());
558/// ```
559///
560/// ## Casting timestamps to a timestamp with timezone
561///
562/// Similarly to the previous example, if you cast numeric values to a timestamp
563/// with timezone, the cast kernel will not change the underlying values
564/// but display and other functions will interpret them as being in the provided timezone.
565///
566/// ```
567/// # use arrow_array::Int64Array;
568/// # use arrow_array::types::TimestampSecondType;
569/// # use arrow_cast::{cast, display};
570/// # use arrow_array::cast::AsArray;
571/// # use arrow_schema::{DataType, TimeUnit};
572/// // can use "Americas/New_York" if chrono-tz feature is enabled, here use offset based timezone
573/// let data_type = DataType::Timestamp(TimeUnit::Second, Some("-05:00".into()));
574/// let a = Int64Array::from(vec![1_000_000_000, 2_000_000_000, 3_000_000_000]);
575/// let b = cast(&a, &data_type).unwrap();
576/// let b = b.as_primitive::<TimestampSecondType>(); // downcast to result type
577/// assert_eq!(2_000_000_000, b.value(1)); // values are still the same
578/// // displayed in the target timezone (note the offset -05:00)
579/// assert_eq!("2033-05-17T22:33:20-05:00", display::array_value_to_string(&b, 1).unwrap());
580/// ```
581/// # Casting timestamps without timezone to timestamps with timezone
582///
583/// When casting from a timestamp without timezone to a timestamp with
584/// timezone, the cast kernel interprets the timestamp values as being in
585/// the destination timezone and then adjusts the underlying value to UTC as required
586///
587/// However, note that when casting from a timestamp with timezone BACK to a
588/// timestamp without timezone the cast kernel does not adjust the values.
589///
590/// Thus round trip casting a timestamp without timezone to a timestamp with
591/// timezone and back to a timestamp without timezone results in different
592/// values than the starting values.
593///
594/// ```
595/// # use arrow_array::Int64Array;
596/// # use arrow_array::types::{TimestampSecondType};
597/// # use arrow_cast::{cast, display};
598/// # use arrow_array::cast::AsArray;
599/// # use arrow_schema::{DataType, TimeUnit};
600/// let data_type  = DataType::Timestamp(TimeUnit::Second, None);
601/// let data_type_tz = DataType::Timestamp(TimeUnit::Second, Some("-05:00".into()));
602/// let a = Int64Array::from(vec![1_000_000_000, 2_000_000_000, 3_000_000_000]);
603/// let b = cast(&a, &data_type).unwrap(); // cast to timestamp without timezone
604/// let b = b.as_primitive::<TimestampSecondType>(); // downcast to result type
605/// assert_eq!(2_000_000_000, b.value(1)); // values are still the same
606/// // displayed without a timezone (note lack of offset or Z)
607/// assert_eq!("2033-05-18T03:33:20", display::array_value_to_string(&b, 1).unwrap());
608///
609/// // Convert timestamps without a timezone to timestamps with a timezone
610/// let c = cast(&b, &data_type_tz).unwrap();
611/// let c = c.as_primitive::<TimestampSecondType>(); // downcast to result type
612/// assert_eq!(2_000_018_000, c.value(1)); // value has been adjusted by offset
613/// // displayed with the target timezone offset (-05:00)
614/// assert_eq!("2033-05-18T03:33:20-05:00", display::array_value_to_string(&c, 1).unwrap());
615///
616/// // Convert from timestamp with timezone back to timestamp without timezone
617/// let d = cast(&c, &data_type).unwrap();
618/// let d = d.as_primitive::<TimestampSecondType>(); // downcast to result type
619/// assert_eq!(2_000_018_000, d.value(1)); // value has not been adjusted
620/// // NOTE: the timestamp is adjusted (08:33:20 instead of 03:33:20 as in previous example)
621/// assert_eq!("2033-05-18T08:33:20", display::array_value_to_string(&d, 1).unwrap());
622/// ```
623pub fn cast_with_options(
624    array: &dyn Array,
625    to_type: &DataType,
626    cast_options: &CastOptions,
627) -> Result<ArrayRef, ArrowError> {
628    use DataType::*;
629    let from_type = array.data_type();
630    // clone array if types are the same
631    if from_type == to_type {
632        return Ok(make_array(array.to_data()));
633    }
634    match (from_type, to_type) {
635        (Null, _) => Ok(new_null_array(to_type, array.len())),
636        (RunEndEncoded(index_type, _), _) => match index_type.data_type() {
637            Int16 => run_end_encoded_cast::<Int16Type>(array, to_type, cast_options),
638            Int32 => run_end_encoded_cast::<Int32Type>(array, to_type, cast_options),
639            Int64 => run_end_encoded_cast::<Int64Type>(array, to_type, cast_options),
640            _ => Err(ArrowError::InvalidArgumentError(format!(
641                "Casting from run end encoded type {from_type:?} to {to_type:?} not supported",
642            ))),
643        },
644        (_, RunEndEncoded(index_type, value_type)) => {
645            let array_ref = make_array(array.to_data());
646            match index_type.data_type() {
647                Int16 => cast_to_run_end_encoded::<Int16Type>(
648                    &array_ref,
649                    value_type.data_type(),
650                    cast_options,
651                ),
652                Int32 => cast_to_run_end_encoded::<Int32Type>(
653                    &array_ref,
654                    value_type.data_type(),
655                    cast_options,
656                ),
657                Int64 => cast_to_run_end_encoded::<Int64Type>(
658                    &array_ref,
659                    value_type.data_type(),
660                    cast_options,
661                ),
662                _ => Err(ArrowError::InvalidArgumentError(format!(
663                    "Casting from type {from_type:?} to run end encoded type {to_type:?} not supported",
664                ))),
665            }
666        }
667        (Union(_, _), _) => union_extract_by_type(
668            array.as_any().downcast_ref::<UnionArray>().unwrap(),
669            to_type,
670            cast_options,
671        ),
672        (_, Union(_, _)) => Err(ArrowError::InvalidArgumentError(format!(
673            "Casting from {from_type} to {to_type} not supported"
674        ))),
675        (Dictionary(index_type, _), _) => match **index_type {
676            Int8 => dictionary_cast::<Int8Type>(array, to_type, cast_options),
677            Int16 => dictionary_cast::<Int16Type>(array, to_type, cast_options),
678            Int32 => dictionary_cast::<Int32Type>(array, to_type, cast_options),
679            Int64 => dictionary_cast::<Int64Type>(array, to_type, cast_options),
680            UInt8 => dictionary_cast::<UInt8Type>(array, to_type, cast_options),
681            UInt16 => dictionary_cast::<UInt16Type>(array, to_type, cast_options),
682            UInt32 => dictionary_cast::<UInt32Type>(array, to_type, cast_options),
683            UInt64 => dictionary_cast::<UInt64Type>(array, to_type, cast_options),
684            _ => Err(ArrowError::InvalidArgumentError(format!(
685                "Casting from dictionary type {from_type} to {to_type} not supported",
686            ))),
687        },
688        (_, Dictionary(index_type, value_type)) => match **index_type {
689            Int8 => cast_to_dictionary::<Int8Type>(array, value_type, cast_options),
690            Int16 => cast_to_dictionary::<Int16Type>(array, value_type, cast_options),
691            Int32 => cast_to_dictionary::<Int32Type>(array, value_type, cast_options),
692            Int64 => cast_to_dictionary::<Int64Type>(array, value_type, cast_options),
693            UInt8 => cast_to_dictionary::<UInt8Type>(array, value_type, cast_options),
694            UInt16 => cast_to_dictionary::<UInt16Type>(array, value_type, cast_options),
695            UInt32 => cast_to_dictionary::<UInt32Type>(array, value_type, cast_options),
696            UInt64 => cast_to_dictionary::<UInt64Type>(array, value_type, cast_options),
697            _ => Err(ArrowError::InvalidArgumentError(format!(
698                "Casting from type {from_type} to dictionary type {to_type} not supported",
699            ))),
700        },
701        // Casting between lists of same types (cast inner values)
702        (List(_), List(to)) => cast_list_values::<i32>(array, to, cast_options),
703        (LargeList(_), LargeList(to)) => cast_list_values::<i64>(array, to, cast_options),
704        (FixedSizeList(_, size_from), FixedSizeList(list_to, size_to)) => {
705            if size_from != size_to {
706                return Err(ArrowError::InvalidArgumentError(
707                    "cannot cast fixed-size-list to fixed-size-list with different size".into(),
708                ));
709            }
710            let array = array.as_fixed_size_list();
711            let values = cast_with_options(array.values(), list_to.data_type(), cast_options)?;
712            let nulls = array.nulls().cloned();
713            let len = array.len();
714            Ok(Arc::new(FixedSizeListArray::try_new_with_length(
715                list_to.clone(),
716                *size_from,
717                values,
718                nulls,
719                len,
720            )?))
721        }
722        (ListView(_), ListView(to)) => cast_list_view_values::<i32>(array, to, cast_options),
723        (LargeListView(_), LargeListView(to)) => {
724            cast_list_view_values::<i64>(array, to, cast_options)
725        }
726        // Casting between different types of lists
727        // List
728        (List(_), LargeList(list_to)) => cast_list::<i32, i64>(array, list_to, cast_options),
729        (List(_), FixedSizeList(field, size)) => {
730            cast_list_to_fixed_size_list::<i32>(array, field, *size, cast_options)
731        }
732        (List(_), ListView(list_to)) => {
733            cast_list_to_list_view::<i32, i32>(array, list_to, cast_options)
734        }
735        (List(_), LargeListView(list_to)) => {
736            cast_list_to_list_view::<i32, i64>(array, list_to, cast_options)
737        }
738        // LargeList
739        (LargeList(_), List(list_to)) => cast_list::<i64, i32>(array, list_to, cast_options),
740        (LargeList(_), FixedSizeList(field, size)) => {
741            cast_list_to_fixed_size_list::<i64>(array, field, *size, cast_options)
742        }
743        (LargeList(_), ListView(list_to)) => {
744            cast_list_to_list_view::<i64, i32>(array, list_to, cast_options)
745        }
746        (LargeList(_), LargeListView(list_to)) => {
747            cast_list_to_list_view::<i64, i64>(array, list_to, cast_options)
748        }
749        // ListView
750        (ListView(_), List(list_to)) => {
751            cast_list_view_to_list::<i32, Int32Type>(array, list_to, cast_options)
752        }
753        (ListView(_), LargeList(list_to)) => {
754            cast_list_view_to_list::<i32, Int64Type>(array, list_to, cast_options)
755        }
756        (ListView(_), LargeListView(list_to)) => {
757            cast_list_view::<i32, i64>(array, list_to, cast_options)
758        }
759        (ListView(_), FixedSizeList(field, size)) => {
760            cast_list_view_to_fixed_size_list::<i32>(array, field, *size, cast_options)
761        }
762        // LargeListView
763        (LargeListView(_), LargeList(list_to)) => {
764            cast_list_view_to_list::<i64, Int64Type>(array, list_to, cast_options)
765        }
766        (LargeListView(_), List(list_to)) => {
767            cast_list_view_to_list::<i64, Int32Type>(array, list_to, cast_options)
768        }
769        (LargeListView(_), ListView(list_to)) => {
770            cast_list_view::<i64, i32>(array, list_to, cast_options)
771        }
772        (LargeListView(_), FixedSizeList(field, size)) => {
773            cast_list_view_to_fixed_size_list::<i64>(array, field, *size, cast_options)
774        }
775        // FixedSizeList
776        (FixedSizeList(_, _), List(list_to)) => {
777            cast_fixed_size_list_to_list::<i32>(array, list_to, cast_options)
778        }
779        (FixedSizeList(_, _), LargeList(list_to)) => {
780            cast_fixed_size_list_to_list::<i64>(array, list_to, cast_options)
781        }
782        (FixedSizeList(_, _), ListView(list_to)) => {
783            cast_fixed_size_list_to_list_view::<i32>(array, list_to, cast_options)
784        }
785        (FixedSizeList(_, _), LargeListView(list_to)) => {
786            cast_fixed_size_list_to_list_view::<i64>(array, list_to, cast_options)
787        }
788        // List to/from other types
789        (FixedSizeList(_, size), _) if *size == 1 => {
790            cast_single_element_fixed_size_list_to_values(array, to_type, cast_options)
791        }
792        // NOTE: we could support FSL to string here too but might be confusing
793        //       since behaviour for size 1 would be different (see arm above)
794        (List(_) | LargeList(_) | ListView(_) | LargeListView(_), _) => match to_type {
795            Utf8 => value_to_string::<i32>(array, cast_options),
796            LargeUtf8 => value_to_string::<i64>(array, cast_options),
797            Utf8View => value_to_string_view(array, cast_options),
798            dt => Err(ArrowError::InvalidArgumentError(format!(
799                "Cannot cast LIST to non-list data type {dt}"
800            ))),
801        },
802        (_, List(to)) => cast_values_to_list::<i32>(array, to, cast_options),
803        (_, LargeList(to)) => cast_values_to_list::<i64>(array, to, cast_options),
804        (_, ListView(to)) => cast_values_to_list_view::<i32>(array, to, cast_options),
805        (_, LargeListView(to)) => cast_values_to_list_view::<i64>(array, to, cast_options),
806        (_, FixedSizeList(to, size)) if *size == 1 => {
807            let values = cast_with_options(array, to.data_type(), cast_options)?;
808            let list = FixedSizeListArray::try_new(to.clone(), 1, values, None)?;
809            Ok(Arc::new(list))
810        }
811        // Map
812        (Map(_, ordered1), Map(_, ordered2)) if ordered1 == ordered2 => {
813            cast_map_values(array.as_map(), to_type, cast_options, ordered1.to_owned())
814        }
815        // Decimal to decimal, same width
816        (Decimal32(p1, s1), Decimal32(p2, s2)) => {
817            cast_decimal_to_decimal_same_type::<Decimal32Type>(
818                array.as_primitive(),
819                *p1,
820                *s1,
821                *p2,
822                *s2,
823                cast_options,
824            )
825        }
826        (Decimal64(p1, s1), Decimal64(p2, s2)) => {
827            cast_decimal_to_decimal_same_type::<Decimal64Type>(
828                array.as_primitive(),
829                *p1,
830                *s1,
831                *p2,
832                *s2,
833                cast_options,
834            )
835        }
836        (Decimal128(p1, s1), Decimal128(p2, s2)) => {
837            cast_decimal_to_decimal_same_type::<Decimal128Type>(
838                array.as_primitive(),
839                *p1,
840                *s1,
841                *p2,
842                *s2,
843                cast_options,
844            )
845        }
846        (Decimal256(p1, s1), Decimal256(p2, s2)) => {
847            cast_decimal_to_decimal_same_type::<Decimal256Type>(
848                array.as_primitive(),
849                *p1,
850                *s1,
851                *p2,
852                *s2,
853                cast_options,
854            )
855        }
856        // Decimal to decimal, different width
857        (Decimal32(p1, s1), Decimal64(p2, s2)) => {
858            cast_decimal_to_decimal::<Decimal32Type, Decimal64Type>(
859                array.as_primitive(),
860                *p1,
861                *s1,
862                *p2,
863                *s2,
864                cast_options,
865            )
866        }
867        (Decimal32(p1, s1), Decimal128(p2, s2)) => {
868            cast_decimal_to_decimal::<Decimal32Type, Decimal128Type>(
869                array.as_primitive(),
870                *p1,
871                *s1,
872                *p2,
873                *s2,
874                cast_options,
875            )
876        }
877        (Decimal32(p1, s1), Decimal256(p2, s2)) => {
878            cast_decimal_to_decimal::<Decimal32Type, Decimal256Type>(
879                array.as_primitive(),
880                *p1,
881                *s1,
882                *p2,
883                *s2,
884                cast_options,
885            )
886        }
887        (Decimal64(p1, s1), Decimal32(p2, s2)) => {
888            cast_decimal_to_decimal::<Decimal64Type, Decimal32Type>(
889                array.as_primitive(),
890                *p1,
891                *s1,
892                *p2,
893                *s2,
894                cast_options,
895            )
896        }
897        (Decimal64(p1, s1), Decimal128(p2, s2)) => {
898            cast_decimal_to_decimal::<Decimal64Type, Decimal128Type>(
899                array.as_primitive(),
900                *p1,
901                *s1,
902                *p2,
903                *s2,
904                cast_options,
905            )
906        }
907        (Decimal64(p1, s1), Decimal256(p2, s2)) => {
908            cast_decimal_to_decimal::<Decimal64Type, Decimal256Type>(
909                array.as_primitive(),
910                *p1,
911                *s1,
912                *p2,
913                *s2,
914                cast_options,
915            )
916        }
917        (Decimal128(p1, s1), Decimal32(p2, s2)) => {
918            cast_decimal_to_decimal::<Decimal128Type, Decimal32Type>(
919                array.as_primitive(),
920                *p1,
921                *s1,
922                *p2,
923                *s2,
924                cast_options,
925            )
926        }
927        (Decimal128(p1, s1), Decimal64(p2, s2)) => {
928            cast_decimal_to_decimal::<Decimal128Type, Decimal64Type>(
929                array.as_primitive(),
930                *p1,
931                *s1,
932                *p2,
933                *s2,
934                cast_options,
935            )
936        }
937        (Decimal128(p1, s1), Decimal256(p2, s2)) => {
938            cast_decimal_to_decimal::<Decimal128Type, Decimal256Type>(
939                array.as_primitive(),
940                *p1,
941                *s1,
942                *p2,
943                *s2,
944                cast_options,
945            )
946        }
947        (Decimal256(p1, s1), Decimal32(p2, s2)) => {
948            cast_decimal_to_decimal::<Decimal256Type, Decimal32Type>(
949                array.as_primitive(),
950                *p1,
951                *s1,
952                *p2,
953                *s2,
954                cast_options,
955            )
956        }
957        (Decimal256(p1, s1), Decimal64(p2, s2)) => {
958            cast_decimal_to_decimal::<Decimal256Type, Decimal64Type>(
959                array.as_primitive(),
960                *p1,
961                *s1,
962                *p2,
963                *s2,
964                cast_options,
965            )
966        }
967        (Decimal256(p1, s1), Decimal128(p2, s2)) => {
968            cast_decimal_to_decimal::<Decimal256Type, Decimal128Type>(
969                array.as_primitive(),
970                *p1,
971                *s1,
972                *p2,
973                *s2,
974                cast_options,
975            )
976        }
977        // Decimal to non-decimal
978        (Decimal32(_, scale), _) if !to_type.is_temporal() => {
979            cast_from_decimal::<Decimal32Type, _>(
980                array,
981                scale,
982                from_type,
983                to_type,
984                |x: i32| x as f64,
985                cast_options,
986            )
987        }
988        (Decimal64(_, scale), _) if !to_type.is_temporal() => {
989            cast_from_decimal::<Decimal64Type, _>(
990                array,
991                scale,
992                from_type,
993                to_type,
994                |x: i64| x as f64,
995                cast_options,
996            )
997        }
998        (Decimal128(_, scale), _) if !to_type.is_temporal() => {
999            cast_from_decimal::<Decimal128Type, _>(
1000                array,
1001                scale,
1002                from_type,
1003                to_type,
1004                |x: i128| x as f64,
1005                cast_options,
1006            )
1007        }
1008        (Decimal256(_, scale), _) if !to_type.is_temporal() => {
1009            cast_from_decimal::<Decimal256Type, _>(
1010                array,
1011                scale,
1012                from_type,
1013                to_type,
1014                |x: i256| x.to_f64().expect("All i256 values fit in f64"),
1015                cast_options,
1016            )
1017        }
1018        // Non-decimal to decimal
1019        (_, Decimal32(precision, scale)) if !from_type.is_temporal() => {
1020            cast_to_decimal::<Decimal32Type, _>(
1021                array,
1022                precision,
1023                scale,
1024                from_type,
1025                to_type,
1026                cast_options,
1027            )
1028        }
1029        (_, Decimal64(precision, scale)) if !from_type.is_temporal() => {
1030            cast_to_decimal::<Decimal64Type, _>(
1031                array,
1032                precision,
1033                scale,
1034                from_type,
1035                to_type,
1036                cast_options,
1037            )
1038        }
1039        (_, Decimal128(precision, scale)) if !from_type.is_temporal() => {
1040            cast_to_decimal::<Decimal128Type, _>(
1041                array,
1042                precision,
1043                scale,
1044                from_type,
1045                to_type,
1046                cast_options,
1047            )
1048        }
1049        (_, Decimal256(precision, scale)) if !from_type.is_temporal() => {
1050            cast_to_decimal::<Decimal256Type, _>(
1051                array,
1052                precision,
1053                scale,
1054                from_type,
1055                to_type,
1056                cast_options,
1057            )
1058        }
1059        (Struct(from_fields), Struct(to_fields)) => cast_struct_to_struct(
1060            array.as_struct(),
1061            from_fields.clone(),
1062            to_fields.clone(),
1063            cast_options,
1064        ),
1065        (Struct(_), _) => Err(ArrowError::InvalidArgumentError(format!(
1066            "Casting from {from_type} to {to_type} not supported"
1067        ))),
1068        (_, Struct(_)) => Err(ArrowError::InvalidArgumentError(format!(
1069            "Casting from {from_type} to {to_type} not supported"
1070        ))),
1071        (_, Boolean) => match from_type {
1072            UInt8 => cast_numeric_to_bool::<UInt8Type>(array),
1073            UInt16 => cast_numeric_to_bool::<UInt16Type>(array),
1074            UInt32 => cast_numeric_to_bool::<UInt32Type>(array),
1075            UInt64 => cast_numeric_to_bool::<UInt64Type>(array),
1076            Int8 => cast_numeric_to_bool::<Int8Type>(array),
1077            Int16 => cast_numeric_to_bool::<Int16Type>(array),
1078            Int32 => cast_numeric_to_bool::<Int32Type>(array),
1079            Int64 => cast_numeric_to_bool::<Int64Type>(array),
1080            Float16 => cast_numeric_to_bool::<Float16Type>(array),
1081            Float32 => cast_numeric_to_bool::<Float32Type>(array),
1082            Float64 => cast_numeric_to_bool::<Float64Type>(array),
1083            Utf8View => cast_utf8view_to_boolean(array, cast_options),
1084            Utf8 => cast_utf8_to_boolean::<i32>(array, cast_options),
1085            LargeUtf8 => cast_utf8_to_boolean::<i64>(array, cast_options),
1086            _ => Err(ArrowError::InvalidArgumentError(format!(
1087                "Casting from {from_type} to {to_type} not supported",
1088            ))),
1089        },
1090        (Boolean, _) => match to_type {
1091            UInt8 => cast_bool_to_numeric::<UInt8Type>(array, cast_options),
1092            UInt16 => cast_bool_to_numeric::<UInt16Type>(array, cast_options),
1093            UInt32 => cast_bool_to_numeric::<UInt32Type>(array, cast_options),
1094            UInt64 => cast_bool_to_numeric::<UInt64Type>(array, cast_options),
1095            Int8 => cast_bool_to_numeric::<Int8Type>(array, cast_options),
1096            Int16 => cast_bool_to_numeric::<Int16Type>(array, cast_options),
1097            Int32 => cast_bool_to_numeric::<Int32Type>(array, cast_options),
1098            Int64 => cast_bool_to_numeric::<Int64Type>(array, cast_options),
1099            Float16 => cast_bool_to_numeric::<Float16Type>(array, cast_options),
1100            Float32 => cast_bool_to_numeric::<Float32Type>(array, cast_options),
1101            Float64 => cast_bool_to_numeric::<Float64Type>(array, cast_options),
1102            Utf8View => cast_bool_to_string::<StringViewArray>(array),
1103            Utf8 => cast_bool_to_string::<StringArray>(array),
1104            LargeUtf8 => cast_bool_to_string::<LargeStringArray>(array),
1105            _ => Err(ArrowError::InvalidArgumentError(format!(
1106                "Casting from {from_type} to {to_type} not supported",
1107            ))),
1108        },
1109        (Utf8, _) => match to_type {
1110            UInt8 => parse_string::<UInt8Type, i32>(array, cast_options),
1111            UInt16 => parse_string::<UInt16Type, i32>(array, cast_options),
1112            UInt32 => parse_string::<UInt32Type, i32>(array, cast_options),
1113            UInt64 => parse_string::<UInt64Type, i32>(array, cast_options),
1114            Int8 => parse_string::<Int8Type, i32>(array, cast_options),
1115            Int16 => parse_string::<Int16Type, i32>(array, cast_options),
1116            Int32 => parse_string::<Int32Type, i32>(array, cast_options),
1117            Int64 => parse_string::<Int64Type, i32>(array, cast_options),
1118            Float16 => parse_string::<Float16Type, i32>(array, cast_options),
1119            Float32 => parse_string::<Float32Type, i32>(array, cast_options),
1120            Float64 => parse_string::<Float64Type, i32>(array, cast_options),
1121            Date32 => parse_string::<Date32Type, i32>(array, cast_options),
1122            Date64 => parse_string::<Date64Type, i32>(array, cast_options),
1123            Binary => Ok(Arc::new(BinaryArray::from(
1124                array.as_string::<i32>().clone(),
1125            ))),
1126            LargeBinary => {
1127                let binary = BinaryArray::from(array.as_string::<i32>().clone());
1128                cast_byte_container::<BinaryType, LargeBinaryType>(&binary)
1129            }
1130            Utf8View => Ok(Arc::new(StringViewArray::from(array.as_string::<i32>()))),
1131            BinaryView => Ok(Arc::new(
1132                StringViewArray::from(array.as_string::<i32>()).to_binary_view(),
1133            )),
1134            LargeUtf8 => cast_byte_container::<Utf8Type, LargeUtf8Type>(array),
1135            Time32(TimeUnit::Second) => parse_string::<Time32SecondType, i32>(array, cast_options),
1136            Time32(TimeUnit::Millisecond) => {
1137                parse_string::<Time32MillisecondType, i32>(array, cast_options)
1138            }
1139            Time64(TimeUnit::Microsecond) => {
1140                parse_string::<Time64MicrosecondType, i32>(array, cast_options)
1141            }
1142            Time64(TimeUnit::Nanosecond) => {
1143                parse_string::<Time64NanosecondType, i32>(array, cast_options)
1144            }
1145            Timestamp(TimeUnit::Second, to_tz) => cast_string_to_timestamp::<
1146                i32,
1147                TimestampSecondType,
1148            >(array, to_tz.as_ref(), cast_options),
1149            Timestamp(TimeUnit::Millisecond, to_tz) => cast_string_to_timestamp::<
1150                i32,
1151                TimestampMillisecondType,
1152            >(
1153                array, to_tz.as_ref(), cast_options
1154            ),
1155            Timestamp(TimeUnit::Microsecond, to_tz) => cast_string_to_timestamp::<
1156                i32,
1157                TimestampMicrosecondType,
1158            >(
1159                array, to_tz.as_ref(), cast_options
1160            ),
1161            Timestamp(TimeUnit::Nanosecond, to_tz) => cast_string_to_timestamp::<
1162                i32,
1163                TimestampNanosecondType,
1164            >(
1165                array, to_tz.as_ref(), cast_options
1166            ),
1167            Interval(IntervalUnit::YearMonth) => {
1168                cast_string_to_year_month_interval::<i32>(array, cast_options)
1169            }
1170            Interval(IntervalUnit::DayTime) => {
1171                cast_string_to_day_time_interval::<i32>(array, cast_options)
1172            }
1173            Interval(IntervalUnit::MonthDayNano) => {
1174                cast_string_to_month_day_nano_interval::<i32>(array, cast_options)
1175            }
1176            _ => Err(ArrowError::InvalidArgumentError(format!(
1177                "Casting from {from_type} to {to_type} not supported",
1178            ))),
1179        },
1180        (Utf8View, _) => match to_type {
1181            UInt8 => parse_string_view::<UInt8Type>(array, cast_options),
1182            UInt16 => parse_string_view::<UInt16Type>(array, cast_options),
1183            UInt32 => parse_string_view::<UInt32Type>(array, cast_options),
1184            UInt64 => parse_string_view::<UInt64Type>(array, cast_options),
1185            Int8 => parse_string_view::<Int8Type>(array, cast_options),
1186            Int16 => parse_string_view::<Int16Type>(array, cast_options),
1187            Int32 => parse_string_view::<Int32Type>(array, cast_options),
1188            Int64 => parse_string_view::<Int64Type>(array, cast_options),
1189            Float16 => parse_string_view::<Float16Type>(array, cast_options),
1190            Float32 => parse_string_view::<Float32Type>(array, cast_options),
1191            Float64 => parse_string_view::<Float64Type>(array, cast_options),
1192            Date32 => parse_string_view::<Date32Type>(array, cast_options),
1193            Date64 => parse_string_view::<Date64Type>(array, cast_options),
1194            Binary => cast_view_to_byte::<StringViewType, GenericBinaryType<i32>>(array),
1195            LargeBinary => cast_view_to_byte::<StringViewType, GenericBinaryType<i64>>(array),
1196            BinaryView => Ok(Arc::new(array.as_string_view().clone().to_binary_view())),
1197            Utf8 => cast_view_to_byte::<StringViewType, GenericStringType<i32>>(array),
1198            LargeUtf8 => cast_view_to_byte::<StringViewType, GenericStringType<i64>>(array),
1199            Time32(TimeUnit::Second) => parse_string_view::<Time32SecondType>(array, cast_options),
1200            Time32(TimeUnit::Millisecond) => {
1201                parse_string_view::<Time32MillisecondType>(array, cast_options)
1202            }
1203            Time64(TimeUnit::Microsecond) => {
1204                parse_string_view::<Time64MicrosecondType>(array, cast_options)
1205            }
1206            Time64(TimeUnit::Nanosecond) => {
1207                parse_string_view::<Time64NanosecondType>(array, cast_options)
1208            }
1209            Timestamp(TimeUnit::Second, to_tz) => {
1210                cast_view_to_timestamp::<TimestampSecondType>(array, to_tz.as_ref(), cast_options)
1211            }
1212            Timestamp(TimeUnit::Millisecond, to_tz) => cast_view_to_timestamp::<
1213                TimestampMillisecondType,
1214            >(
1215                array, to_tz.as_ref(), cast_options
1216            ),
1217            Timestamp(TimeUnit::Microsecond, to_tz) => cast_view_to_timestamp::<
1218                TimestampMicrosecondType,
1219            >(
1220                array, to_tz.as_ref(), cast_options
1221            ),
1222            Timestamp(TimeUnit::Nanosecond, to_tz) => cast_view_to_timestamp::<
1223                TimestampNanosecondType,
1224            >(
1225                array, to_tz.as_ref(), cast_options
1226            ),
1227            Interval(IntervalUnit::YearMonth) => {
1228                cast_view_to_year_month_interval(array, cast_options)
1229            }
1230            Interval(IntervalUnit::DayTime) => cast_view_to_day_time_interval(array, cast_options),
1231            Interval(IntervalUnit::MonthDayNano) => {
1232                cast_view_to_month_day_nano_interval(array, cast_options)
1233            }
1234            _ => Err(ArrowError::InvalidArgumentError(format!(
1235                "Casting from {from_type} to {to_type} not supported",
1236            ))),
1237        },
1238        (LargeUtf8, _) => match to_type {
1239            UInt8 => parse_string::<UInt8Type, i64>(array, cast_options),
1240            UInt16 => parse_string::<UInt16Type, i64>(array, cast_options),
1241            UInt32 => parse_string::<UInt32Type, i64>(array, cast_options),
1242            UInt64 => parse_string::<UInt64Type, i64>(array, cast_options),
1243            Int8 => parse_string::<Int8Type, i64>(array, cast_options),
1244            Int16 => parse_string::<Int16Type, i64>(array, cast_options),
1245            Int32 => parse_string::<Int32Type, i64>(array, cast_options),
1246            Int64 => parse_string::<Int64Type, i64>(array, cast_options),
1247            Float16 => parse_string::<Float16Type, i64>(array, cast_options),
1248            Float32 => parse_string::<Float32Type, i64>(array, cast_options),
1249            Float64 => parse_string::<Float64Type, i64>(array, cast_options),
1250            Date32 => parse_string::<Date32Type, i64>(array, cast_options),
1251            Date64 => parse_string::<Date64Type, i64>(array, cast_options),
1252            Utf8 => cast_byte_container::<LargeUtf8Type, Utf8Type>(array),
1253            Binary => {
1254                let large_binary = LargeBinaryArray::from(array.as_string::<i64>().clone());
1255                cast_byte_container::<LargeBinaryType, BinaryType>(&large_binary)
1256            }
1257            LargeBinary => Ok(Arc::new(LargeBinaryArray::from(
1258                array.as_string::<i64>().clone(),
1259            ))),
1260            Utf8View => Ok(Arc::new(StringViewArray::from(array.as_string::<i64>()))),
1261            BinaryView => Ok(Arc::new(BinaryViewArray::from(
1262                array
1263                    .as_string::<i64>()
1264                    .into_iter()
1265                    .map(|x| x.map(|x| x.as_bytes()))
1266                    .collect::<Vec<_>>(),
1267            ))),
1268            Time32(TimeUnit::Second) => parse_string::<Time32SecondType, i64>(array, cast_options),
1269            Time32(TimeUnit::Millisecond) => {
1270                parse_string::<Time32MillisecondType, i64>(array, cast_options)
1271            }
1272            Time64(TimeUnit::Microsecond) => {
1273                parse_string::<Time64MicrosecondType, i64>(array, cast_options)
1274            }
1275            Time64(TimeUnit::Nanosecond) => {
1276                parse_string::<Time64NanosecondType, i64>(array, cast_options)
1277            }
1278            Timestamp(TimeUnit::Second, to_tz) => cast_string_to_timestamp::<
1279                i64,
1280                TimestampSecondType,
1281            >(array, to_tz.as_ref(), cast_options),
1282            Timestamp(TimeUnit::Millisecond, to_tz) => cast_string_to_timestamp::<
1283                i64,
1284                TimestampMillisecondType,
1285            >(
1286                array, to_tz.as_ref(), cast_options
1287            ),
1288            Timestamp(TimeUnit::Microsecond, to_tz) => cast_string_to_timestamp::<
1289                i64,
1290                TimestampMicrosecondType,
1291            >(
1292                array, to_tz.as_ref(), cast_options
1293            ),
1294            Timestamp(TimeUnit::Nanosecond, to_tz) => cast_string_to_timestamp::<
1295                i64,
1296                TimestampNanosecondType,
1297            >(
1298                array, to_tz.as_ref(), cast_options
1299            ),
1300            Interval(IntervalUnit::YearMonth) => {
1301                cast_string_to_year_month_interval::<i64>(array, cast_options)
1302            }
1303            Interval(IntervalUnit::DayTime) => {
1304                cast_string_to_day_time_interval::<i64>(array, cast_options)
1305            }
1306            Interval(IntervalUnit::MonthDayNano) => {
1307                cast_string_to_month_day_nano_interval::<i64>(array, cast_options)
1308            }
1309            _ => Err(ArrowError::InvalidArgumentError(format!(
1310                "Casting from {from_type} to {to_type} not supported",
1311            ))),
1312        },
1313        (Binary, _) => match to_type {
1314            Utf8 => cast_binary_to_string::<i32>(array, cast_options),
1315            LargeUtf8 => {
1316                let array = cast_binary_to_string::<i32>(array, cast_options)?;
1317                cast_byte_container::<Utf8Type, LargeUtf8Type>(array.as_ref())
1318            }
1319            LargeBinary => cast_byte_container::<BinaryType, LargeBinaryType>(array),
1320            FixedSizeBinary(size) => {
1321                cast_binary_to_fixed_size_binary::<i32>(array, *size, cast_options)
1322            }
1323            BinaryView => Ok(Arc::new(BinaryViewArray::from(array.as_binary::<i32>()))),
1324            Utf8View => Ok(Arc::new(StringViewArray::from(
1325                cast_binary_to_string::<i32>(array, cast_options)?.as_string::<i32>(),
1326            ))),
1327            _ => Err(ArrowError::InvalidArgumentError(format!(
1328                "Casting from {from_type} to {to_type} not supported",
1329            ))),
1330        },
1331        (LargeBinary, _) => match to_type {
1332            Utf8 => {
1333                let array = cast_binary_to_string::<i64>(array, cast_options)?;
1334                cast_byte_container::<LargeUtf8Type, Utf8Type>(array.as_ref())
1335            }
1336            LargeUtf8 => cast_binary_to_string::<i64>(array, cast_options),
1337            Binary => cast_byte_container::<LargeBinaryType, BinaryType>(array),
1338            FixedSizeBinary(size) => {
1339                cast_binary_to_fixed_size_binary::<i64>(array, *size, cast_options)
1340            }
1341            BinaryView => Ok(Arc::new(BinaryViewArray::from(array.as_binary::<i64>()))),
1342            Utf8View => {
1343                let array = cast_binary_to_string::<i64>(array, cast_options)?;
1344                Ok(Arc::new(StringViewArray::from(array.as_string::<i64>())))
1345            }
1346            _ => Err(ArrowError::InvalidArgumentError(format!(
1347                "Casting from {from_type} to {to_type} not supported",
1348            ))),
1349        },
1350        (FixedSizeBinary(size), _) => match to_type {
1351            Binary => cast_fixed_size_binary_to_binary::<i32>(array, *size),
1352            LargeBinary => cast_fixed_size_binary_to_binary::<i64>(array, *size),
1353            BinaryView => cast_fixed_size_binary_to_binary_view(array, *size),
1354            _ => Err(ArrowError::InvalidArgumentError(format!(
1355                "Casting from {from_type} to {to_type} not supported",
1356            ))),
1357        },
1358        (BinaryView, Binary) => cast_view_to_byte::<BinaryViewType, GenericBinaryType<i32>>(array),
1359        (BinaryView, LargeBinary) => {
1360            cast_view_to_byte::<BinaryViewType, GenericBinaryType<i64>>(array)
1361        }
1362        (BinaryView, Utf8) => {
1363            let binary_arr = cast_view_to_byte::<BinaryViewType, GenericBinaryType<i32>>(array)?;
1364            cast_binary_to_string::<i32>(&binary_arr, cast_options)
1365        }
1366        (BinaryView, LargeUtf8) => {
1367            let binary_arr = cast_view_to_byte::<BinaryViewType, GenericBinaryType<i64>>(array)?;
1368            cast_binary_to_string::<i64>(&binary_arr, cast_options)
1369        }
1370        (BinaryView, Utf8View) => cast_binary_view_to_string_view(array, cast_options),
1371        (BinaryView, _) => Err(ArrowError::InvalidArgumentError(format!(
1372            "Casting from {from_type} to {to_type} not supported",
1373        ))),
1374        (from_type, Utf8View) if from_type.is_primitive() => {
1375            value_to_string_view(array, cast_options)
1376        }
1377        (from_type, LargeUtf8) if from_type.is_primitive() => {
1378            value_to_string::<i64>(array, cast_options)
1379        }
1380        (from_type, Utf8) if from_type.is_primitive() => {
1381            value_to_string::<i32>(array, cast_options)
1382        }
1383        (from_type, Binary) if from_type.is_integer() => match from_type {
1384            UInt8 => cast_numeric_to_binary::<UInt8Type, i32>(array),
1385            UInt16 => cast_numeric_to_binary::<UInt16Type, i32>(array),
1386            UInt32 => cast_numeric_to_binary::<UInt32Type, i32>(array),
1387            UInt64 => cast_numeric_to_binary::<UInt64Type, i32>(array),
1388            Int8 => cast_numeric_to_binary::<Int8Type, i32>(array),
1389            Int16 => cast_numeric_to_binary::<Int16Type, i32>(array),
1390            Int32 => cast_numeric_to_binary::<Int32Type, i32>(array),
1391            Int64 => cast_numeric_to_binary::<Int64Type, i32>(array),
1392            _ => unreachable!(),
1393        },
1394        (from_type, LargeBinary) if from_type.is_integer() => match from_type {
1395            UInt8 => cast_numeric_to_binary::<UInt8Type, i64>(array),
1396            UInt16 => cast_numeric_to_binary::<UInt16Type, i64>(array),
1397            UInt32 => cast_numeric_to_binary::<UInt32Type, i64>(array),
1398            UInt64 => cast_numeric_to_binary::<UInt64Type, i64>(array),
1399            Int8 => cast_numeric_to_binary::<Int8Type, i64>(array),
1400            Int16 => cast_numeric_to_binary::<Int16Type, i64>(array),
1401            Int32 => cast_numeric_to_binary::<Int32Type, i64>(array),
1402            Int64 => cast_numeric_to_binary::<Int64Type, i64>(array),
1403            _ => unreachable!(),
1404        },
1405        // start numeric casts
1406        (UInt8, UInt16) => cast_numeric_arrays::<UInt8Type, UInt16Type>(array, cast_options),
1407        (UInt8, UInt32) => cast_numeric_arrays::<UInt8Type, UInt32Type>(array, cast_options),
1408        (UInt8, UInt64) => cast_numeric_arrays::<UInt8Type, UInt64Type>(array, cast_options),
1409        (UInt8, Int8) => cast_numeric_arrays::<UInt8Type, Int8Type>(array, cast_options),
1410        (UInt8, Int16) => cast_numeric_arrays::<UInt8Type, Int16Type>(array, cast_options),
1411        (UInt8, Int32) => cast_numeric_arrays::<UInt8Type, Int32Type>(array, cast_options),
1412        (UInt8, Int64) => cast_numeric_arrays::<UInt8Type, Int64Type>(array, cast_options),
1413        (UInt8, Float16) => cast_numeric_arrays::<UInt8Type, Float16Type>(array, cast_options),
1414        (UInt8, Float32) => cast_numeric_arrays::<UInt8Type, Float32Type>(array, cast_options),
1415        (UInt8, Float64) => cast_numeric_arrays::<UInt8Type, Float64Type>(array, cast_options),
1416
1417        (UInt16, UInt8) => cast_numeric_arrays::<UInt16Type, UInt8Type>(array, cast_options),
1418        (UInt16, UInt32) => cast_numeric_arrays::<UInt16Type, UInt32Type>(array, cast_options),
1419        (UInt16, UInt64) => cast_numeric_arrays::<UInt16Type, UInt64Type>(array, cast_options),
1420        (UInt16, Int8) => cast_numeric_arrays::<UInt16Type, Int8Type>(array, cast_options),
1421        (UInt16, Int16) => cast_numeric_arrays::<UInt16Type, Int16Type>(array, cast_options),
1422        (UInt16, Int32) => cast_numeric_arrays::<UInt16Type, Int32Type>(array, cast_options),
1423        (UInt16, Int64) => cast_numeric_arrays::<UInt16Type, Int64Type>(array, cast_options),
1424        (UInt16, Float16) => cast_numeric_arrays::<UInt16Type, Float16Type>(array, cast_options),
1425        (UInt16, Float32) => cast_numeric_arrays::<UInt16Type, Float32Type>(array, cast_options),
1426        (UInt16, Float64) => cast_numeric_arrays::<UInt16Type, Float64Type>(array, cast_options),
1427
1428        (UInt32, UInt8) => cast_numeric_arrays::<UInt32Type, UInt8Type>(array, cast_options),
1429        (UInt32, UInt16) => cast_numeric_arrays::<UInt32Type, UInt16Type>(array, cast_options),
1430        (UInt32, UInt64) => cast_numeric_arrays::<UInt32Type, UInt64Type>(array, cast_options),
1431        (UInt32, Int8) => cast_numeric_arrays::<UInt32Type, Int8Type>(array, cast_options),
1432        (UInt32, Int16) => cast_numeric_arrays::<UInt32Type, Int16Type>(array, cast_options),
1433        (UInt32, Int32) => cast_numeric_arrays::<UInt32Type, Int32Type>(array, cast_options),
1434        (UInt32, Int64) => cast_numeric_arrays::<UInt32Type, Int64Type>(array, cast_options),
1435        (UInt32, Float16) => cast_numeric_arrays::<UInt32Type, Float16Type>(array, cast_options),
1436        (UInt32, Float32) => cast_numeric_arrays::<UInt32Type, Float32Type>(array, cast_options),
1437        (UInt32, Float64) => cast_numeric_arrays::<UInt32Type, Float64Type>(array, cast_options),
1438
1439        (UInt64, UInt8) => cast_numeric_arrays::<UInt64Type, UInt8Type>(array, cast_options),
1440        (UInt64, UInt16) => cast_numeric_arrays::<UInt64Type, UInt16Type>(array, cast_options),
1441        (UInt64, UInt32) => cast_numeric_arrays::<UInt64Type, UInt32Type>(array, cast_options),
1442        (UInt64, Int8) => cast_numeric_arrays::<UInt64Type, Int8Type>(array, cast_options),
1443        (UInt64, Int16) => cast_numeric_arrays::<UInt64Type, Int16Type>(array, cast_options),
1444        (UInt64, Int32) => cast_numeric_arrays::<UInt64Type, Int32Type>(array, cast_options),
1445        (UInt64, Int64) => cast_numeric_arrays::<UInt64Type, Int64Type>(array, cast_options),
1446        (UInt64, Float16) => cast_numeric_arrays::<UInt64Type, Float16Type>(array, cast_options),
1447        (UInt64, Float32) => cast_numeric_arrays::<UInt64Type, Float32Type>(array, cast_options),
1448        (UInt64, Float64) => cast_numeric_arrays::<UInt64Type, Float64Type>(array, cast_options),
1449
1450        (Int8, UInt8) => cast_numeric_arrays::<Int8Type, UInt8Type>(array, cast_options),
1451        (Int8, UInt16) => cast_numeric_arrays::<Int8Type, UInt16Type>(array, cast_options),
1452        (Int8, UInt32) => cast_numeric_arrays::<Int8Type, UInt32Type>(array, cast_options),
1453        (Int8, UInt64) => cast_numeric_arrays::<Int8Type, UInt64Type>(array, cast_options),
1454        (Int8, Int16) => cast_numeric_arrays::<Int8Type, Int16Type>(array, cast_options),
1455        (Int8, Int32) => cast_numeric_arrays::<Int8Type, Int32Type>(array, cast_options),
1456        (Int8, Int64) => cast_numeric_arrays::<Int8Type, Int64Type>(array, cast_options),
1457        (Int8, Float16) => cast_numeric_arrays::<Int8Type, Float16Type>(array, cast_options),
1458        (Int8, Float32) => cast_numeric_arrays::<Int8Type, Float32Type>(array, cast_options),
1459        (Int8, Float64) => cast_numeric_arrays::<Int8Type, Float64Type>(array, cast_options),
1460
1461        (Int16, UInt8) => cast_numeric_arrays::<Int16Type, UInt8Type>(array, cast_options),
1462        (Int16, UInt16) => cast_numeric_arrays::<Int16Type, UInt16Type>(array, cast_options),
1463        (Int16, UInt32) => cast_numeric_arrays::<Int16Type, UInt32Type>(array, cast_options),
1464        (Int16, UInt64) => cast_numeric_arrays::<Int16Type, UInt64Type>(array, cast_options),
1465        (Int16, Int8) => cast_numeric_arrays::<Int16Type, Int8Type>(array, cast_options),
1466        (Int16, Int32) => cast_numeric_arrays::<Int16Type, Int32Type>(array, cast_options),
1467        (Int16, Int64) => cast_numeric_arrays::<Int16Type, Int64Type>(array, cast_options),
1468        (Int16, Float16) => cast_numeric_arrays::<Int16Type, Float16Type>(array, cast_options),
1469        (Int16, Float32) => cast_numeric_arrays::<Int16Type, Float32Type>(array, cast_options),
1470        (Int16, Float64) => cast_numeric_arrays::<Int16Type, Float64Type>(array, cast_options),
1471
1472        (Int32, UInt8) => cast_numeric_arrays::<Int32Type, UInt8Type>(array, cast_options),
1473        (Int32, UInt16) => cast_numeric_arrays::<Int32Type, UInt16Type>(array, cast_options),
1474        (Int32, UInt32) => cast_numeric_arrays::<Int32Type, UInt32Type>(array, cast_options),
1475        (Int32, UInt64) => cast_numeric_arrays::<Int32Type, UInt64Type>(array, cast_options),
1476        (Int32, Int8) => cast_numeric_arrays::<Int32Type, Int8Type>(array, cast_options),
1477        (Int32, Int16) => cast_numeric_arrays::<Int32Type, Int16Type>(array, cast_options),
1478        (Int32, Int64) => cast_numeric_arrays::<Int32Type, Int64Type>(array, cast_options),
1479        (Int32, Float16) => cast_numeric_arrays::<Int32Type, Float16Type>(array, cast_options),
1480        (Int32, Float32) => cast_numeric_arrays::<Int32Type, Float32Type>(array, cast_options),
1481        (Int32, Float64) => cast_numeric_arrays::<Int32Type, Float64Type>(array, cast_options),
1482
1483        (Int64, UInt8) => cast_numeric_arrays::<Int64Type, UInt8Type>(array, cast_options),
1484        (Int64, UInt16) => cast_numeric_arrays::<Int64Type, UInt16Type>(array, cast_options),
1485        (Int64, UInt32) => cast_numeric_arrays::<Int64Type, UInt32Type>(array, cast_options),
1486        (Int64, UInt64) => cast_numeric_arrays::<Int64Type, UInt64Type>(array, cast_options),
1487        (Int64, Int8) => cast_numeric_arrays::<Int64Type, Int8Type>(array, cast_options),
1488        (Int64, Int16) => cast_numeric_arrays::<Int64Type, Int16Type>(array, cast_options),
1489        (Int64, Int32) => cast_numeric_arrays::<Int64Type, Int32Type>(array, cast_options),
1490        (Int64, Float16) => cast_numeric_arrays::<Int64Type, Float16Type>(array, cast_options),
1491        (Int64, Float32) => cast_numeric_arrays::<Int64Type, Float32Type>(array, cast_options),
1492        (Int64, Float64) => cast_numeric_arrays::<Int64Type, Float64Type>(array, cast_options),
1493
1494        (Float16, UInt8) => cast_numeric_arrays::<Float16Type, UInt8Type>(array, cast_options),
1495        (Float16, UInt16) => cast_numeric_arrays::<Float16Type, UInt16Type>(array, cast_options),
1496        (Float16, UInt32) => cast_numeric_arrays::<Float16Type, UInt32Type>(array, cast_options),
1497        (Float16, UInt64) => cast_numeric_arrays::<Float16Type, UInt64Type>(array, cast_options),
1498        (Float16, Int8) => cast_numeric_arrays::<Float16Type, Int8Type>(array, cast_options),
1499        (Float16, Int16) => cast_numeric_arrays::<Float16Type, Int16Type>(array, cast_options),
1500        (Float16, Int32) => cast_numeric_arrays::<Float16Type, Int32Type>(array, cast_options),
1501        (Float16, Int64) => cast_numeric_arrays::<Float16Type, Int64Type>(array, cast_options),
1502        (Float16, Float32) => cast_numeric_arrays::<Float16Type, Float32Type>(array, cast_options),
1503        (Float16, Float64) => cast_numeric_arrays::<Float16Type, Float64Type>(array, cast_options),
1504
1505        (Float32, UInt8) => cast_numeric_arrays::<Float32Type, UInt8Type>(array, cast_options),
1506        (Float32, UInt16) => cast_numeric_arrays::<Float32Type, UInt16Type>(array, cast_options),
1507        (Float32, UInt32) => cast_numeric_arrays::<Float32Type, UInt32Type>(array, cast_options),
1508        (Float32, UInt64) => cast_numeric_arrays::<Float32Type, UInt64Type>(array, cast_options),
1509        (Float32, Int8) => cast_numeric_arrays::<Float32Type, Int8Type>(array, cast_options),
1510        (Float32, Int16) => cast_numeric_arrays::<Float32Type, Int16Type>(array, cast_options),
1511        (Float32, Int32) => cast_numeric_arrays::<Float32Type, Int32Type>(array, cast_options),
1512        (Float32, Int64) => cast_numeric_arrays::<Float32Type, Int64Type>(array, cast_options),
1513        (Float32, Float16) => cast_numeric_arrays::<Float32Type, Float16Type>(array, cast_options),
1514        (Float32, Float64) => cast_numeric_arrays::<Float32Type, Float64Type>(array, cast_options),
1515
1516        (Float64, UInt8) => cast_numeric_arrays::<Float64Type, UInt8Type>(array, cast_options),
1517        (Float64, UInt16) => cast_numeric_arrays::<Float64Type, UInt16Type>(array, cast_options),
1518        (Float64, UInt32) => cast_numeric_arrays::<Float64Type, UInt32Type>(array, cast_options),
1519        (Float64, UInt64) => cast_numeric_arrays::<Float64Type, UInt64Type>(array, cast_options),
1520        (Float64, Int8) => cast_numeric_arrays::<Float64Type, Int8Type>(array, cast_options),
1521        (Float64, Int16) => cast_numeric_arrays::<Float64Type, Int16Type>(array, cast_options),
1522        (Float64, Int32) => cast_numeric_arrays::<Float64Type, Int32Type>(array, cast_options),
1523        (Float64, Int64) => cast_numeric_arrays::<Float64Type, Int64Type>(array, cast_options),
1524        (Float64, Float16) => cast_numeric_arrays::<Float64Type, Float16Type>(array, cast_options),
1525        (Float64, Float32) => cast_numeric_arrays::<Float64Type, Float32Type>(array, cast_options),
1526        // end numeric casts
1527
1528        // temporal casts
1529        (Int32, Date32) => cast_reinterpret_arrays::<Int32Type, Date32Type>(array),
1530        (Int32, Date64) => cast_with_options(
1531            &cast_with_options(array, &Date32, cast_options)?,
1532            &Date64,
1533            cast_options,
1534        ),
1535        (Int32, Time32(TimeUnit::Second)) => {
1536            cast_reinterpret_arrays::<Int32Type, Time32SecondType>(array)
1537        }
1538        (Int32, Time32(TimeUnit::Millisecond)) => {
1539            cast_reinterpret_arrays::<Int32Type, Time32MillisecondType>(array)
1540        }
1541        // No support for microsecond/nanosecond with i32
1542        (Date32, Int32) => cast_reinterpret_arrays::<Date32Type, Int32Type>(array),
1543        (Date32, Int64) => cast_with_options(
1544            &cast_with_options(array, &Int32, cast_options)?,
1545            &Int64,
1546            cast_options,
1547        ),
1548        (Time32(TimeUnit::Second), Int32) => {
1549            cast_reinterpret_arrays::<Time32SecondType, Int32Type>(array)
1550        }
1551        (Time32(TimeUnit::Millisecond), Int32) => {
1552            cast_reinterpret_arrays::<Time32MillisecondType, Int32Type>(array)
1553        }
1554        (Time32(TimeUnit::Second), Int64) => cast_with_options(
1555            &cast_with_options(array, &Int32, cast_options)?,
1556            &Int64,
1557            cast_options,
1558        ),
1559        (Time32(TimeUnit::Millisecond), Int64) => cast_with_options(
1560            &cast_with_options(array, &Int32, cast_options)?,
1561            &Int64,
1562            cast_options,
1563        ),
1564        (Int64, Date64) => cast_reinterpret_arrays::<Int64Type, Date64Type>(array),
1565        (Int64, Date32) => cast_with_options(
1566            &cast_with_options(array, &Int32, cast_options)?,
1567            &Date32,
1568            cast_options,
1569        ),
1570        // No support for second/milliseconds with i64
1571        (Int64, Time64(TimeUnit::Microsecond)) => {
1572            cast_reinterpret_arrays::<Int64Type, Time64MicrosecondType>(array)
1573        }
1574        (Int64, Time64(TimeUnit::Nanosecond)) => {
1575            cast_reinterpret_arrays::<Int64Type, Time64NanosecondType>(array)
1576        }
1577
1578        (Date64, Int64) => cast_reinterpret_arrays::<Date64Type, Int64Type>(array),
1579        (Date64, Int32) => cast_with_options(
1580            &cast_with_options(array, &Int64, cast_options)?,
1581            &Int32,
1582            cast_options,
1583        ),
1584        (Time64(TimeUnit::Microsecond), Int64) => {
1585            cast_reinterpret_arrays::<Time64MicrosecondType, Int64Type>(array)
1586        }
1587        (Time64(TimeUnit::Nanosecond), Int64) => {
1588            cast_reinterpret_arrays::<Time64NanosecondType, Int64Type>(array)
1589        }
1590        (Date32, Date64) => Ok(Arc::new(
1591            array
1592                .as_primitive::<Date32Type>()
1593                .unary::<_, Date64Type>(|x| x as i64 * MILLISECONDS_IN_DAY),
1594        )),
1595        (Date64, Date32) => {
1596            let array = array.as_primitive::<Date64Type>();
1597            let result = if cast_options.safe {
1598                array.unary_opt::<_, Date32Type>(|x| i32::try_from(x / MILLISECONDS_IN_DAY).ok())
1599            } else {
1600                array.try_unary::<_, Date32Type, _>(|x| {
1601                    i32::try_from(x / MILLISECONDS_IN_DAY).map_err(|_| {
1602                        ArrowError::CastError(format!(
1603                            "Cannot cast Date64 value {x} to Date32 without overflow"
1604                        ))
1605                    })
1606                })?
1607            };
1608            Ok(Arc::new(result))
1609        }
1610
1611        (Time32(TimeUnit::Second), Time32(TimeUnit::Millisecond)) => {
1612            let array = array.as_primitive::<Time32SecondType>();
1613            let result = if cast_options.safe {
1614                array.unary_opt::<_, Time32MillisecondType>(|x| x.checked_mul(MILLISECONDS as i32))
1615            } else {
1616                array.try_unary::<_, Time32MillisecondType, _>(|x| {
1617                    x.mul_checked(MILLISECONDS as i32)
1618                })?
1619            };
1620            Ok(Arc::new(result))
1621        }
1622        (Time32(TimeUnit::Second), Time64(TimeUnit::Microsecond)) => Ok(Arc::new(
1623            array
1624                .as_primitive::<Time32SecondType>()
1625                .unary::<_, Time64MicrosecondType>(|x| x as i64 * MICROSECONDS),
1626        )),
1627        (Time32(TimeUnit::Second), Time64(TimeUnit::Nanosecond)) => Ok(Arc::new(
1628            array
1629                .as_primitive::<Time32SecondType>()
1630                .unary::<_, Time64NanosecondType>(|x| x as i64 * NANOSECONDS),
1631        )),
1632
1633        (Time32(TimeUnit::Millisecond), Time32(TimeUnit::Second)) => Ok(Arc::new(
1634            array
1635                .as_primitive::<Time32MillisecondType>()
1636                .unary::<_, Time32SecondType>(|x| x / MILLISECONDS as i32),
1637        )),
1638        (Time32(TimeUnit::Millisecond), Time64(TimeUnit::Microsecond)) => Ok(Arc::new(
1639            array
1640                .as_primitive::<Time32MillisecondType>()
1641                .unary::<_, Time64MicrosecondType>(|x| x as i64 * (MICROSECONDS / MILLISECONDS)),
1642        )),
1643        (Time32(TimeUnit::Millisecond), Time64(TimeUnit::Nanosecond)) => Ok(Arc::new(
1644            array
1645                .as_primitive::<Time32MillisecondType>()
1646                .unary::<_, Time64NanosecondType>(|x| x as i64 * (NANOSECONDS / MILLISECONDS)),
1647        )),
1648
1649        (Time64(TimeUnit::Microsecond), Time32(TimeUnit::Second)) => {
1650            cast_time64_to_time32::<Time64MicrosecondType, Time32SecondType>(
1651                array,
1652                MICROSECONDS,
1653                cast_options,
1654            )
1655        }
1656        (Time64(TimeUnit::Microsecond), Time32(TimeUnit::Millisecond)) => {
1657            cast_time64_to_time32::<Time64MicrosecondType, Time32MillisecondType>(
1658                array,
1659                MICROSECONDS / MILLISECONDS,
1660                cast_options,
1661            )
1662        }
1663        (Time64(TimeUnit::Microsecond), Time64(TimeUnit::Nanosecond)) => {
1664            let array = array.as_primitive::<Time64MicrosecondType>();
1665            let result = if cast_options.safe {
1666                array.unary_opt::<_, Time64NanosecondType>(|x| {
1667                    x.checked_mul(NANOSECONDS / MICROSECONDS)
1668                })
1669            } else {
1670                array.try_unary::<_, Time64NanosecondType, _>(|x| {
1671                    x.mul_checked(NANOSECONDS / MICROSECONDS)
1672                })?
1673            };
1674            Ok(Arc::new(result))
1675        }
1676
1677        (Time64(TimeUnit::Nanosecond), Time32(TimeUnit::Second)) => {
1678            cast_time64_to_time32::<Time64NanosecondType, Time32SecondType>(
1679                array,
1680                NANOSECONDS,
1681                cast_options,
1682            )
1683        }
1684        (Time64(TimeUnit::Nanosecond), Time32(TimeUnit::Millisecond)) => {
1685            cast_time64_to_time32::<Time64NanosecondType, Time32MillisecondType>(
1686                array,
1687                NANOSECONDS / MILLISECONDS,
1688                cast_options,
1689            )
1690        }
1691        (Time64(TimeUnit::Nanosecond), Time64(TimeUnit::Microsecond)) => Ok(Arc::new(
1692            array
1693                .as_primitive::<Time64NanosecondType>()
1694                .unary::<_, Time64MicrosecondType>(|x| x / (NANOSECONDS / MICROSECONDS)),
1695        )),
1696
1697        // Timestamp to integer/floating/decimals
1698        (Timestamp(TimeUnit::Second, _), _) if to_type.is_numeric() => {
1699            let array = cast_reinterpret_arrays::<TimestampSecondType, Int64Type>(array)?;
1700            cast_with_options(&array, to_type, cast_options)
1701        }
1702        (Timestamp(TimeUnit::Millisecond, _), _) if to_type.is_numeric() => {
1703            let array = cast_reinterpret_arrays::<TimestampMillisecondType, Int64Type>(array)?;
1704            cast_with_options(&array, to_type, cast_options)
1705        }
1706        (Timestamp(TimeUnit::Microsecond, _), _) if to_type.is_numeric() => {
1707            let array = cast_reinterpret_arrays::<TimestampMicrosecondType, Int64Type>(array)?;
1708            cast_with_options(&array, to_type, cast_options)
1709        }
1710        (Timestamp(TimeUnit::Nanosecond, _), _) if to_type.is_numeric() => {
1711            let array = cast_reinterpret_arrays::<TimestampNanosecondType, Int64Type>(array)?;
1712            cast_with_options(&array, to_type, cast_options)
1713        }
1714
1715        (_, Timestamp(unit, tz)) if from_type.is_numeric() => {
1716            let array = cast_with_options(array, &Int64, cast_options)?;
1717            Ok(make_timestamp_array(
1718                array.as_primitive(),
1719                *unit,
1720                tz.clone(),
1721            ))
1722        }
1723
1724        (Timestamp(from_unit, from_tz), Timestamp(to_unit, to_tz)) => {
1725            let array = cast_with_options(array, &Int64, cast_options)?;
1726            let time_array = array.as_primitive::<Int64Type>();
1727            let from_size = time_unit_multiple(from_unit);
1728            let to_size = time_unit_multiple(to_unit);
1729            // we either divide or multiply, depending on size of each unit
1730            // units are never the same when the types are the same
1731            let converted = match from_size.cmp(&to_size) {
1732                Ordering::Greater => {
1733                    let divisor = from_size / to_size;
1734                    time_array.unary::<_, Int64Type>(|o| o / divisor)
1735                }
1736                Ordering::Equal => time_array.clone(),
1737                Ordering::Less => {
1738                    let mul = to_size / from_size;
1739                    if cast_options.safe {
1740                        time_array.unary_opt::<_, Int64Type>(|o| o.checked_mul(mul))
1741                    } else {
1742                        time_array.try_unary::<_, Int64Type, _>(|o| o.mul_checked(mul))?
1743                    }
1744                }
1745            };
1746            // Normalize timezone
1747            let adjusted = match (from_tz, to_tz) {
1748                // Only this case needs to be adjusted because we're casting from
1749                // unknown time offset to some time offset, we want the time to be
1750                // unchanged.
1751                //
1752                // i.e. Timestamp('2001-01-01T00:00', None) -> Timestamp('2001-01-01T00:00', '+0700')
1753                //
1754                // For IANA timezones a wall clock reading is not always a unique
1755                // instant: a "fall back" DST transition makes an hour occur twice
1756                // and a "spring forward" transition skips an hour entirely. See
1757                // `resolve_local_offset` for how those readings are resolved.
1758                (None, Some(to_tz)) => {
1759                    let to_tz: Tz = to_tz.parse()?;
1760                    match to_unit {
1761                        TimeUnit::Second => adjust_timestamp_to_timezone::<TimestampSecondType>(
1762                            converted,
1763                            &to_tz,
1764                            cast_options,
1765                        )?,
1766                        TimeUnit::Millisecond => adjust_timestamp_to_timezone::<
1767                            TimestampMillisecondType,
1768                        >(
1769                            converted, &to_tz, cast_options
1770                        )?,
1771                        TimeUnit::Microsecond => adjust_timestamp_to_timezone::<
1772                            TimestampMicrosecondType,
1773                        >(
1774                            converted, &to_tz, cast_options
1775                        )?,
1776                        TimeUnit::Nanosecond => adjust_timestamp_to_timezone::<
1777                            TimestampNanosecondType,
1778                        >(
1779                            converted, &to_tz, cast_options
1780                        )?,
1781                    }
1782                }
1783                _ => converted,
1784            };
1785            Ok(make_timestamp_array(&adjusted, *to_unit, to_tz.clone()))
1786        }
1787        (Timestamp(TimeUnit::Microsecond, _), Date32) => timestamp_to_date32(
1788            array.as_primitive::<TimestampMicrosecondType>(),
1789            cast_options,
1790        ),
1791        (Timestamp(TimeUnit::Millisecond, _), Date32) => timestamp_to_date32(
1792            array.as_primitive::<TimestampMillisecondType>(),
1793            cast_options,
1794        ),
1795        (Timestamp(TimeUnit::Second, _), Date32) => {
1796            timestamp_to_date32(array.as_primitive::<TimestampSecondType>(), cast_options)
1797        }
1798        (Timestamp(TimeUnit::Nanosecond, _), Date32) => timestamp_to_date32(
1799            array.as_primitive::<TimestampNanosecondType>(),
1800            cast_options,
1801        ),
1802        (Timestamp(TimeUnit::Second, _), Date64) => {
1803            timestamp_to_date64(array.as_primitive::<TimestampSecondType>(), cast_options)
1804        }
1805        (Timestamp(TimeUnit::Millisecond, _), Date64) => timestamp_to_date64(
1806            array.as_primitive::<TimestampMillisecondType>(),
1807            cast_options,
1808        ),
1809        (Timestamp(TimeUnit::Microsecond, _), Date64) => timestamp_to_date64(
1810            array.as_primitive::<TimestampMicrosecondType>(),
1811            cast_options,
1812        ),
1813        (Timestamp(TimeUnit::Nanosecond, _), Date64) => timestamp_to_date64(
1814            array.as_primitive::<TimestampNanosecondType>(),
1815            cast_options,
1816        ),
1817        (Timestamp(TimeUnit::Second, _), Time32(_) | Time64(_)) => {
1818            cast_timestamp_to_time::<TimestampSecondType>(array, to_type, cast_options)
1819        }
1820        (Timestamp(TimeUnit::Millisecond, _), Time32(_) | Time64(_)) => {
1821            cast_timestamp_to_time::<TimestampMillisecondType>(array, to_type, cast_options)
1822        }
1823        (Timestamp(TimeUnit::Microsecond, _), Time32(_) | Time64(_)) => {
1824            cast_timestamp_to_time::<TimestampMicrosecondType>(array, to_type, cast_options)
1825        }
1826        (Timestamp(TimeUnit::Nanosecond, _), Time32(_) | Time64(_)) => {
1827            cast_timestamp_to_time::<TimestampNanosecondType>(array, to_type, cast_options)
1828        }
1829        (Date64, Timestamp(TimeUnit::Second, _)) => {
1830            let array = array
1831                .as_primitive::<Date64Type>()
1832                .unary::<_, TimestampSecondType>(|x| x / MILLISECONDS);
1833
1834            cast_with_options(&array, to_type, cast_options)
1835        }
1836        (Date64, Timestamp(TimeUnit::Millisecond, _)) => {
1837            let array = array
1838                .as_primitive::<Date64Type>()
1839                .reinterpret_cast::<TimestampMillisecondType>();
1840
1841            cast_with_options(&array, to_type, cast_options)
1842        }
1843
1844        (Date64, Timestamp(TimeUnit::Microsecond, _)) => {
1845            let array = array
1846                .as_primitive::<Date64Type>()
1847                .reinterpret_cast::<TimestampMillisecondType>();
1848
1849            cast_with_options(&array, to_type, cast_options)
1850        }
1851        (Date64, Timestamp(TimeUnit::Nanosecond, _)) => {
1852            let array = array
1853                .as_primitive::<Date64Type>()
1854                .reinterpret_cast::<TimestampMillisecondType>();
1855
1856            cast_with_options(&array, to_type, cast_options)
1857        }
1858        (Date32, Timestamp(TimeUnit::Second, _)) => {
1859            let array = array
1860                .as_primitive::<Date32Type>()
1861                .unary::<_, TimestampSecondType>(|x| (x as i64) * SECONDS_IN_DAY);
1862
1863            cast_with_options(&array, to_type, cast_options)
1864        }
1865        (Date32, Timestamp(TimeUnit::Millisecond, _)) => {
1866            let array = array
1867                .as_primitive::<Date32Type>()
1868                .unary::<_, TimestampMillisecondType>(|x| (x as i64) * MILLISECONDS_IN_DAY);
1869
1870            cast_with_options(&array, to_type, cast_options)
1871        }
1872        (Date32, Timestamp(TimeUnit::Microsecond, _)) => {
1873            let date_array = array.as_primitive::<Date32Type>();
1874            let converted = if cast_options.safe {
1875                date_array.unary_opt::<_, TimestampMicrosecondType>(|x| {
1876                    (x as i64).checked_mul(MICROSECONDS_IN_DAY)
1877                })
1878            } else {
1879                date_array.try_unary::<_, TimestampMicrosecondType, _>(|x| {
1880                    (x as i64).mul_checked(MICROSECONDS_IN_DAY)
1881                })?
1882            };
1883            cast_with_options(&converted, to_type, cast_options)
1884        }
1885        (Date32, Timestamp(TimeUnit::Nanosecond, _)) => {
1886            let date_array = array.as_primitive::<Date32Type>();
1887            let converted = if cast_options.safe {
1888                date_array.unary_opt::<_, TimestampNanosecondType>(|x| {
1889                    (x as i64).checked_mul(NANOSECONDS_IN_DAY)
1890                })
1891            } else {
1892                date_array.try_unary::<_, TimestampNanosecondType, _>(|x| {
1893                    (x as i64).mul_checked(NANOSECONDS_IN_DAY)
1894                })?
1895            };
1896            cast_with_options(&converted, to_type, cast_options)
1897        }
1898
1899        (_, Duration(unit)) if from_type.is_numeric() => {
1900            let array = cast_with_options(array, &Int64, cast_options)?;
1901            Ok(make_duration_array(array.as_primitive(), *unit))
1902        }
1903        (Duration(TimeUnit::Second), _) if to_type.is_numeric() => {
1904            let array = cast_reinterpret_arrays::<DurationSecondType, Int64Type>(array)?;
1905            cast_with_options(&array, to_type, cast_options)
1906        }
1907        (Duration(TimeUnit::Millisecond), _) if to_type.is_numeric() => {
1908            let array = cast_reinterpret_arrays::<DurationMillisecondType, Int64Type>(array)?;
1909            cast_with_options(&array, to_type, cast_options)
1910        }
1911        (Duration(TimeUnit::Microsecond), _) if to_type.is_numeric() => {
1912            let array = cast_reinterpret_arrays::<DurationMicrosecondType, Int64Type>(array)?;
1913            cast_with_options(&array, to_type, cast_options)
1914        }
1915        (Duration(TimeUnit::Nanosecond), _) if to_type.is_numeric() => {
1916            let array = cast_reinterpret_arrays::<DurationNanosecondType, Int64Type>(array)?;
1917            cast_with_options(&array, to_type, cast_options)
1918        }
1919
1920        (Duration(from_unit), Duration(to_unit)) => {
1921            let array = cast_with_options(array, &Int64, cast_options)?;
1922            let time_array = array.as_primitive::<Int64Type>();
1923            let from_size = time_unit_multiple(from_unit);
1924            let to_size = time_unit_multiple(to_unit);
1925            // we either divide or multiply, depending on size of each unit
1926            // units are never the same when the types are the same
1927            let converted = match from_size.cmp(&to_size) {
1928                Ordering::Greater => {
1929                    let divisor = from_size / to_size;
1930                    time_array.unary::<_, Int64Type>(|o| o / divisor)
1931                }
1932                Ordering::Equal => time_array.clone(),
1933                Ordering::Less => {
1934                    let mul = to_size / from_size;
1935                    if cast_options.safe {
1936                        time_array.unary_opt::<_, Int64Type>(|o| o.checked_mul(mul))
1937                    } else {
1938                        time_array.try_unary::<_, Int64Type, _>(|o| o.mul_checked(mul))?
1939                    }
1940                }
1941            };
1942            Ok(make_duration_array(&converted, *to_unit))
1943        }
1944
1945        (Duration(TimeUnit::Second), Interval(IntervalUnit::MonthDayNano)) => {
1946            cast_duration_to_interval::<DurationSecondType>(array, cast_options)
1947        }
1948        (Duration(TimeUnit::Millisecond), Interval(IntervalUnit::MonthDayNano)) => {
1949            cast_duration_to_interval::<DurationMillisecondType>(array, cast_options)
1950        }
1951        (Duration(TimeUnit::Microsecond), Interval(IntervalUnit::MonthDayNano)) => {
1952            cast_duration_to_interval::<DurationMicrosecondType>(array, cast_options)
1953        }
1954        (Duration(TimeUnit::Nanosecond), Interval(IntervalUnit::MonthDayNano)) => {
1955            cast_duration_to_interval::<DurationNanosecondType>(array, cast_options)
1956        }
1957        (Interval(IntervalUnit::MonthDayNano), Duration(TimeUnit::Second)) => {
1958            cast_month_day_nano_to_duration::<DurationSecondType>(array, cast_options)
1959        }
1960        (Interval(IntervalUnit::MonthDayNano), Duration(TimeUnit::Millisecond)) => {
1961            cast_month_day_nano_to_duration::<DurationMillisecondType>(array, cast_options)
1962        }
1963        (Interval(IntervalUnit::MonthDayNano), Duration(TimeUnit::Microsecond)) => {
1964            cast_month_day_nano_to_duration::<DurationMicrosecondType>(array, cast_options)
1965        }
1966        (Interval(IntervalUnit::MonthDayNano), Duration(TimeUnit::Nanosecond)) => {
1967            cast_month_day_nano_to_duration::<DurationNanosecondType>(array, cast_options)
1968        }
1969        (Interval(IntervalUnit::YearMonth), Interval(IntervalUnit::MonthDayNano)) => {
1970            cast_interval_year_month_to_interval_month_day_nano(array, cast_options)
1971        }
1972        (Interval(IntervalUnit::DayTime), Interval(IntervalUnit::MonthDayNano)) => {
1973            cast_interval_day_time_to_interval_month_day_nano(array, cast_options)
1974        }
1975        (Int32, Interval(IntervalUnit::YearMonth)) => {
1976            cast_reinterpret_arrays::<Int32Type, IntervalYearMonthType>(array)
1977        }
1978        (_, _) => Err(ArrowError::InvalidArgumentError(format!(
1979            "Casting from {from_type} to {to_type} not supported",
1980        ))),
1981    }
1982}
1983
1984/// Number of `T` units in one day
1985const fn units_per_day<T: ArrowTimestampType>() -> i64 {
1986    SECONDS_IN_DAY * time_unit_multiple(&T::UNIT)
1987}
1988
1989/// Get the time unit as a multiple of a second
1990const fn time_unit_multiple(unit: &TimeUnit) -> i64 {
1991    match unit {
1992        TimeUnit::Second => 1,
1993        TimeUnit::Millisecond => MILLISECONDS,
1994        TimeUnit::Microsecond => MICROSECONDS,
1995        TimeUnit::Nanosecond => NANOSECONDS,
1996    }
1997}
1998
1999fn cast_time64_to_time32<FROM, TO>(
2000    array: &dyn Array,
2001    divisor: i64,
2002    cast_options: &CastOptions,
2003) -> Result<ArrayRef, ArrowError>
2004where
2005    FROM: ArrowPrimitiveType<Native = i64>,
2006    TO: ArrowPrimitiveType<Native = i32>,
2007{
2008    let array = array.as_primitive::<FROM>();
2009    let result = if cast_options.safe {
2010        array.unary_opt::<_, TO>(|value| i32::try_from(value / divisor).ok())
2011    } else {
2012        array.try_unary::<_, TO, _>(|value| {
2013            let value = value / divisor;
2014            i32::try_from(value).map_err(|_| {
2015                ArrowError::CastError(format!(
2016                    "Can't cast value {value:?} to type {}",
2017                    TO::DATA_TYPE
2018                ))
2019            })
2020        })?
2021    };
2022
2023    Ok(Arc::new(result))
2024}
2025
2026#[cfg(test)]
2027mod tests {
2028    use super::*;
2029    use crate::cast::numeric::{NumericNative, is_infallible_numeric_cast};
2030    use DataType::*;
2031    use arrow_array::{Int64Array, StringArray};
2032    use arrow_buffer::{NullBuffer, i256};
2033    use arrow_schema::{DataType, Field};
2034    use chrono::{FixedOffset, NaiveDate, NaiveTime};
2035    use half::f16;
2036    use std::sync::Arc;
2037
2038    /// Checks the fast-path classification against `num_cast` for every pair of
2039    /// numeric types. `num_cast` fails only on values outside the target's range,
2040    /// so each type's extremes decide, plus NaN for floats.
2041    #[test]
2042    fn test_is_infallible_numeric_cast() {
2043        macro_rules! check {
2044            ($from:ty => $values:expr, [$($to:ty),*]) => {$(
2045                let infallible = is_infallible_numeric_cast(
2046                    <<$from as ArrowPrimitiveType>::Native as NumericNative>::KIND,
2047                    <<$to as ArrowPrimitiveType>::Native as NumericNative>::KIND,
2048                );
2049                let succeeds = $values
2050                    .iter()
2051                    .all(|&v| num_cast::<_, <$to as ArrowPrimitiveType>::Native>(v).is_some());
2052                assert_eq!(
2053                    infallible,
2054                    succeeds,
2055                    "{} to {}",
2056                    <$from as ArrowPrimitiveType>::DATA_TYPE,
2057                    <$to as ArrowPrimitiveType>::DATA_TYPE
2058                );
2059            )*};
2060        }
2061        macro_rules! check_all {
2062            ($($from:ty => $values:expr),* $(,)?) => {$(
2063                check!($from => $values, [
2064                    UInt8Type, UInt16Type, UInt32Type, UInt64Type, Int8Type, Int16Type,
2065                    Int32Type, Int64Type, Float16Type, Float32Type, Float64Type
2066                ]);
2067            )*};
2068        }
2069        check_all! {
2070            UInt8Type => [u8::MIN, u8::MAX],
2071            UInt16Type => [u16::MIN, u16::MAX],
2072            UInt32Type => [u32::MIN, u32::MAX],
2073            UInt64Type => [u64::MIN, u64::MAX],
2074            Int8Type => [i8::MIN, i8::MAX],
2075            Int16Type => [i16::MIN, i16::MAX],
2076            Int32Type => [i32::MIN, i32::MAX],
2077            Int64Type => [i64::MIN, i64::MAX],
2078            Float16Type => [f16::MIN, f16::MAX, f16::NAN],
2079            Float32Type => [f32::MIN, f32::MAX, f32::NAN],
2080            Float64Type => [f64::MIN, f64::MAX, f64::NAN],
2081        }
2082    }
2083
2084    #[test]
2085    fn test_cast_integer_to_timestamp() {
2086        let array = Int64Array::from(vec![Some(2), Some(10), None]);
2087        let expected = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2088
2089        let array = Int8Array::from(vec![Some(2), Some(10), None]);
2090        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2091
2092        assert_eq!(&actual, &expected);
2093
2094        let array = Int16Array::from(vec![Some(2), Some(10), None]);
2095        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2096
2097        assert_eq!(&actual, &expected);
2098
2099        let array = Int32Array::from(vec![Some(2), Some(10), None]);
2100        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2101
2102        assert_eq!(&actual, &expected);
2103
2104        let array = UInt8Array::from(vec![Some(2), Some(10), None]);
2105        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2106
2107        assert_eq!(&actual, &expected);
2108
2109        let array = UInt16Array::from(vec![Some(2), Some(10), None]);
2110        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2111
2112        assert_eq!(&actual, &expected);
2113
2114        let array = UInt32Array::from(vec![Some(2), Some(10), None]);
2115        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2116
2117        assert_eq!(&actual, &expected);
2118
2119        let array = UInt64Array::from(vec![Some(2), Some(10), None]);
2120        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2121
2122        assert_eq!(&actual, &expected);
2123    }
2124
2125    #[test]
2126    fn test_cast_timestamp_to_integer() {
2127        let array = TimestampMillisecondArray::from(vec![Some(5), Some(1), None])
2128            .with_timezone("UTC".to_string());
2129        let expected = cast(&array, &DataType::Int64).unwrap();
2130
2131        let actual = cast(&cast(&array, &DataType::Int8).unwrap(), &DataType::Int64).unwrap();
2132        assert_eq!(&actual, &expected);
2133
2134        let actual = cast(&cast(&array, &DataType::Int16).unwrap(), &DataType::Int64).unwrap();
2135        assert_eq!(&actual, &expected);
2136
2137        let actual = cast(&cast(&array, &DataType::Int32).unwrap(), &DataType::Int64).unwrap();
2138        assert_eq!(&actual, &expected);
2139
2140        let actual = cast(&cast(&array, &DataType::UInt8).unwrap(), &DataType::Int64).unwrap();
2141        assert_eq!(&actual, &expected);
2142
2143        let actual = cast(&cast(&array, &DataType::UInt16).unwrap(), &DataType::Int64).unwrap();
2144        assert_eq!(&actual, &expected);
2145
2146        let actual = cast(&cast(&array, &DataType::UInt32).unwrap(), &DataType::Int64).unwrap();
2147        assert_eq!(&actual, &expected);
2148
2149        let actual = cast(&cast(&array, &DataType::UInt64).unwrap(), &DataType::Int64).unwrap();
2150        assert_eq!(&actual, &expected);
2151    }
2152
2153    #[test]
2154    #[cfg_attr(miri, ignore)] // Unsupported inline assembly
2155    fn test_cast_floating_to_timestamp() {
2156        let array = Int64Array::from(vec![Some(2), Some(10), None]);
2157        let expected = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2158
2159        let array = Float16Array::from(vec![
2160            Some(f16::from_f32(2.0)),
2161            Some(f16::from_f32(10.6)),
2162            None,
2163        ]);
2164        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2165
2166        assert_eq!(&actual, &expected);
2167
2168        let array = Float32Array::from(vec![Some(2.0), Some(10.6), None]);
2169        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2170
2171        assert_eq!(&actual, &expected);
2172
2173        let array = Float64Array::from(vec![Some(2.1), Some(10.2), None]);
2174        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2175
2176        assert_eq!(&actual, &expected);
2177    }
2178
2179    #[test]
2180    #[cfg_attr(miri, ignore)] // Unsupported inline assembly
2181    fn test_cast_timestamp_to_floating() {
2182        let array = TimestampMillisecondArray::from(vec![Some(5), Some(1), None])
2183            .with_timezone("UTC".to_string());
2184        let expected = cast(&array, &DataType::Int64).unwrap();
2185
2186        let actual = cast(&cast(&array, &DataType::Float16).unwrap(), &DataType::Int64).unwrap();
2187        assert_eq!(&actual, &expected);
2188
2189        let actual = cast(&cast(&array, &DataType::Float32).unwrap(), &DataType::Int64).unwrap();
2190        assert_eq!(&actual, &expected);
2191
2192        let actual = cast(&cast(&array, &DataType::Float64).unwrap(), &DataType::Int64).unwrap();
2193        assert_eq!(&actual, &expected);
2194    }
2195
2196    #[test]
2197    fn test_cast_decimal_to_timestamp() {
2198        let array = Int64Array::from(vec![Some(2), Some(10), None]);
2199        let expected = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2200
2201        let array = Decimal128Array::from(vec![Some(200), Some(1000), None])
2202            .with_precision_and_scale(4, 2)
2203            .unwrap();
2204        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2205
2206        assert_eq!(&actual, &expected);
2207
2208        let array = Decimal256Array::from(vec![
2209            Some(i256::from_i128(2000)),
2210            Some(i256::from_i128(10000)),
2211            None,
2212        ])
2213        .with_precision_and_scale(5, 3)
2214        .unwrap();
2215        let actual = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
2216
2217        assert_eq!(&actual, &expected);
2218    }
2219
2220    #[test]
2221    fn test_cast_timestamp_to_decimal() {
2222        let array = TimestampMillisecondArray::from(vec![Some(5), Some(1), None])
2223            .with_timezone("UTC".to_string());
2224        let expected = cast(&array, &DataType::Int64).unwrap();
2225
2226        let actual = cast(
2227            &cast(&array, &DataType::Decimal128(5, 2)).unwrap(),
2228            &DataType::Int64,
2229        )
2230        .unwrap();
2231        assert_eq!(&actual, &expected);
2232
2233        let actual = cast(
2234            &cast(&array, &DataType::Decimal256(10, 5)).unwrap(),
2235            &DataType::Int64,
2236        )
2237        .unwrap();
2238        assert_eq!(&actual, &expected);
2239    }
2240
2241    #[test]
2242    fn test_cast_date32_to_date64() {
2243        let a = Date32Array::from(vec![10000, 17890]);
2244        let array = Arc::new(a) as ArrayRef;
2245        let b = cast(&array, &DataType::Date64).unwrap();
2246        let c = b.as_primitive::<Date64Type>();
2247        assert_eq!(864000000000, c.value(0));
2248        assert_eq!(1545696000000, c.value(1));
2249    }
2250
2251    #[test]
2252    fn test_cast_date64_to_date32() {
2253        let a = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
2254        let array = Arc::new(a) as ArrayRef;
2255        let b = cast(&array, &DataType::Date32).unwrap();
2256        let c = b.as_primitive::<Date32Type>();
2257        assert_eq!(10000, c.value(0));
2258        assert_eq!(17890, c.value(1));
2259        assert!(c.is_null(2));
2260    }
2261
2262    #[test]
2263    fn test_cast_date64_to_date32_overflow() {
2264        let a = Date64Array::from(vec![i64::MAX]);
2265        let array = Arc::new(a) as ArrayRef;
2266
2267        let b = cast(&array, &DataType::Date32).unwrap();
2268        let c = b.as_primitive::<Date32Type>();
2269        assert!(c.is_null(0));
2270
2271        let options = CastOptions {
2272            safe: false,
2273            ..Default::default()
2274        };
2275        let err = cast_with_options(&array, &DataType::Date32, &options).unwrap_err();
2276        assert!(
2277            err.to_string().contains("Cannot cast Date64 value"),
2278            "{err}"
2279        );
2280    }
2281
2282    #[test]
2283    fn test_cast_string_to_timestamp() {
2284        let a0 = Arc::new(StringViewArray::from(vec![
2285            Some("2020-09-08T12:00:00.123456789+00:00"),
2286            Some("Not a valid date"),
2287            None,
2288        ])) as ArrayRef;
2289        let a1 = Arc::new(StringArray::from(vec![
2290            Some("2020-09-08T12:00:00.123456789+00:00"),
2291            Some("Not a valid date"),
2292            None,
2293        ])) as ArrayRef;
2294        let a2 = Arc::new(LargeStringArray::from(vec![
2295            Some("2020-09-08T12:00:00.123456789+00:00"),
2296            Some("Not a valid date"),
2297            None,
2298        ])) as ArrayRef;
2299        for array in &[a0, a1, a2] {
2300            for time_unit in &[
2301                TimeUnit::Second,
2302                TimeUnit::Millisecond,
2303                TimeUnit::Microsecond,
2304                TimeUnit::Nanosecond,
2305            ] {
2306                let to_type = DataType::Timestamp(*time_unit, None);
2307                let b = cast(array, &to_type).unwrap();
2308
2309                match time_unit {
2310                    TimeUnit::Second => {
2311                        let c = b.as_primitive::<TimestampSecondType>();
2312                        assert_eq!(1599566400, c.value(0));
2313                        assert!(c.is_null(1));
2314                        assert!(c.is_null(2));
2315                    }
2316                    TimeUnit::Millisecond => {
2317                        let c = b
2318                            .as_any()
2319                            .downcast_ref::<TimestampMillisecondArray>()
2320                            .unwrap();
2321                        assert_eq!(1599566400123, c.value(0));
2322                        assert!(c.is_null(1));
2323                        assert!(c.is_null(2));
2324                    }
2325                    TimeUnit::Microsecond => {
2326                        let c = b
2327                            .as_any()
2328                            .downcast_ref::<TimestampMicrosecondArray>()
2329                            .unwrap();
2330                        assert_eq!(1599566400123456, c.value(0));
2331                        assert!(c.is_null(1));
2332                        assert!(c.is_null(2));
2333                    }
2334                    TimeUnit::Nanosecond => {
2335                        let c = b
2336                            .as_any()
2337                            .downcast_ref::<TimestampNanosecondArray>()
2338                            .unwrap();
2339                        assert_eq!(1599566400123456789, c.value(0));
2340                        assert!(c.is_null(1));
2341                        assert!(c.is_null(2));
2342                    }
2343                }
2344
2345                let options = CastOptions {
2346                    safe: false,
2347                    format_options: FormatOptions::default(),
2348                };
2349                let err = cast_with_options(array, &to_type, &options).unwrap_err();
2350                assert_eq!(
2351                    err.to_string(),
2352                    "Parser error: Error parsing timestamp from 'Not a valid date': error parsing date"
2353                );
2354            }
2355        }
2356    }
2357
2358    #[test]
2359    fn test_cast_string_to_timestamp_overflow() {
2360        let array = StringArray::from(vec!["9800-09-08T12:00:00.123456789"]);
2361        let result = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap();
2362        let result = result.as_primitive::<TimestampSecondType>();
2363        assert_eq!(result.values(), &[247112596800]);
2364    }
2365
2366    #[test]
2367    fn test_cast_string_to_date32_with_surrounding_whitespace() {
2368        let array = StringArray::from(vec![" 2026-09-29 ", "2026-09-29"]);
2369
2370        let result = cast(&array, &DataType::Date32).unwrap();
2371        let result = result.as_primitive::<Date32Type>();
2372
2373        assert!(!result.is_null(0));
2374        assert_eq!(result.value(0), result.value(1));
2375    }
2376
2377    #[test]
2378    fn test_cast_string_to_date32() {
2379        let a0 = Arc::new(StringViewArray::from(vec![
2380            Some("2018-12-25"),
2381            Some("Not a valid date"),
2382            None,
2383        ])) as ArrayRef;
2384        let a1 = Arc::new(StringArray::from(vec![
2385            Some("2018-12-25"),
2386            Some("Not a valid date"),
2387            None,
2388        ])) as ArrayRef;
2389        let a2 = Arc::new(LargeStringArray::from(vec![
2390            Some("2018-12-25"),
2391            Some("Not a valid date"),
2392            None,
2393        ])) as ArrayRef;
2394        for array in &[a0, a1, a2] {
2395            let to_type = DataType::Date32;
2396            let b = cast(array, &to_type).unwrap();
2397            let c = b.as_primitive::<Date32Type>();
2398            assert_eq!(17890, c.value(0));
2399            assert!(c.is_null(1));
2400            assert!(c.is_null(2));
2401
2402            let options = CastOptions {
2403                safe: false,
2404                format_options: FormatOptions::default(),
2405            };
2406            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2407            assert_eq!(
2408                err.to_string(),
2409                "Cast error: Cannot cast string 'Not a valid date' to value of Date32 type"
2410            );
2411        }
2412    }
2413
2414    #[test]
2415    fn test_cast_string_with_large_date_to_date32() {
2416        let array = Arc::new(StringArray::from(vec![
2417            Some("+10999-12-31"),
2418            Some("-0010-02-28"),
2419            Some("0010-02-28"),
2420            Some("0000-01-01"),
2421            Some("-0000-01-01"),
2422            Some("-0001-01-01"),
2423        ])) as ArrayRef;
2424        let to_type = DataType::Date32;
2425        let options = CastOptions {
2426            safe: false,
2427            format_options: FormatOptions::default(),
2428        };
2429        let b = cast_with_options(&array, &to_type, &options).unwrap();
2430        let c = b.as_primitive::<Date32Type>();
2431        assert_eq!(3298139, c.value(0)); // 10999-12-31
2432        assert_eq!(-723122, c.value(1)); // -0010-02-28
2433        assert_eq!(-715817, c.value(2)); // 0010-02-28
2434        assert_eq!(c.value(3), c.value(4)); // Expect 0000-01-01 and -0000-01-01 to be parsed the same
2435        assert_eq!(-719528, c.value(3)); // 0000-01-01
2436        assert_eq!(-719528, c.value(4)); // -0000-01-01
2437        assert_eq!(-719893, c.value(5)); // -0001-01-01
2438    }
2439
2440    #[test]
2441    fn test_cast_invalid_string_with_large_date_to_date32() {
2442        // Large dates need to be prefixed with a + or - sign, otherwise they are not parsed correctly
2443        let array = Arc::new(StringArray::from(vec![Some("10999-12-31")])) as ArrayRef;
2444        let to_type = DataType::Date32;
2445        let options = CastOptions {
2446            safe: false,
2447            format_options: FormatOptions::default(),
2448        };
2449        let err = cast_with_options(&array, &to_type, &options).unwrap_err();
2450        assert_eq!(
2451            err.to_string(),
2452            "Cast error: Cannot cast string '10999-12-31' to value of Date32 type"
2453        );
2454    }
2455
2456    #[test]
2457    fn test_cast_string_format_yyyymmdd_to_date32() {
2458        let a0 = Arc::new(StringViewArray::from(vec![
2459            Some("2020-12-25"),
2460            Some("20201117"),
2461        ])) as ArrayRef;
2462        let a1 = Arc::new(StringArray::from(vec![
2463            Some("2020-12-25"),
2464            Some("20201117"),
2465        ])) as ArrayRef;
2466        let a2 = Arc::new(LargeStringArray::from(vec![
2467            Some("2020-12-25"),
2468            Some("20201117"),
2469        ])) as ArrayRef;
2470
2471        for array in &[a0, a1, a2] {
2472            let to_type = DataType::Date32;
2473            let options = CastOptions {
2474                safe: false,
2475                format_options: FormatOptions::default(),
2476            };
2477            let result = cast_with_options(&array, &to_type, &options).unwrap();
2478            let c = result.as_primitive::<Date32Type>();
2479            assert_eq!(
2480                chrono::NaiveDate::from_ymd_opt(2020, 12, 25),
2481                c.value_as_date(0)
2482            );
2483            assert_eq!(
2484                chrono::NaiveDate::from_ymd_opt(2020, 11, 17),
2485                c.value_as_date(1)
2486            );
2487        }
2488    }
2489
2490    #[test]
2491    fn test_cast_string_to_time32second() {
2492        let a0 = Arc::new(StringViewArray::from(vec![
2493            Some("08:08:35.091323414"),
2494            Some("08:08:60.091323414"), // leap second
2495            Some("08:08:61.091323414"), // not valid
2496            Some("Not a valid time"),
2497            None,
2498        ])) as ArrayRef;
2499        let a1 = Arc::new(StringArray::from(vec![
2500            Some("08:08:35.091323414"),
2501            Some("08:08:60.091323414"), // leap second
2502            Some("08:08:61.091323414"), // not valid
2503            Some("Not a valid time"),
2504            None,
2505        ])) as ArrayRef;
2506        let a2 = Arc::new(LargeStringArray::from(vec![
2507            Some("08:08:35.091323414"),
2508            Some("08:08:60.091323414"), // leap second
2509            Some("08:08:61.091323414"), // not valid
2510            Some("Not a valid time"),
2511            None,
2512        ])) as ArrayRef;
2513        for array in &[a0, a1, a2] {
2514            let to_type = DataType::Time32(TimeUnit::Second);
2515            let b = cast(array, &to_type).unwrap();
2516            let c = b.as_primitive::<Time32SecondType>();
2517            assert_eq!(29315, c.value(0));
2518            assert_eq!(29340, c.value(1));
2519            assert!(c.is_null(2));
2520            assert!(c.is_null(3));
2521            assert!(c.is_null(4));
2522
2523            let options = CastOptions {
2524                safe: false,
2525                format_options: FormatOptions::default(),
2526            };
2527            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2528            assert_eq!(
2529                err.to_string(),
2530                "Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(s) type"
2531            );
2532        }
2533    }
2534
2535    #[test]
2536    fn test_cast_string_to_time32millisecond() {
2537        let a0 = Arc::new(StringViewArray::from(vec![
2538            Some("08:08:35.091323414"),
2539            Some("08:08:60.091323414"), // leap second
2540            Some("08:08:61.091323414"), // not valid
2541            Some("Not a valid time"),
2542            None,
2543        ])) as ArrayRef;
2544        let a1 = Arc::new(StringArray::from(vec![
2545            Some("08:08:35.091323414"),
2546            Some("08:08:60.091323414"), // leap second
2547            Some("08:08:61.091323414"), // not valid
2548            Some("Not a valid time"),
2549            None,
2550        ])) as ArrayRef;
2551        let a2 = Arc::new(LargeStringArray::from(vec![
2552            Some("08:08:35.091323414"),
2553            Some("08:08:60.091323414"), // leap second
2554            Some("08:08:61.091323414"), // not valid
2555            Some("Not a valid time"),
2556            None,
2557        ])) as ArrayRef;
2558        for array in &[a0, a1, a2] {
2559            let to_type = DataType::Time32(TimeUnit::Millisecond);
2560            let b = cast(array, &to_type).unwrap();
2561            let c = b.as_primitive::<Time32MillisecondType>();
2562            assert_eq!(29315091, c.value(0));
2563            assert_eq!(29340091, c.value(1));
2564            assert!(c.is_null(2));
2565            assert!(c.is_null(3));
2566            assert!(c.is_null(4));
2567
2568            let options = CastOptions {
2569                safe: false,
2570                format_options: FormatOptions::default(),
2571            };
2572            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2573            assert_eq!(
2574                err.to_string(),
2575                "Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(ms) type"
2576            );
2577        }
2578    }
2579
2580    #[test]
2581    fn test_cast_string_to_time64microsecond() {
2582        let a0 = Arc::new(StringViewArray::from(vec![
2583            Some("08:08:35.091323414"),
2584            Some("Not a valid time"),
2585            None,
2586        ])) as ArrayRef;
2587        let a1 = Arc::new(StringArray::from(vec![
2588            Some("08:08:35.091323414"),
2589            Some("Not a valid time"),
2590            None,
2591        ])) as ArrayRef;
2592        let a2 = Arc::new(LargeStringArray::from(vec![
2593            Some("08:08:35.091323414"),
2594            Some("Not a valid time"),
2595            None,
2596        ])) as ArrayRef;
2597        for array in &[a0, a1, a2] {
2598            let to_type = DataType::Time64(TimeUnit::Microsecond);
2599            let b = cast(array, &to_type).unwrap();
2600            let c = b.as_primitive::<Time64MicrosecondType>();
2601            assert_eq!(29315091323, c.value(0));
2602            assert!(c.is_null(1));
2603            assert!(c.is_null(2));
2604
2605            let options = CastOptions {
2606                safe: false,
2607                format_options: FormatOptions::default(),
2608            };
2609            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2610            assert_eq!(
2611                err.to_string(),
2612                "Cast error: Cannot cast string 'Not a valid time' to value of Time64(µs) type"
2613            );
2614        }
2615    }
2616
2617    #[test]
2618    fn test_cast_string_to_time64nanosecond() {
2619        let a0 = Arc::new(StringViewArray::from(vec![
2620            Some("08:08:35.091323414"),
2621            Some("Not a valid time"),
2622            None,
2623        ])) as ArrayRef;
2624        let a1 = Arc::new(StringArray::from(vec![
2625            Some("08:08:35.091323414"),
2626            Some("Not a valid time"),
2627            None,
2628        ])) as ArrayRef;
2629        let a2 = Arc::new(LargeStringArray::from(vec![
2630            Some("08:08:35.091323414"),
2631            Some("Not a valid time"),
2632            None,
2633        ])) as ArrayRef;
2634        for array in &[a0, a1, a2] {
2635            let to_type = DataType::Time64(TimeUnit::Nanosecond);
2636            let b = cast(array, &to_type).unwrap();
2637            let c = b.as_primitive::<Time64NanosecondType>();
2638            assert_eq!(29315091323414, c.value(0));
2639            assert!(c.is_null(1));
2640            assert!(c.is_null(2));
2641
2642            let options = CastOptions {
2643                safe: false,
2644                format_options: FormatOptions::default(),
2645            };
2646            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2647            assert_eq!(
2648                err.to_string(),
2649                "Cast error: Cannot cast string 'Not a valid time' to value of Time64(ns) type"
2650            );
2651        }
2652    }
2653
2654    #[test]
2655    fn test_cast_string_to_date64() {
2656        let a0 = Arc::new(StringViewArray::from(vec![
2657            Some("2020-09-08T12:00:00"),
2658            Some("Not a valid date"),
2659            None,
2660        ])) as ArrayRef;
2661        let a1 = Arc::new(StringArray::from(vec![
2662            Some("2020-09-08T12:00:00"),
2663            Some("Not a valid date"),
2664            None,
2665        ])) as ArrayRef;
2666        let a2 = Arc::new(LargeStringArray::from(vec![
2667            Some("2020-09-08T12:00:00"),
2668            Some("Not a valid date"),
2669            None,
2670        ])) as ArrayRef;
2671        for array in &[a0, a1, a2] {
2672            let to_type = DataType::Date64;
2673            let b = cast(array, &to_type).unwrap();
2674            let c = b.as_primitive::<Date64Type>();
2675            assert_eq!(1599566400000, c.value(0));
2676            assert!(c.is_null(1));
2677            assert!(c.is_null(2));
2678
2679            let options = CastOptions {
2680                safe: false,
2681                format_options: FormatOptions::default(),
2682            };
2683            let err = cast_with_options(array, &to_type, &options).unwrap_err();
2684            assert_eq!(
2685                err.to_string(),
2686                "Cast error: Cannot cast string 'Not a valid date' to value of Date64 type"
2687            );
2688        }
2689    }
2690
2691    #[test]
2692    fn test_cast_date32_to_int32() {
2693        let array = Date32Array::from(vec![10000, 17890]);
2694        let b = cast(&array, &DataType::Int32).unwrap();
2695        let c = b.as_primitive::<Int32Type>();
2696        assert_eq!(10000, c.value(0));
2697        assert_eq!(17890, c.value(1));
2698    }
2699
2700    #[test]
2701    fn test_cast_int32_to_date32() {
2702        let array = Int32Array::from(vec![10000, 17890]);
2703        let b = cast(&array, &DataType::Date32).unwrap();
2704        let c = b.as_primitive::<Date32Type>();
2705        assert_eq!(10000, c.value(0));
2706        assert_eq!(17890, c.value(1));
2707    }
2708
2709    /// Compares arithmetic casts with Chrono for representable dates, including
2710    /// negative and fractional boundaries, nulls, and nonzero-offset slices.
2711    fn check_timestamp_casts<T: ArrowTimestampType>() {
2712        use rand::rngs::StdRng;
2713        use rand::{RngExt, SeedableRng};
2714
2715        let units = time_unit_multiple(&T::UNIT);
2716        let around = |x: i64| [x - 1, x, x + 1, -x - 1, -x, -x + 1];
2717        let mut values = vec![i64::MIN, i64::MAX];
2718        for base in [0, 60, 3_600, 86_400] {
2719            for seconds in around(base) {
2720                for fraction in [-1, 0, 1, units - 1] {
2721                    values.push(seconds * units + fraction);
2722                }
2723            }
2724        }
2725        for boundary in [1_000, 1_000_000] {
2726            values.extend(around(boundary));
2727        }
2728        let mut rng = StdRng::seed_from_u64(42);
2729        for _ in 0..256 {
2730            values.push(rng.random());
2731            let seconds = rng.random_range(-2_000_000_000..2_000_000_000);
2732            values.push(seconds * units + rng.random_range(0..units));
2733        }
2734        values.retain(|&v| as_datetime::<T>(v).is_some());
2735        let no_nulls = PrimitiveArray::<T>::new(values.clone().into(), None);
2736        let mixed = PrimitiveArray::<T>::from_iter(
2737            values
2738                .iter()
2739                .enumerate()
2740                .map(|(i, &v)| (i % 5 != 0).then_some(v)),
2741        );
2742        for array in [no_nulls, mixed.slice(1, mixed.len() - 2)] {
2743            let dates: Vec<_> = array
2744                .iter()
2745                .map(|v| v.map(|v| as_datetime::<T>(v).unwrap()))
2746                .collect();
2747            let expected: [ArrayRef; 5] = [
2748                Arc::new(Date32Array::from_iter(
2749                    dates
2750                        .iter()
2751                        .map(|d| d.map(|d| Date32Type::from_naive_date(d.date()))),
2752                )),
2753                Arc::new(Time32SecondArray::from_iter(
2754                    dates.iter().map(|d| d.map(|d| time_to_time32s(d.time()))),
2755                )),
2756                Arc::new(Time32MillisecondArray::from_iter(
2757                    dates.iter().map(|d| d.map(|d| time_to_time32ms(d.time()))),
2758                )),
2759                Arc::new(Time64MicrosecondArray::from_iter(
2760                    dates.iter().map(|d| d.map(|d| time_to_time64us(d.time()))),
2761                )),
2762                Arc::new(Time64NanosecondArray::from_iter(
2763                    dates.iter().map(|d| d.map(|d| time_to_time64ns(d.time()))),
2764                )),
2765            ];
2766            for expected in expected {
2767                let actual = cast(&array, expected.data_type()).unwrap();
2768                assert_eq!(actual.as_ref(), expected.as_ref(), "{}", T::DATA_TYPE);
2769            }
2770        }
2771    }
2772
2773    #[test]
2774    fn test_cast_timestamp_without_timezone_matches_chrono() {
2775        check_timestamp_casts::<TimestampSecondType>();
2776        check_timestamp_casts::<TimestampMillisecondType>();
2777        check_timestamp_casts::<TimestampMicrosecondType>();
2778        check_timestamp_casts::<TimestampNanosecondType>();
2779    }
2780
2781    #[test]
2782    fn test_cast_timestamp_to_time_extremes() {
2783        fn check<T: ArrowTimestampType>(min: (u32, u32, u32, u32), max: (u32, u32, u32, u32)) {
2784            let time = |(h, m, s, ns)| NaiveTime::from_hms_nano_opt(h, m, s, ns).unwrap();
2785            let times = [Some(time(min)), None, Some(time(max))];
2786            let array = PrimitiveArray::<T>::from_iter([Some(i64::MIN), None, Some(i64::MAX)]);
2787            let expected: [ArrayRef; 4] = [
2788                Arc::new(Time32SecondArray::from_iter(
2789                    times.map(|v| v.map(time_to_time32s)),
2790                )),
2791                Arc::new(Time32MillisecondArray::from_iter(
2792                    times.map(|v| v.map(time_to_time32ms)),
2793                )),
2794                Arc::new(Time64MicrosecondArray::from_iter(
2795                    times.map(|v| v.map(time_to_time64us)),
2796                )),
2797                Arc::new(Time64NanosecondArray::from_iter(
2798                    times.map(|v| v.map(time_to_time64ns)),
2799                )),
2800            ];
2801            for expected in expected {
2802                assert_eq!(
2803                    cast(&array, expected.data_type()).unwrap().as_ref(),
2804                    expected.as_ref()
2805                );
2806            }
2807        }
2808        check::<TimestampSecondType>((8, 29, 52, 0), (15, 30, 7, 0));
2809        check::<TimestampMillisecondType>((16, 47, 4, 192_000_000), (7, 12, 55, 807_000_000));
2810        check::<TimestampMicrosecondType>((19, 59, 5, 224_192_000), (4, 0, 54, 775_807_000));
2811        // Nanosecond extremes are representable in Chrono and covered above.
2812    }
2813
2814    #[test]
2815    fn test_cast_timestamp_to_date32_range() {
2816        fn check<T: ArrowTimestampType>() {
2817            let day = SECONDS_IN_DAY * time_unit_multiple(&T::UNIT);
2818            let first = i32::MIN as i64 * day;
2819            let last = (i32::MAX as i64 + 1) * day - 1;
2820            let array = PrimitiveArray::<T>::new(
2821                vec![first, i64::MAX, last].into(),
2822                Some(NullBuffer::from(vec![true, false, true])),
2823            );
2824            let expected = Date32Array::from(vec![Some(i32::MIN), None, Some(i32::MAX)]);
2825            for safe in [true, false] {
2826                let options = CastOptions {
2827                    safe,
2828                    ..Default::default()
2829                };
2830                assert_eq!(
2831                    cast_with_options(&array, &Date32, &options)
2832                        .unwrap()
2833                        .as_ref(),
2834                    &expected
2835                );
2836            }
2837            // Day counts that do not fit in i32 become null when safe, otherwise an error.
2838            let array = PrimitiveArray::<T>::from_iter_values([
2839                first - 1,
2840                last,
2841                last + 1,
2842                i64::MIN,
2843                i64::MAX,
2844            ]);
2845            let expected = Date32Array::from(vec![None, Some(i32::MAX), None, None, None]);
2846            assert_eq!(cast(&array, &Date32).unwrap().as_ref(), &expected);
2847            let options = CastOptions {
2848                safe: false,
2849                ..Default::default()
2850            };
2851            assert!(cast_with_options(&array, &Date32, &options).is_err());
2852        }
2853        check::<TimestampSecondType>();
2854        check::<TimestampMillisecondType>();
2855        // The entire microsecond domain fits in Date32, including dates outside Chrono's range.
2856        let array = TimestampMicrosecondArray::from(vec![Some(i64::MIN), None, Some(i64::MAX)]);
2857        assert_eq!(
2858            cast(&array, &Date32).unwrap().as_ref(),
2859            &Date32Array::from(vec![Some(-106_751_992), None, Some(106_751_991)]),
2860        );
2861    }
2862
2863    #[test]
2864    fn test_cast_timestamp_date_time_timezone_validation() {
2865        let invalid = TimestampSecondArray::from(vec![0]).with_timezone("invalid timezone");
2866        let extreme = TimestampSecondArray::from(vec![0, i64::MAX]).with_timezone("+00:00");
2867        let options = CastOptions {
2868            safe: false,
2869            ..Default::default()
2870        };
2871        for target in [
2872            Date32,
2873            Time32(TimeUnit::Second),
2874            Time32(TimeUnit::Millisecond),
2875            Time64(TimeUnit::Microsecond),
2876            Time64(TimeUnit::Nanosecond),
2877        ] {
2878            // A timezone that fails to parse is an error even when the cast is safe.
2879            assert!(cast(&invalid, &target).is_err());
2880            // A timestamp outside Chrono's date range is null when safe, otherwise an error.
2881            let actual = cast(&extreme, &target).unwrap();
2882            assert!(actual.is_valid(0));
2883            assert!(actual.is_null(1));
2884            assert!(cast_with_options(&extreme, &target, &options).is_err());
2885        }
2886    }
2887
2888    #[test]
2889    fn test_cast_timestamp_to_date32() {
2890        let array =
2891            TimestampMillisecondArray::from(vec![Some(864000000005), Some(1545696000001), None])
2892                .with_timezone("+00:00".to_string());
2893        let b = cast(&array, &DataType::Date32).unwrap();
2894        let c = b.as_primitive::<Date32Type>();
2895        assert_eq!(10000, c.value(0));
2896        assert_eq!(17890, c.value(1));
2897        assert!(c.is_null(2));
2898    }
2899    #[test]
2900    fn test_cast_timestamp_to_date32_zone() {
2901        let strings = StringArray::from_iter([
2902            Some("1970-01-01T00:00:01"),
2903            Some("1970-01-01T23:59:59"),
2904            None,
2905            Some("2020-03-01T02:00:23+00:00"),
2906        ]);
2907        let dt = DataType::Timestamp(TimeUnit::Millisecond, Some("-07:00".into()));
2908        let timestamps = cast(&strings, &dt).unwrap();
2909        let dates = cast(timestamps.as_ref(), &DataType::Date32).unwrap();
2910
2911        let c = dates.as_primitive::<Date32Type>();
2912        let expected = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
2913        assert_eq!(c.value_as_date(0).unwrap(), expected);
2914        assert_eq!(c.value_as_date(1).unwrap(), expected);
2915        assert!(c.is_null(2));
2916        let expected = NaiveDate::from_ymd_opt(2020, 2, 29).unwrap();
2917        assert_eq!(c.value_as_date(3).unwrap(), expected);
2918    }
2919    #[test]
2920    fn test_cast_timestamp_to_date64() {
2921        let array =
2922            TimestampMillisecondArray::from(vec![Some(864000000005), Some(1545696000001), None]);
2923        let b = cast(&array, &DataType::Date64).unwrap();
2924        let c = b.as_primitive::<Date64Type>();
2925        assert_eq!(864000000000, c.value(0));
2926        assert_eq!(1545696000000, c.value(1));
2927        assert!(c.is_null(2));
2928
2929        let array = TimestampSecondArray::from(vec![Some(864000000005), Some(1545696000001)]);
2930        let b = cast(&array, &DataType::Date64).unwrap();
2931        let c = b.as_primitive::<Date64Type>();
2932        assert_eq!(864000000000000, c.value(0));
2933        assert_eq!(1545696000000000, c.value(1));
2934
2935        // test overflow, safe cast
2936        let array = TimestampSecondArray::from(vec![Some(i64::MAX)]);
2937        let b = cast(&array, &DataType::Date64).unwrap();
2938        assert!(b.is_null(0));
2939        // test overflow, unsafe cast
2940        let array = TimestampSecondArray::from(vec![Some(i64::MAX)]);
2941        let options = CastOptions {
2942            safe: false,
2943            format_options: FormatOptions::default(),
2944        };
2945        let b = cast_with_options(&array, &DataType::Date64, &options);
2946        assert!(b.is_err());
2947    }
2948
2949    #[test]
2950    fn test_cast_timestamp_to_date64_whole_days() {
2951        // 2024-05-01T10:30:00, 1970-01-01T00:00:00, and one millisecond before the epoch
2952        let millis: [i64; 3] = [1_714_559_400_000, 0, -1];
2953        let expected = Date64Array::from(vec![1_714_521_600_000, 0, -MILLISECONDS_IN_DAY]);
2954        let arrays: [ArrayRef; 4] = [
2955            Arc::new(TimestampSecondArray::from(
2956                millis.map(|x| x.div_euclid(1_000)).to_vec(),
2957            )),
2958            Arc::new(TimestampMillisecondArray::from(millis.to_vec())),
2959            Arc::new(TimestampMicrosecondArray::from(
2960                millis.map(|x| x * 1_000).to_vec(),
2961            )),
2962            Arc::new(TimestampNanosecondArray::from(
2963                millis.map(|x| x * 1_000_000).to_vec(),
2964            )),
2965        ];
2966        for array in arrays {
2967            let actual = cast(&array, &DataType::Date64).unwrap();
2968            let actual = actual.as_primitive::<Date64Type>();
2969            // The second timestamp array rounds -1ms down to -1s, which is still the
2970            // day before the epoch.
2971            assert_eq!(actual, &expected, "{}", array.data_type());
2972        }
2973
2974        // With a timezone the date is the local date, as for Date32.
2975        // 1970-01-01T00:00:01Z and 1970-01-01T20:00:00Z are 1969-12-31 and 1970-01-01 in -05:00.
2976        let array = TimestampSecondArray::from(vec![1, 72_000]).with_timezone("-05:00");
2977        let date64 = cast(&array, &DataType::Date64).unwrap();
2978        assert_eq!(
2979            date64.as_primitive::<Date64Type>(),
2980            &Date64Array::from(vec![-MILLISECONDS_IN_DAY, 0])
2981        );
2982        let date32 = cast(&array, &DataType::Date32).unwrap();
2983        assert_eq!(
2984            cast(&date32, &DataType::Date64).unwrap().as_ref(),
2985            date64.as_ref()
2986        );
2987
2988        // Flooring i64::MIN milliseconds to a whole day overflows.
2989        let array = TimestampMillisecondArray::from(vec![i64::MIN]);
2990        assert!(cast(&array, &DataType::Date64).unwrap().is_null(0));
2991        let options = CastOptions {
2992            safe: false,
2993            ..Default::default()
2994        };
2995        assert!(cast_with_options(&array, &DataType::Date64, &options).is_err());
2996    }
2997
2998    #[test]
2999    fn test_cast_timestamp_to_time64() {
3000        // test timestamp secs
3001        let array = TimestampSecondArray::from(vec![Some(86405), Some(1), None])
3002            .with_timezone("+01:00".to_string());
3003        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
3004        let c = b.as_primitive::<Time64MicrosecondType>();
3005        assert_eq!(3605000000, c.value(0));
3006        assert_eq!(3601000000, c.value(1));
3007        assert!(c.is_null(2));
3008        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
3009        let c = b.as_primitive::<Time64NanosecondType>();
3010        assert_eq!(3605000000000, c.value(0));
3011        assert_eq!(3601000000000, c.value(1));
3012        assert!(c.is_null(2));
3013
3014        // test timestamp milliseconds
3015        let a = TimestampMillisecondArray::from(vec![Some(86405000), Some(1000), None])
3016            .with_timezone("+01:00".to_string());
3017        let array = Arc::new(a) as ArrayRef;
3018        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
3019        let c = b.as_primitive::<Time64MicrosecondType>();
3020        assert_eq!(3605000000, c.value(0));
3021        assert_eq!(3601000000, c.value(1));
3022        assert!(c.is_null(2));
3023        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
3024        let c = b.as_primitive::<Time64NanosecondType>();
3025        assert_eq!(3605000000000, c.value(0));
3026        assert_eq!(3601000000000, c.value(1));
3027        assert!(c.is_null(2));
3028
3029        // test timestamp microseconds
3030        let a = TimestampMicrosecondArray::from(vec![Some(86405000000), Some(1000000), None])
3031            .with_timezone("+01:00".to_string());
3032        let array = Arc::new(a) as ArrayRef;
3033        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
3034        let c = b.as_primitive::<Time64MicrosecondType>();
3035        assert_eq!(3605000000, c.value(0));
3036        assert_eq!(3601000000, c.value(1));
3037        assert!(c.is_null(2));
3038        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
3039        let c = b.as_primitive::<Time64NanosecondType>();
3040        assert_eq!(3605000000000, c.value(0));
3041        assert_eq!(3601000000000, c.value(1));
3042        assert!(c.is_null(2));
3043
3044        // Test fractional timestamps on both sides of the epoch.
3045        let a = TimestampNanosecondArray::from(vec![Some(86_405_123_456_789), Some(-1), None])
3046            .with_timezone("+01:00".to_string());
3047        let array = Arc::new(a) as ArrayRef;
3048        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
3049        let c = b.as_primitive::<Time64MicrosecondType>();
3050        assert_eq!(3_605_123_456, c.value(0));
3051        assert_eq!(3_599_999_999, c.value(1));
3052        assert!(c.is_null(2));
3053        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
3054        let c = b.as_primitive::<Time64NanosecondType>();
3055        assert_eq!(3_605_123_456_789, c.value(0));
3056        assert_eq!(3_599_999_999_999, c.value(1));
3057        assert!(c.is_null(2));
3058
3059        // test overflow, safe cast
3060        let a =
3061            TimestampSecondArray::from(vec![Some(i64::MAX)]).with_timezone("+01:00".to_string());
3062        let array = Arc::new(a) as ArrayRef;
3063        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
3064        assert!(b.is_null(0));
3065        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
3066        assert!(b.is_null(0));
3067        // test overflow, unsafe cast
3068        let options = CastOptions {
3069            safe: false,
3070            ..Default::default()
3071        };
3072        let b = cast_with_options(&array, &DataType::Time64(TimeUnit::Microsecond), &options);
3073        assert!(b.is_err());
3074        let b = cast_with_options(&array, &DataType::Time64(TimeUnit::Nanosecond), &options);
3075        assert!(b.is_err());
3076        // Time64 only supports microseconds and nanoseconds
3077        let b = cast(&array, &DataType::Time64(TimeUnit::Millisecond));
3078        assert!(b.is_err());
3079    }
3080
3081    #[test]
3082    fn test_cast_timestamp_to_time32() {
3083        // test timestamp secs
3084        let a = TimestampSecondArray::from(vec![Some(86405), Some(1), None])
3085            .with_timezone("+01:00".to_string());
3086        let array = Arc::new(a) as ArrayRef;
3087        let b = cast(&array, &DataType::Time32(TimeUnit::Second)).unwrap();
3088        let c = b.as_primitive::<Time32SecondType>();
3089        assert_eq!(3605, c.value(0));
3090        assert_eq!(3601, c.value(1));
3091        assert!(c.is_null(2));
3092        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
3093        let c = b.as_primitive::<Time32MillisecondType>();
3094        assert_eq!(3605000, c.value(0));
3095        assert_eq!(3601000, c.value(1));
3096        assert!(c.is_null(2));
3097
3098        // test timestamp milliseconds
3099        let a = TimestampMillisecondArray::from(vec![Some(86405000), Some(1000), None])
3100            .with_timezone("+01:00".to_string());
3101        let array = Arc::new(a) as ArrayRef;
3102        let b = cast(&array, &DataType::Time32(TimeUnit::Second)).unwrap();
3103        let c = b.as_primitive::<Time32SecondType>();
3104        assert_eq!(3605, c.value(0));
3105        assert_eq!(3601, c.value(1));
3106        assert!(c.is_null(2));
3107        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
3108        let c = b.as_primitive::<Time32MillisecondType>();
3109        assert_eq!(3605000, c.value(0));
3110        assert_eq!(3601000, c.value(1));
3111        assert!(c.is_null(2));
3112
3113        // test timestamp microseconds
3114        let a = TimestampMicrosecondArray::from(vec![Some(86405000000), Some(1000000), None])
3115            .with_timezone("+01:00".to_string());
3116        let array = Arc::new(a) as ArrayRef;
3117        let b = cast(&array, &DataType::Time32(TimeUnit::Second)).unwrap();
3118        let c = b.as_primitive::<Time32SecondType>();
3119        assert_eq!(3605, c.value(0));
3120        assert_eq!(3601, c.value(1));
3121        assert!(c.is_null(2));
3122        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
3123        let c = b.as_primitive::<Time32MillisecondType>();
3124        assert_eq!(3605000, c.value(0));
3125        assert_eq!(3601000, c.value(1));
3126        assert!(c.is_null(2));
3127
3128        // Test fractional timestamps on both sides of the epoch.
3129        let a = TimestampNanosecondArray::from(vec![Some(86_405_123_456_789), Some(-1), None])
3130            .with_timezone("+01:00".to_string());
3131        let array = Arc::new(a) as ArrayRef;
3132        let b = cast(&array, &DataType::Time32(TimeUnit::Second)).unwrap();
3133        let c = b.as_primitive::<Time32SecondType>();
3134        assert_eq!(3605, c.value(0));
3135        assert_eq!(3599, c.value(1));
3136        assert!(c.is_null(2));
3137        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
3138        let c = b.as_primitive::<Time32MillisecondType>();
3139        assert_eq!(3_605_123, c.value(0));
3140        assert_eq!(3_599_999, c.value(1));
3141        assert!(c.is_null(2));
3142
3143        // test overflow, safe cast
3144        let a =
3145            TimestampSecondArray::from(vec![Some(i64::MAX)]).with_timezone("+01:00".to_string());
3146        let array = Arc::new(a) as ArrayRef;
3147        let b = cast(&array, &DataType::Time32(TimeUnit::Second)).unwrap();
3148        assert!(b.is_null(0));
3149        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
3150        assert!(b.is_null(0));
3151        // test overflow, unsafe cast
3152        let options = CastOptions {
3153            safe: false,
3154            ..Default::default()
3155        };
3156        let b = cast_with_options(&array, &DataType::Time32(TimeUnit::Second), &options);
3157        assert!(b.is_err());
3158        let b = cast_with_options(&array, &DataType::Time32(TimeUnit::Millisecond), &options);
3159        assert!(b.is_err());
3160    }
3161
3162    // Cast Timestamp(_, None) -> Timestamp(_, Some(timezone))
3163    #[test]
3164    fn test_cast_timestamp_with_timezone_1() {
3165        let string_array: Arc<dyn Array> = Arc::new(StringArray::from(vec![
3166            Some("2000-01-01T00:00:00.123456789"),
3167            Some("2010-01-01T00:00:00.123456789"),
3168            None,
3169        ]));
3170        let to_type = DataType::Timestamp(TimeUnit::Nanosecond, None);
3171        let timestamp_array = cast(&string_array, &to_type).unwrap();
3172
3173        let to_type = DataType::Timestamp(TimeUnit::Microsecond, Some("+0700".into()));
3174        let timestamp_array = cast(&timestamp_array, &to_type).unwrap();
3175
3176        let string_array = cast(&timestamp_array, &DataType::Utf8).unwrap();
3177        let result = string_array.as_string::<i32>();
3178        assert_eq!("2000-01-01T00:00:00.123456+07:00", result.value(0));
3179        assert_eq!("2010-01-01T00:00:00.123456+07:00", result.value(1));
3180        assert!(result.is_null(2));
3181    }
3182
3183    // Cast Timestamp(_, Some(timezone)) -> Timestamp(_, None)
3184    #[test]
3185    fn test_cast_timestamp_with_timezone_2() {
3186        let string_array: Arc<dyn Array> = Arc::new(StringArray::from(vec![
3187            Some("2000-01-01T07:00:00.123456789"),
3188            Some("2010-01-01T07:00:00.123456789"),
3189            None,
3190        ]));
3191        let to_type = DataType::Timestamp(TimeUnit::Millisecond, Some("+0700".into()));
3192        let timestamp_array = cast(&string_array, &to_type).unwrap();
3193
3194        // Check intermediate representation is correct
3195        let string_array = cast(&timestamp_array, &DataType::Utf8).unwrap();
3196        let result = string_array.as_string::<i32>();
3197        assert_eq!("2000-01-01T07:00:00.123+07:00", result.value(0));
3198        assert_eq!("2010-01-01T07:00:00.123+07:00", result.value(1));
3199        assert!(result.is_null(2));
3200
3201        let to_type = DataType::Timestamp(TimeUnit::Nanosecond, None);
3202        let timestamp_array = cast(&timestamp_array, &to_type).unwrap();
3203
3204        let string_array = cast(&timestamp_array, &DataType::Utf8).unwrap();
3205        let result = string_array.as_string::<i32>();
3206        assert_eq!("2000-01-01T00:00:00.123", result.value(0));
3207        assert_eq!("2010-01-01T00:00:00.123", result.value(1));
3208        assert!(result.is_null(2));
3209    }
3210
3211    // Cast Timestamp(_, Some(timezone)) -> Timestamp(_, Some(timezone))
3212    #[test]
3213    fn test_cast_timestamp_with_timezone_3() {
3214        let string_array: Arc<dyn Array> = Arc::new(StringArray::from(vec![
3215            Some("2000-01-01T07:00:00.123456789"),
3216            Some("2010-01-01T07:00:00.123456789"),
3217            None,
3218        ]));
3219        let to_type = DataType::Timestamp(TimeUnit::Microsecond, Some("+0700".into()));
3220        let timestamp_array = cast(&string_array, &to_type).unwrap();
3221
3222        // Check intermediate representation is correct
3223        let string_array = cast(&timestamp_array, &DataType::Utf8).unwrap();
3224        let result = string_array.as_string::<i32>();
3225        assert_eq!("2000-01-01T07:00:00.123456+07:00", result.value(0));
3226        assert_eq!("2010-01-01T07:00:00.123456+07:00", result.value(1));
3227        assert!(result.is_null(2));
3228
3229        let to_type = DataType::Timestamp(TimeUnit::Second, Some("-08:00".into()));
3230        let timestamp_array = cast(&timestamp_array, &to_type).unwrap();
3231
3232        let string_array = cast(&timestamp_array, &DataType::Utf8).unwrap();
3233        let result = string_array.as_string::<i32>();
3234        assert_eq!("1999-12-31T16:00:00-08:00", result.value(0));
3235        assert_eq!("2009-12-31T16:00:00-08:00", result.value(1));
3236        assert!(result.is_null(2));
3237    }
3238
3239    /// The i64 value of a `Timestamp(Second, None)` holding the given wall clock
3240    /// reading (a naive timestamp is stored as if it were UTC).
3241    fn naive_seconds(y: i32, m: u32, d: u32, h: u32, min: u32) -> i64 {
3242        NaiveDate::from_ymd_opt(y, m, d)
3243            .unwrap()
3244            .and_hms_opt(h, min, 0)
3245            .unwrap()
3246            .and_utc()
3247            .timestamp()
3248    }
3249
3250    /// The instant, in seconds since the epoch, denoted by the given wall clock
3251    /// reading at a fixed offset of `offset_hours`.
3252    fn instant_seconds(y: i32, m: u32, d: u32, h: u32, min: u32, offset_hours: i32) -> i64 {
3253        let offset = FixedOffset::east_opt(offset_hours * 3600).unwrap();
3254        NaiveDate::from_ymd_opt(y, m, d)
3255            .unwrap()
3256            .and_hms_opt(h, min, 0)
3257            .unwrap()
3258            .and_local_timezone(offset)
3259            .unwrap()
3260            .timestamp()
3261    }
3262
3263    // Cast Timestamp(_, None) -> Timestamp(_, Some(IANA timezone)) across DST
3264    // transitions. See `resolve_local_offset`.
3265    #[test]
3266    fn test_cast_timestamp_to_named_timezone_dst() {
3267        // Unambiguous, EDT (-04:00) is in effect.
3268        let unambiguous = naive_seconds(2024, 11, 1, 0, 0);
3269        // Ambiguous: the clocks go back at 2024-11-03T02:00 EDT, so 01:30
3270        // happens twice, first at -04:00 and then at -05:00.
3271        let ambiguous = naive_seconds(2024, 11, 3, 1, 30);
3272        // Nonexistent: the clocks go forward at 2024-03-10T02:00 EST, so 02:30
3273        // never happens.
3274        let nonexistent = naive_seconds(2024, 3, 10, 2, 30);
3275        assert_eq!(
3276            [unambiguous, ambiguous, nonexistent],
3277            [1_730_419_200, 1_730_597_400, 1_710_037_800]
3278        );
3279
3280        let array = TimestampSecondArray::from(vec![
3281            Some(unambiguous),
3282            Some(ambiguous),
3283            Some(nonexistent),
3284            None,
3285        ]);
3286        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/New_York".into()));
3287        let options = CastOptions {
3288            safe: false,
3289            ..Default::default()
3290        };
3291
3292        let b = cast_with_options(&array, &to_type, &options).unwrap();
3293        assert_eq!(b.data_type(), &to_type);
3294        let c = b.as_primitive::<TimestampSecondType>();
3295
3296        assert_eq!(c.value(0), instant_seconds(2024, 11, 1, 0, 0, -4));
3297        assert_eq!(c.value(0), 1_730_433_600);
3298        // The later of the two candidates, i.e. EST rather than EDT.
3299        assert_eq!(c.value(1), instant_seconds(2024, 11, 3, 1, 30, -5));
3300        assert_eq!(c.value(1), 1_730_615_400);
3301        // Shifted forward by the one hour gap: 02:30 EST is 03:30 EDT.
3302        assert_eq!(c.value(2), instant_seconds(2024, 3, 10, 2, 30, -5));
3303        assert_eq!(c.value(2), instant_seconds(2024, 3, 10, 3, 30, -4));
3304        assert_eq!(c.value(2), 1_710_055_800);
3305        assert!(c.is_null(3));
3306    }
3307
3308    /// The rows of the string array used by the string -> timestamp DST tests,
3309    /// and the instants they denote in `America/New_York` according to
3310    /// PostgreSQL 17.11.
3311    ///
3312    /// They deliberately straddle both transitions of 2024, so a single offset
3313    /// resolved once for the whole array cannot satisfy all of them.
3314    const DST_STRINGS: [&str; 5] = [
3315        // EDT (-04:00), before the November transition.
3316        "2024-11-02 12:00:00",
3317        // Ambiguous: 01:30 happens twice, the later (EST) instant wins.
3318        "2024-11-03 01:30:00",
3319        // EST (-05:00), after the November transition.
3320        "2024-11-03 12:00:00",
3321        // Nonexistent: 02:30 is skipped in March and shifts to 03:30 EDT.
3322        "2024-03-10 02:30:00",
3323        // EST (-05:00), before the March transition.
3324        "2024-03-09 12:00:00",
3325    ];
3326
3327    const DST_SECONDS: [i64; 5] = [
3328        1_730_563_200,
3329        1_730_615_400,
3330        1_730_653_200,
3331        1_710_055_800,
3332        1_710_003_600,
3333    ];
3334
3335    // Casting strings to `Timestamp(_, Some(tz))` goes through
3336    // `string_to_datetime`, not through `adjust_timestamp_to_timezone`, so it
3337    // needs its own coverage of the DST rules. See `crate::local_time`.
3338    #[test]
3339    fn test_cast_string_to_named_timezone_dst() {
3340        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/New_York".into()));
3341        let options = CastOptions {
3342            safe: false,
3343            ..Default::default()
3344        };
3345
3346        let mut values: Vec<Option<&str>> = DST_STRINGS.iter().copied().map(Some).collect();
3347        values.push(None);
3348
3349        let arrays: Vec<ArrayRef> = vec![
3350            Arc::new(StringArray::from(values.clone())),
3351            Arc::new(LargeStringArray::from(values.clone())),
3352            Arc::new(StringViewArray::from(values)),
3353        ];
3354
3355        for array in arrays {
3356            let from_type = array.data_type().clone();
3357            let b = cast_with_options(&array, &to_type, &options)
3358                .unwrap_or_else(|e| panic!("{from_type:?}: {e}"));
3359            assert_eq!(b.data_type(), &to_type);
3360            let c = b.as_primitive::<TimestampSecondType>();
3361            for (i, expected) in DST_SECONDS.iter().enumerate() {
3362                assert_eq!(c.value(i), *expected, "{from_type:?} row {i}");
3363            }
3364            assert!(c.is_null(5), "{from_type:?} null row");
3365        }
3366    }
3367
3368    // The same values must not silently become null under `safe` casting either.
3369    #[test]
3370    fn test_cast_string_to_named_timezone_dst_safe() {
3371        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/New_York".into()));
3372        let options = CastOptions {
3373            safe: true,
3374            ..Default::default()
3375        };
3376
3377        let array = StringArray::from(vec![
3378            Some(DST_STRINGS[1]),
3379            Some(DST_STRINGS[3]),
3380            Some("not a timestamp"),
3381            None,
3382        ]);
3383
3384        let b = cast_with_options(&array, &to_type, &options).unwrap();
3385        let c = b.as_primitive::<TimestampSecondType>();
3386        assert_eq!(c.value(0), DST_SECONDS[1]);
3387        assert_eq!(c.value(1), DST_SECONDS[3]);
3388        // Genuinely unparsable input still becomes null.
3389        assert!(c.is_null(2));
3390        assert!(c.is_null(3));
3391        assert_eq!(c.null_count(), 2);
3392    }
3393
3394    // Sub-second precision survives the shift applied to a nonexistent reading.
3395    #[test]
3396    fn test_cast_string_to_named_timezone_dst_nanos() {
3397        let to_type = DataType::Timestamp(TimeUnit::Nanosecond, Some("America/New_York".into()));
3398        let options = CastOptions {
3399            safe: false,
3400            ..Default::default()
3401        };
3402
3403        let array = StringArray::from(vec![
3404            "2024-03-10 02:30:00.123456789",
3405            "2024-11-03 01:30:00.123456789",
3406        ]);
3407        let b = cast_with_options(&array, &to_type, &options).unwrap();
3408        let c = b.as_primitive::<TimestampNanosecondType>();
3409        assert_eq!(c.value(0), 1_710_055_800 * 1_000_000_000 + 123_456_789);
3410        assert_eq!(c.value(1), 1_730_615_400 * 1_000_000_000 + 123_456_789);
3411    }
3412
3413    // A date-only string reads local midnight, which is itself skipped or
3414    // repeated in some zones.
3415    #[test]
3416    fn test_cast_string_to_named_timezone_dst_date_only() {
3417        let options = CastOptions {
3418            safe: false,
3419            ..Default::default()
3420        };
3421
3422        // Local midnight does not exist in Sao Paulo on 2018-11-04.
3423        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/Sao_Paulo".into()));
3424        let array = StringArray::from(vec!["2018-11-04"]);
3425        let b = cast_with_options(&array, &to_type, &options).unwrap();
3426        assert_eq!(
3427            b.as_primitive::<TimestampSecondType>().value(0),
3428            1_541_300_400
3429        );
3430
3431        // Local midnight happens twice in Havana on 2024-11-03.
3432        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/Havana".into()));
3433        let array = StringArray::from(vec!["2024-11-03"]);
3434        let b = cast_with_options(&array, &to_type, &options).unwrap();
3435        assert_eq!(
3436            b.as_primitive::<TimestampSecondType>().value(0),
3437            1_730_610_000
3438        );
3439    }
3440
3441    // A timezone named by the string itself is resolved the same way, matching
3442    // PostgreSQL.
3443    #[test]
3444    fn test_cast_string_to_timezone_named_in_string_dst() {
3445        let to_type = DataType::Timestamp(TimeUnit::Second, Some("UTC".into()));
3446        let options = CastOptions {
3447            safe: false,
3448            ..Default::default()
3449        };
3450
3451        let array = StringArray::from(vec![
3452            "2024-03-10 02:30:00 America/New_York",
3453            "2024-11-03 01:30:00 America/New_York",
3454        ]);
3455        let b = cast_with_options(&array, &to_type, &options).unwrap();
3456        let c = b.as_primitive::<TimestampSecondType>();
3457        assert_eq!(c.value(0), 1_710_055_800);
3458        assert_eq!(c.value(1), 1_730_615_400);
3459    }
3460
3461    // The same values must not become null when `safe` casting is requested.
3462    #[test]
3463    fn test_cast_timestamp_to_named_timezone_dst_safe() {
3464        let array = TimestampSecondArray::from(vec![
3465            Some(naive_seconds(2024, 11, 1, 0, 0)),
3466            Some(naive_seconds(2024, 11, 3, 1, 30)),
3467            Some(naive_seconds(2024, 3, 10, 2, 30)),
3468            None,
3469        ]);
3470        let to_type = DataType::Timestamp(TimeUnit::Second, Some("America/New_York".into()));
3471        let options = CastOptions {
3472            safe: true,
3473            ..Default::default()
3474        };
3475
3476        let b = cast_with_options(&array, &to_type, &options).unwrap();
3477        assert_eq!(b.data_type(), &to_type);
3478        let c = b.as_primitive::<TimestampSecondType>();
3479        assert_eq!(c.null_count(), 1);
3480        assert_eq!(c.value(0), 1_730_433_600);
3481        assert_eq!(c.value(1), 1_730_615_400);
3482        assert_eq!(c.value(2), 1_710_055_800);
3483        assert!(c.is_null(3));
3484    }
3485
3486    // Southern hemisphere: the transitions run the other way around.
3487    #[test]
3488    fn test_cast_timestamp_to_named_timezone_dst_southern_hemisphere() {
3489        // Ambiguous: clocks go back at 2024-04-07T03:00 AEDT (+11:00 -> +10:00).
3490        let ambiguous = naive_seconds(2024, 4, 7, 2, 30);
3491        // Nonexistent: clocks go forward at 2024-10-06T02:00 AEST (+10:00 -> +11:00).
3492        let nonexistent = naive_seconds(2024, 10, 6, 2, 30);
3493
3494        let array = TimestampSecondArray::from(vec![Some(ambiguous), Some(nonexistent)]);
3495        let to_type = DataType::Timestamp(TimeUnit::Second, Some("Australia/Sydney".into()));
3496        let options = CastOptions {
3497            safe: false,
3498            ..Default::default()
3499        };
3500
3501        let b = cast_with_options(&array, &to_type, &options).unwrap();
3502        assert_eq!(b.data_type(), &to_type);
3503        let c = b.as_primitive::<TimestampSecondType>();
3504
3505        // The later of the two candidates, i.e. AEST (+10:00).
3506        assert_eq!(c.value(0), instant_seconds(2024, 4, 7, 2, 30, 10));
3507        assert_eq!(c.value(0), 1_712_421_000);
3508        // Shifted forward by the one hour gap: 02:30 AEST is 03:30 AEDT.
3509        assert_eq!(c.value(1), instant_seconds(2024, 10, 6, 2, 30, 10));
3510        assert_eq!(c.value(1), instant_seconds(2024, 10, 6, 3, 30, 11));
3511        assert_eq!(c.value(1), 1_728_145_800);
3512    }
3513
3514    // The resolution is independent of the time unit.
3515    #[test]
3516    fn test_cast_timestamp_to_named_timezone_dst_nanosecond() {
3517        let ambiguous = naive_seconds(2024, 11, 3, 1, 30) * 1_000_000_000 + 123_456_789;
3518        let nonexistent = naive_seconds(2024, 3, 10, 2, 30) * 1_000_000_000 + 123_456_789;
3519        let array = TimestampNanosecondArray::from(vec![Some(ambiguous), Some(nonexistent)]);
3520        let to_type = DataType::Timestamp(TimeUnit::Nanosecond, Some("America/New_York".into()));
3521        let options = CastOptions {
3522            safe: false,
3523            ..Default::default()
3524        };
3525
3526        let b = cast_with_options(&array, &to_type, &options).unwrap();
3527        assert_eq!(b.data_type(), &to_type);
3528        let c = b.as_primitive::<TimestampNanosecondType>();
3529        assert_eq!(c.value(0), 1_730_615_400 * 1_000_000_000 + 123_456_789);
3530        assert_eq!(c.value(1), 1_710_055_800 * 1_000_000_000 + 123_456_789);
3531    }
3532
3533    // Unit conversion still composes with the timezone adjustment.
3534    #[test]
3535    fn test_cast_timestamp_to_named_timezone_dst_changing_unit() {
3536        let array = TimestampSecondArray::from(vec![
3537            Some(naive_seconds(2024, 11, 3, 1, 30)),
3538            Some(naive_seconds(2024, 3, 10, 2, 30)),
3539        ]);
3540        let to_type = DataType::Timestamp(TimeUnit::Millisecond, Some("America/New_York".into()));
3541        let options = CastOptions {
3542            safe: false,
3543            ..Default::default()
3544        };
3545
3546        let b = cast_with_options(&array, &to_type, &options).unwrap();
3547        assert_eq!(b.data_type(), &to_type);
3548        let c = b.as_primitive::<TimestampMillisecondType>();
3549        assert_eq!(c.value(0), 1_730_615_400_000);
3550        assert_eq!(c.value(1), 1_710_055_800_000);
3551    }
3552
3553    // A fixed offset has no transitions, so the same readings are unaffected.
3554    #[test]
3555    fn test_cast_timestamp_to_fixed_offset_timezone_unaffected() {
3556        let array = TimestampSecondArray::from(vec![
3557            Some(naive_seconds(2024, 11, 1, 0, 0)),
3558            Some(naive_seconds(2024, 11, 3, 1, 30)),
3559            Some(naive_seconds(2024, 3, 10, 2, 30)),
3560            None,
3561        ]);
3562        let to_type = DataType::Timestamp(TimeUnit::Second, Some("+08:00".into()));
3563        let options = CastOptions {
3564            safe: false,
3565            ..Default::default()
3566        };
3567
3568        let b = cast_with_options(&array, &to_type, &options).unwrap();
3569        assert_eq!(b.data_type(), &to_type);
3570        let c = b.as_primitive::<TimestampSecondType>();
3571        assert_eq!(c.value(0), instant_seconds(2024, 11, 1, 0, 0, 8));
3572        assert_eq!(c.value(1), instant_seconds(2024, 11, 3, 1, 30, 8));
3573        assert_eq!(c.value(2), instant_seconds(2024, 3, 10, 2, 30, 8));
3574        assert!(c.is_null(3));
3575    }
3576
3577    #[test]
3578    fn test_cast_date64_to_timestamp() {
3579        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3580        let b = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap();
3581        let c = b.as_primitive::<TimestampSecondType>();
3582        assert_eq!(864000000, c.value(0));
3583        assert_eq!(1545696000, c.value(1));
3584        assert!(c.is_null(2));
3585    }
3586
3587    #[test]
3588    fn test_cast_date64_to_timestamp_ms() {
3589        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3590        let b = cast(&array, &DataType::Timestamp(TimeUnit::Millisecond, None)).unwrap();
3591        let c = b
3592            .as_any()
3593            .downcast_ref::<TimestampMillisecondArray>()
3594            .unwrap();
3595        assert_eq!(864000000005, c.value(0));
3596        assert_eq!(1545696000001, c.value(1));
3597        assert!(c.is_null(2));
3598    }
3599
3600    #[test]
3601    fn test_cast_date64_to_timestamp_us() {
3602        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3603        let b = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
3604        let c = b
3605            .as_any()
3606            .downcast_ref::<TimestampMicrosecondArray>()
3607            .unwrap();
3608        assert_eq!(864000000005000, c.value(0));
3609        assert_eq!(1545696000001000, c.value(1));
3610        assert!(c.is_null(2));
3611    }
3612
3613    #[test]
3614    fn test_cast_date64_to_timestamp_ns() {
3615        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3616        let b = cast(&array, &DataType::Timestamp(TimeUnit::Nanosecond, None)).unwrap();
3617        let c = b
3618            .as_any()
3619            .downcast_ref::<TimestampNanosecondArray>()
3620            .unwrap();
3621        assert_eq!(864000000005000000, c.value(0));
3622        assert_eq!(1545696000001000000, c.value(1));
3623        assert!(c.is_null(2));
3624    }
3625
3626    #[test]
3627    fn test_cast_timestamp_to_i64() {
3628        let array =
3629            TimestampMillisecondArray::from(vec![Some(864000000005), Some(1545696000001), None])
3630                .with_timezone("UTC".to_string());
3631        let b = cast(&array, &DataType::Int64).unwrap();
3632        let c = b.as_primitive::<Int64Type>();
3633        assert_eq!(&DataType::Int64, c.data_type());
3634        assert_eq!(864000000005, c.value(0));
3635        assert_eq!(1545696000001, c.value(1));
3636        assert!(c.is_null(2));
3637    }
3638
3639    macro_rules! assert_cast {
3640        ($array:expr, $datatype:expr, $output_array_type: ty, $expected:expr) => {{
3641            assert!(can_cast_types($array.data_type(), &$datatype));
3642            let out = cast(&$array, &$datatype).unwrap();
3643            let actual = out
3644                .as_any()
3645                .downcast_ref::<$output_array_type>()
3646                .unwrap()
3647                .into_iter()
3648                .collect::<Vec<_>>();
3649            assert_eq!(actual, $expected);
3650        }};
3651        ($array:expr, $datatype:expr, $output_array_type: ty, $options:expr, $expected:expr) => {{
3652            assert!(can_cast_types($array.data_type(), &$datatype));
3653            let out = cast_with_options(&$array, &$datatype, &$options).unwrap();
3654            let actual = out
3655                .as_any()
3656                .downcast_ref::<$output_array_type>()
3657                .unwrap()
3658                .into_iter()
3659                .collect::<Vec<_>>();
3660            assert_eq!(actual, $expected);
3661        }};
3662    }
3663
3664    #[test]
3665    fn test_cast_date32_to_string() {
3666        let array = Date32Array::from(vec![Some(0), Some(10000), Some(13036), Some(17890), None]);
3667        let expected = vec![
3668            Some("1970-01-01"),
3669            Some("1997-05-19"),
3670            Some("2005-09-10"),
3671            Some("2018-12-25"),
3672            None,
3673        ];
3674
3675        assert_cast!(array, DataType::Utf8View, StringViewArray, expected);
3676        assert_cast!(array, DataType::Utf8, StringArray, expected);
3677        assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected);
3678    }
3679
3680    #[test]
3681    fn test_cast_date64_to_string() {
3682        let array = Date64Array::from(vec![
3683            Some(0),
3684            Some(10000 * 86400000),
3685            Some(13036 * 86400000),
3686            Some(17890 * 86400000),
3687            None,
3688        ]);
3689        let expected = vec![
3690            Some("1970-01-01T00:00:00"),
3691            Some("1997-05-19T00:00:00"),
3692            Some("2005-09-10T00:00:00"),
3693            Some("2018-12-25T00:00:00"),
3694            None,
3695        ];
3696
3697        assert_cast!(array, DataType::Utf8View, StringViewArray, expected);
3698        assert_cast!(array, DataType::Utf8, StringArray, expected);
3699        assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected);
3700    }
3701
3702    #[test]
3703    fn test_cast_date32_to_timestamp_and_timestamp_with_timezone() {
3704        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3705        let a = Date32Array::from(vec![Some(18628), None, None]); // 2021-1-1, 2022-1-1
3706        let array = Arc::new(a) as ArrayRef;
3707
3708        let b = cast(
3709            &array,
3710            &DataType::Timestamp(TimeUnit::Second, Some(tz.into())),
3711        )
3712        .unwrap();
3713        let c = b.as_primitive::<TimestampSecondType>();
3714        let string_array = cast(&c, &DataType::Utf8).unwrap();
3715        let result = string_array.as_string::<i32>();
3716        assert_eq!("2021-01-01T00:00:00+05:45", result.value(0));
3717
3718        let b = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap();
3719        let c = b.as_primitive::<TimestampSecondType>();
3720        let string_array = cast(&c, &DataType::Utf8).unwrap();
3721        let result = string_array.as_string::<i32>();
3722        assert_eq!("2021-01-01T00:00:00", result.value(0));
3723    }
3724
3725    #[test]
3726    fn test_cast_date32_to_timestamp_with_timezone() {
3727        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3728        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
3729        let array = Arc::new(a) as ArrayRef;
3730        let b = cast(
3731            &array,
3732            &DataType::Timestamp(TimeUnit::Second, Some(tz.into())),
3733        )
3734        .unwrap();
3735        let c = b.as_primitive::<TimestampSecondType>();
3736        assert_eq!(1609438500, c.value(0));
3737        assert_eq!(1640974500, c.value(1));
3738        assert!(c.is_null(2));
3739
3740        let string_array = cast(&c, &DataType::Utf8).unwrap();
3741        let result = string_array.as_string::<i32>();
3742        assert_eq!("2021-01-01T00:00:00+05:45", result.value(0));
3743        assert_eq!("2022-01-01T00:00:00+05:45", result.value(1));
3744    }
3745
3746    #[test]
3747    fn test_cast_date32_to_timestamp_with_timezone_ms() {
3748        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3749        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
3750        let array = Arc::new(a) as ArrayRef;
3751        let b = cast(
3752            &array,
3753            &DataType::Timestamp(TimeUnit::Millisecond, Some(tz.into())),
3754        )
3755        .unwrap();
3756        let c = b.as_primitive::<TimestampMillisecondType>();
3757        assert_eq!(1609438500000, c.value(0));
3758        assert_eq!(1640974500000, c.value(1));
3759        assert!(c.is_null(2));
3760
3761        let string_array = cast(&c, &DataType::Utf8).unwrap();
3762        let result = string_array.as_string::<i32>();
3763        assert_eq!("2021-01-01T00:00:00+05:45", result.value(0));
3764        assert_eq!("2022-01-01T00:00:00+05:45", result.value(1));
3765    }
3766
3767    #[test]
3768    fn test_cast_date32_to_timestamp_with_timezone_us() {
3769        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3770        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
3771        let array = Arc::new(a) as ArrayRef;
3772        let b = cast(
3773            &array,
3774            &DataType::Timestamp(TimeUnit::Microsecond, Some(tz.into())),
3775        )
3776        .unwrap();
3777        let c = b.as_primitive::<TimestampMicrosecondType>();
3778        assert_eq!(1609438500000000, c.value(0));
3779        assert_eq!(1640974500000000, c.value(1));
3780        assert!(c.is_null(2));
3781
3782        let string_array = cast(&c, &DataType::Utf8).unwrap();
3783        let result = string_array.as_string::<i32>();
3784        assert_eq!("2021-01-01T00:00:00+05:45", result.value(0));
3785        assert_eq!("2022-01-01T00:00:00+05:45", result.value(1));
3786    }
3787
3788    #[test]
3789    fn test_cast_date32_to_timestamp_with_timezone_ns() {
3790        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3791        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
3792        let array = Arc::new(a) as ArrayRef;
3793        let b = cast(
3794            &array,
3795            &DataType::Timestamp(TimeUnit::Nanosecond, Some(tz.into())),
3796        )
3797        .unwrap();
3798        let c = b.as_primitive::<TimestampNanosecondType>();
3799        assert_eq!(1609438500000000000, c.value(0));
3800        assert_eq!(1640974500000000000, c.value(1));
3801        assert!(c.is_null(2));
3802
3803        let string_array = cast(&c, &DataType::Utf8).unwrap();
3804        let result = string_array.as_string::<i32>();
3805        assert_eq!("2021-01-01T00:00:00+05:45", result.value(0));
3806        assert_eq!("2022-01-01T00:00:00+05:45", result.value(1));
3807    }
3808
3809    #[test]
3810    fn test_cast_date64_to_timestamp_with_timezone() {
3811        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3812        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3813        let b = cast(
3814            &array,
3815            &DataType::Timestamp(TimeUnit::Second, Some(tz.into())),
3816        )
3817        .unwrap();
3818
3819        let c = b.as_primitive::<TimestampSecondType>();
3820        assert_eq!(863979300, c.value(0));
3821        assert_eq!(1545675300, c.value(1));
3822        assert!(c.is_null(2));
3823
3824        let string_array = cast(&c, &DataType::Utf8).unwrap();
3825        let result = string_array.as_string::<i32>();
3826        assert_eq!("1997-05-19T00:00:00+05:45", result.value(0));
3827        assert_eq!("2018-12-25T00:00:00+05:45", result.value(1));
3828    }
3829
3830    #[test]
3831    fn test_cast_date64_to_timestamp_with_timezone_ms() {
3832        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3833        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3834        let b = cast(
3835            &array,
3836            &DataType::Timestamp(TimeUnit::Millisecond, Some(tz.into())),
3837        )
3838        .unwrap();
3839
3840        let c = b.as_primitive::<TimestampMillisecondType>();
3841        assert_eq!(863979300005, c.value(0));
3842        assert_eq!(1545675300001, c.value(1));
3843        assert!(c.is_null(2));
3844
3845        let string_array = cast(&c, &DataType::Utf8).unwrap();
3846        let result = string_array.as_string::<i32>();
3847        assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0));
3848        assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1));
3849    }
3850
3851    #[test]
3852    fn test_cast_date64_to_timestamp_with_timezone_us() {
3853        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3854        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3855        let b = cast(
3856            &array,
3857            &DataType::Timestamp(TimeUnit::Microsecond, Some(tz.into())),
3858        )
3859        .unwrap();
3860
3861        let c = b.as_primitive::<TimestampMicrosecondType>();
3862        assert_eq!(863979300005000, c.value(0));
3863        assert_eq!(1545675300001000, c.value(1));
3864        assert!(c.is_null(2));
3865
3866        let string_array = cast(&c, &DataType::Utf8).unwrap();
3867        let result = string_array.as_string::<i32>();
3868        assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0));
3869        assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1));
3870    }
3871
3872    #[test]
3873    fn test_cast_date64_to_timestamp_with_timezone_ns() {
3874        let array = Date64Array::from(vec![Some(864000000005), Some(1545696000001), None]);
3875        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3876        let b = cast(
3877            &array,
3878            &DataType::Timestamp(TimeUnit::Nanosecond, Some(tz.into())),
3879        )
3880        .unwrap();
3881
3882        let c = b.as_primitive::<TimestampNanosecondType>();
3883        assert_eq!(863979300005000000, c.value(0));
3884        assert_eq!(1545675300001000000, c.value(1));
3885        assert!(c.is_null(2));
3886
3887        let string_array = cast(&c, &DataType::Utf8).unwrap();
3888        let result = string_array.as_string::<i32>();
3889        assert_eq!("1997-05-19T00:00:00.005+05:45", result.value(0));
3890        assert_eq!("2018-12-25T00:00:00.001+05:45", result.value(1));
3891    }
3892
3893    #[test]
3894    fn test_cast_timestamp_to_strings() {
3895        // "2018-12-25T00:00:02.001", "1997-05-19T00:00:03.005", None
3896        let array =
3897            TimestampMillisecondArray::from(vec![Some(864000003005), Some(1545696002001), None]);
3898        let expected = vec![
3899            Some("1997-05-19T00:00:03.005"),
3900            Some("2018-12-25T00:00:02.001"),
3901            None,
3902        ];
3903
3904        assert_cast!(array, DataType::Utf8View, StringViewArray, expected);
3905        assert_cast!(array, DataType::Utf8, StringArray, expected);
3906        assert_cast!(array, DataType::LargeUtf8, LargeStringArray, expected);
3907    }
3908
3909    #[test]
3910    fn test_cast_timestamp_to_strings_opt() {
3911        let ts_format = "%Y-%m-%d %H:%M:%S%.6f";
3912        let tz = "+0545"; // UTC + 0545 is Asia/Kathmandu
3913        let cast_options = CastOptions {
3914            safe: true,
3915            format_options: FormatOptions::default()
3916                .with_timestamp_format(Some(ts_format))
3917                .with_timestamp_tz_format(Some(ts_format)),
3918        };
3919
3920        // "2018-12-25T00:00:02.001", "1997-05-19T00:00:03.005", None
3921        let array_without_tz =
3922            TimestampMillisecondArray::from(vec![Some(864000003005), Some(1545696002001), None]);
3923        let expected = vec![
3924            Some("1997-05-19 00:00:03.005000"),
3925            Some("2018-12-25 00:00:02.001000"),
3926            None,
3927        ];
3928        assert_cast!(
3929            array_without_tz,
3930            DataType::Utf8View,
3931            StringViewArray,
3932            cast_options,
3933            expected
3934        );
3935        assert_cast!(
3936            array_without_tz,
3937            DataType::Utf8,
3938            StringArray,
3939            cast_options,
3940            expected
3941        );
3942        assert_cast!(
3943            array_without_tz,
3944            DataType::LargeUtf8,
3945            LargeStringArray,
3946            cast_options,
3947            expected
3948        );
3949
3950        let array_with_tz =
3951            TimestampMillisecondArray::from(vec![Some(864000003005), Some(1545696002001), None])
3952                .with_timezone(tz.to_string());
3953        let expected = vec![
3954            Some("1997-05-19 05:45:03.005000"),
3955            Some("2018-12-25 05:45:02.001000"),
3956            None,
3957        ];
3958        assert_cast!(
3959            array_with_tz,
3960            DataType::Utf8View,
3961            StringViewArray,
3962            cast_options,
3963            expected
3964        );
3965        assert_cast!(
3966            array_with_tz,
3967            DataType::Utf8,
3968            StringArray,
3969            cast_options,
3970            expected
3971        );
3972        assert_cast!(
3973            array_with_tz,
3974            DataType::LargeUtf8,
3975            LargeStringArray,
3976            cast_options,
3977            expected
3978        );
3979    }
3980
3981    #[test]
3982    fn test_cast_between_timestamps() {
3983        let array =
3984            TimestampMillisecondArray::from(vec![Some(864000003005), Some(1545696002001), None]);
3985        let b = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap();
3986        let c = b.as_primitive::<TimestampSecondType>();
3987        assert_eq!(864000003, c.value(0));
3988        assert_eq!(1545696002, c.value(1));
3989        assert!(c.is_null(2));
3990    }
3991
3992    #[test]
3993    fn test_cast_utf8_to_date32() {
3994        use chrono::NaiveDate;
3995        let from_ymd = chrono::NaiveDate::from_ymd_opt;
3996        let since = chrono::NaiveDate::signed_duration_since;
3997
3998        let a = StringArray::from(vec![
3999            "2000-01-01",          // valid date with leading 0s
4000            "2000-01-01T12:00:00", // valid datetime, will throw away the time part
4001            "2000-2-2",            // valid date without leading 0s
4002            "2000-00-00",          // invalid month and day
4003            "2000",                // just a year is invalid
4004        ]);
4005        let array = Arc::new(a) as ArrayRef;
4006        let b = cast(&array, &DataType::Date32).unwrap();
4007        let c = b.as_primitive::<Date32Type>();
4008
4009        // test valid inputs
4010        let date_value = since(
4011            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
4012            from_ymd(1970, 1, 1).unwrap(),
4013        )
4014        .num_days() as i32;
4015        assert!(c.is_valid(0)); // "2000-01-01"
4016        assert_eq!(date_value, c.value(0));
4017
4018        assert!(c.is_valid(1)); // "2000-01-01T12:00:00"
4019        assert_eq!(date_value, c.value(1));
4020
4021        let date_value = since(
4022            NaiveDate::from_ymd_opt(2000, 2, 2).unwrap(),
4023            from_ymd(1970, 1, 1).unwrap(),
4024        )
4025        .num_days() as i32;
4026        assert!(c.is_valid(2)); // "2000-2-2"
4027        assert_eq!(date_value, c.value(2));
4028
4029        // test invalid inputs
4030        assert!(!c.is_valid(3)); // "2000-00-00"
4031        assert!(!c.is_valid(4)); // "2000"
4032    }
4033
4034    #[test]
4035    fn test_cast_utf8_to_date64() {
4036        let a = StringArray::from(vec![
4037            "2000-01-01T12:00:00", // date + time valid
4038            "2020-12-15T12:34:56", // date + time valid
4039            "2020-2-2T12:34:56",   // valid date time without leading 0s
4040            "2000-00-00T12:00:00", // invalid month and day
4041            "2000-01-01 12:00:00", // missing the 'T'
4042            "2000-01-01",          // just a date is invalid
4043        ]);
4044        let array = Arc::new(a) as ArrayRef;
4045        let b = cast(&array, &DataType::Date64).unwrap();
4046        let c = b.as_primitive::<Date64Type>();
4047
4048        // test valid inputs
4049        assert!(c.is_valid(0)); // "2000-01-01T12:00:00"
4050        assert_eq!(946728000000, c.value(0));
4051        assert!(c.is_valid(1)); // "2020-12-15T12:34:56"
4052        assert_eq!(1608035696000, c.value(1));
4053        assert!(!c.is_valid(2)); // "2020-2-2T12:34:56"
4054
4055        assert!(!c.is_valid(3)); // "2000-00-00T12:00:00"
4056        assert!(c.is_valid(4)); // "2000-01-01 12:00:00"
4057        assert_eq!(946728000000, c.value(4));
4058        assert!(c.is_valid(5)); // "2000-01-01"
4059        assert_eq!(946684800000, c.value(5));
4060    }
4061
4062    #[test]
4063    fn test_cast_outside_supported_range_for_nanoseconds() {
4064        const EXPECTED_ERROR_MESSAGE: &str = "The dates that can be represented as nanoseconds have to be between 1677-09-21T00:12:44.0 and 2262-04-11T23:47:16.854775804";
4065
4066        let array = StringArray::from(vec![Some("1650-01-01 01:01:01.000001")]);
4067
4068        let cast_options = CastOptions {
4069            safe: false,
4070            format_options: FormatOptions::default(),
4071        };
4072
4073        let result =
4074            cast_string_to_timestamp::<i32, TimestampNanosecondType>(&array, None, &cast_options);
4075
4076        let err = result.unwrap_err();
4077        assert_eq!(
4078            err.to_string(),
4079            format!(
4080                "Cast error: Overflow converting {} to Nanosecond. {}",
4081                array.value(0),
4082                EXPECTED_ERROR_MESSAGE
4083            )
4084        );
4085    }
4086
4087    #[test]
4088    fn test_cast_date32_to_timestamp() {
4089        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
4090        let array = Arc::new(a) as ArrayRef;
4091        let b = cast(&array, &DataType::Timestamp(TimeUnit::Second, None)).unwrap();
4092        let c = b.as_primitive::<TimestampSecondType>();
4093        assert_eq!(1609459200, c.value(0));
4094        assert_eq!(1640995200, c.value(1));
4095        assert!(c.is_null(2));
4096    }
4097
4098    #[test]
4099    fn test_cast_date32_to_timestamp_ms() {
4100        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
4101        let array = Arc::new(a) as ArrayRef;
4102        let b = cast(&array, &DataType::Timestamp(TimeUnit::Millisecond, None)).unwrap();
4103        let c = b
4104            .as_any()
4105            .downcast_ref::<TimestampMillisecondArray>()
4106            .unwrap();
4107        assert_eq!(1609459200000, c.value(0));
4108        assert_eq!(1640995200000, c.value(1));
4109        assert!(c.is_null(2));
4110    }
4111
4112    #[test]
4113    fn test_cast_date32_to_timestamp_us() {
4114        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
4115        let array = Arc::new(a) as ArrayRef;
4116        let b = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
4117        let c = b
4118            .as_any()
4119            .downcast_ref::<TimestampMicrosecondArray>()
4120            .unwrap();
4121        assert_eq!(1609459200000000, c.value(0));
4122        assert_eq!(1640995200000000, c.value(1));
4123        assert!(c.is_null(2));
4124    }
4125
4126    #[test]
4127    fn test_cast_date32_to_timestamp_ns() {
4128        let a = Date32Array::from(vec![Some(18628), Some(18993), None]); // 2021-1-1, 2022-1-1
4129        let array = Arc::new(a) as ArrayRef;
4130        let b = cast(&array, &DataType::Timestamp(TimeUnit::Nanosecond, None)).unwrap();
4131        let c = b
4132            .as_any()
4133            .downcast_ref::<TimestampNanosecondArray>()
4134            .unwrap();
4135        assert_eq!(1609459200000000000, c.value(0));
4136        assert_eq!(1640995200000000000, c.value(1));
4137        assert!(c.is_null(2));
4138    }
4139
4140    #[test]
4141    fn test_cast_date32_to_timestamp_us_overflow() {
4142        const MAX_DAYS_MICROS: i32 = (i64::MAX / MICROSECONDS_IN_DAY) as i32;
4143        let a = Date32Array::from(vec![Some(MAX_DAYS_MICROS), Some(MAX_DAYS_MICROS + 1), None]);
4144        let array = Arc::new(a) as ArrayRef;
4145        let err = cast_with_options(
4146            &array,
4147            &DataType::Timestamp(TimeUnit::Microsecond, None),
4148            &CastOptions {
4149                safe: false,
4150                format_options: FormatOptions::default(),
4151            },
4152        );
4153        assert!(err.is_err());
4154
4155        let b = cast(&array, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap();
4156        let c = b.as_primitive::<TimestampMicrosecondType>();
4157        assert_eq!(MAX_DAYS_MICROS as i64 * MICROSECONDS_IN_DAY, c.value(0));
4158        assert!(c.is_null(1));
4159        assert!(c.is_null(2));
4160    }
4161
4162    #[test]
4163    fn test_cast_date32_to_timestamp_ns_overflow() {
4164        // 2262-04-11, 2062-04-12
4165        let upper_limit = 106_751;
4166        let a = Date32Array::from(vec![Some(upper_limit), Some(upper_limit + 1), None]);
4167        let array = Arc::new(a) as ArrayRef;
4168        let err = cast_with_options(
4169            &array,
4170            &DataType::Timestamp(TimeUnit::Nanosecond, None),
4171            &CastOptions {
4172                safe: false,
4173                format_options: FormatOptions::default(),
4174            },
4175        );
4176        assert!(err.is_err());
4177
4178        let b = cast(&array, &DataType::Timestamp(TimeUnit::Nanosecond, None)).unwrap();
4179        let c = b.as_primitive::<TimestampNanosecondType>();
4180        assert_eq!(upper_limit as i64 * NANOSECONDS_IN_DAY, c.value(0));
4181        assert!(c.is_null(1));
4182        assert!(c.is_null(2));
4183    }
4184
4185    #[test]
4186    fn test_timezone_cast() {
4187        let a = StringArray::from(vec![
4188            "2000-01-01T12:00:00", // date + time valid
4189            "2020-12-15T12:34:56", // date + time valid
4190        ]);
4191        let array = Arc::new(a) as ArrayRef;
4192        let b = cast(&array, &DataType::Timestamp(TimeUnit::Nanosecond, None)).unwrap();
4193        let v = b.as_primitive::<TimestampNanosecondType>();
4194
4195        assert_eq!(v.value(0), 946728000000000000);
4196        assert_eq!(v.value(1), 1608035696000000000);
4197
4198        let b = cast(
4199            &b,
4200            &DataType::Timestamp(TimeUnit::Nanosecond, Some("+00:00".into())),
4201        )
4202        .unwrap();
4203        let v = b.as_primitive::<TimestampNanosecondType>();
4204
4205        assert_eq!(v.value(0), 946728000000000000);
4206        assert_eq!(v.value(1), 1608035696000000000);
4207
4208        let b = cast(
4209            &b,
4210            &DataType::Timestamp(TimeUnit::Millisecond, Some("+02:00".into())),
4211        )
4212        .unwrap();
4213        let v = b.as_primitive::<TimestampMillisecondType>();
4214
4215        assert_eq!(v.value(0), 946728000000);
4216        assert_eq!(v.value(1), 1608035696000);
4217    }
4218
4219    #[test]
4220    fn test_cast_utf8_to_timestamp() {
4221        fn test_tz(tz: Arc<str>) {
4222            let valid = StringArray::from(vec![
4223                "2023-01-01 04:05:06.789000-08:00",
4224                "2023-01-01 04:05:06.789000-07:00",
4225                "2023-01-01 04:05:06.789 -0800",
4226                "2023-01-01 04:05:06.789 -08:00",
4227                "2023-01-01 040506 +0730",
4228                "2023-01-01 040506 +07:30",
4229                "2023-01-01 04:05:06.789",
4230                "2023-01-01 04:05:06",
4231                "2023-01-01",
4232            ]);
4233
4234            let array = Arc::new(valid) as ArrayRef;
4235            let b = cast_with_options(
4236                &array,
4237                &DataType::Timestamp(TimeUnit::Nanosecond, Some(tz.clone())),
4238                &CastOptions {
4239                    safe: false,
4240                    format_options: FormatOptions::default(),
4241                },
4242            )
4243            .unwrap();
4244
4245            let tz = tz.as_ref().parse().unwrap();
4246
4247            let as_tz =
4248                |v: i64| as_datetime_with_timezone::<TimestampNanosecondType>(v, tz).unwrap();
4249
4250            let as_utc = |v: &i64| as_tz(*v).naive_utc().to_string();
4251            let as_local = |v: &i64| as_tz(*v).naive_local().to_string();
4252
4253            let values = b.as_primitive::<TimestampNanosecondType>().values();
4254            let utc_results: Vec<_> = values.iter().map(as_utc).collect();
4255            let local_results: Vec<_> = values.iter().map(as_local).collect();
4256
4257            // Absolute timestamps should be parsed preserving the same UTC instant
4258            assert_eq!(
4259                &utc_results[..6],
4260                &[
4261                    "2023-01-01 12:05:06.789".to_string(),
4262                    "2023-01-01 11:05:06.789".to_string(),
4263                    "2023-01-01 12:05:06.789".to_string(),
4264                    "2023-01-01 12:05:06.789".to_string(),
4265                    "2022-12-31 20:35:06".to_string(),
4266                    "2022-12-31 20:35:06".to_string(),
4267                ]
4268            );
4269            // Non-absolute timestamps should be parsed preserving the same local instant
4270            assert_eq!(
4271                &local_results[6..],
4272                &[
4273                    "2023-01-01 04:05:06.789".to_string(),
4274                    "2023-01-01 04:05:06".to_string(),
4275                    "2023-01-01 00:00:00".to_string()
4276                ]
4277            )
4278        }
4279
4280        test_tz("+00:00".into());
4281        test_tz("+02:00".into());
4282    }
4283
4284    #[test]
4285    fn test_cast_utf8_to_timestamptz() {
4286        let valid = StringArray::from(vec!["2023-01-01"]);
4287
4288        let array = Arc::new(valid) as ArrayRef;
4289        let b = cast(
4290            &array,
4291            &DataType::Timestamp(TimeUnit::Nanosecond, Some("+00:00".into())),
4292        )
4293        .unwrap();
4294
4295        let expect = DataType::Timestamp(TimeUnit::Nanosecond, Some("+00:00".into()));
4296
4297        assert_eq!(b.data_type(), &expect);
4298        let c = b
4299            .as_any()
4300            .downcast_ref::<TimestampNanosecondArray>()
4301            .unwrap();
4302        assert_eq!(1672531200000000000, c.value(0));
4303    }
4304
4305    #[test]
4306    fn test_cast_below_unixtimestamp() {
4307        let valid = StringArray::from(vec![
4308            "1900-01-03 23:59:59",
4309            "1969-12-31 00:00:01",
4310            "1989-12-31 00:00:01",
4311        ]);
4312
4313        let array = Arc::new(valid) as ArrayRef;
4314        let casted_array = cast_with_options(
4315            &array,
4316            &DataType::Timestamp(TimeUnit::Nanosecond, Some("+00:00".into())),
4317            &CastOptions {
4318                safe: false,
4319                format_options: FormatOptions::default(),
4320            },
4321        )
4322        .unwrap();
4323
4324        let ts_array = casted_array
4325            .as_primitive::<TimestampNanosecondType>()
4326            .values()
4327            .iter()
4328            .map(|ts| ts / 1_000_000)
4329            .collect::<Vec<_>>();
4330
4331        let array = TimestampMillisecondArray::from(ts_array).with_timezone("+00:00".to_string());
4332        let casted_array = cast(&array, &DataType::Date32).unwrap();
4333        let date_array = casted_array.as_primitive::<Date32Type>();
4334        let casted_array = cast(&date_array, &DataType::Utf8).unwrap();
4335        let string_array = casted_array.as_string::<i32>();
4336        assert_eq!("1900-01-03", string_array.value(0));
4337        assert_eq!("1969-12-31", string_array.value(1));
4338        assert_eq!("1989-12-31", string_array.value(2));
4339    }
4340
4341    #[test]
4342    fn test_cast_string_to_timestamp_invalid_tz() {
4343        // content after Z should be ignored
4344        let bad_timestamp = "2023-12-05T21:58:10.45ZZTOP";
4345        let array = StringArray::from(vec![Some(bad_timestamp)]);
4346
4347        let data_types = [
4348            DataType::Timestamp(TimeUnit::Second, None),
4349            DataType::Timestamp(TimeUnit::Millisecond, None),
4350            DataType::Timestamp(TimeUnit::Microsecond, None),
4351            DataType::Timestamp(TimeUnit::Nanosecond, None),
4352        ];
4353
4354        let cast_options = CastOptions {
4355            safe: false,
4356            ..Default::default()
4357        };
4358
4359        for dt in data_types {
4360            // The trailing detail of the message differs depending on whether
4361            // `chrono-tz` is enabled, so only the common prefix is asserted.
4362            let err = cast_with_options(&array, &dt, &cast_options)
4363                .unwrap_err()
4364                .to_string();
4365            assert!(
4366                err.starts_with("Parser error: Invalid timezone \"ZZTOP\":"),
4367                "{err}"
4368            );
4369        }
4370    }
4371    #[test]
4372    fn test_first_none() {
4373        let array = Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
4374            None,
4375            Some(vec![Some(1), Some(2)]),
4376        ])) as ArrayRef;
4377        let data_type =
4378            DataType::FixedSizeList(FieldRef::new(Field::new("item", DataType::Int64, true)), 2);
4379        let opt = CastOptions::default();
4380        let r = cast_with_options(&array, &data_type, &opt).unwrap();
4381
4382        let fixed_array = Arc::new(FixedSizeListArray::from_iter_primitive::<Int64Type, _, _>(
4383            vec![None, Some(vec![Some(1), Some(2)])],
4384            2,
4385        )) as ArrayRef;
4386        assert_eq!(*fixed_array, *r);
4387    }
4388
4389    #[test]
4390    fn test_first_last_none() {
4391        let array = Arc::new(ListArray::from_iter_primitive::<Int64Type, _, _>(vec![
4392            None,
4393            Some(vec![Some(1), Some(2)]),
4394            None,
4395        ])) as ArrayRef;
4396        let data_type =
4397            DataType::FixedSizeList(FieldRef::new(Field::new("item", DataType::Int64, true)), 2);
4398        let opt = CastOptions::default();
4399        let r = cast_with_options(&array, &data_type, &opt).unwrap();
4400
4401        let fixed_array = Arc::new(FixedSizeListArray::from_iter_primitive::<Int64Type, _, _>(
4402            vec![None, Some(vec![Some(1), Some(2)]), None],
4403            2,
4404        )) as ArrayRef;
4405        assert_eq!(*fixed_array, *r);
4406    }
4407
4408    #[test]
4409    fn test_cast_time32_second_to_int64() {
4410        let array = Time32SecondArray::from(vec![1000, 2000, 3000]);
4411        let array = Arc::new(array) as Arc<dyn Array>;
4412        let to_type = DataType::Int64;
4413        let cast_options = CastOptions::default();
4414
4415        assert!(can_cast_types(array.data_type(), &to_type));
4416
4417        let result = cast_with_options(&array, &to_type, &cast_options);
4418        assert!(
4419            result.is_ok(),
4420            "Failed to cast Time32(Second) to Int64: {:?}",
4421            result.err()
4422        );
4423
4424        let cast_array = result.unwrap();
4425        let cast_array = cast_array.as_any().downcast_ref::<Int64Array>().unwrap();
4426
4427        assert_eq!(cast_array.value(0), 1000);
4428        assert_eq!(cast_array.value(1), 2000);
4429        assert_eq!(cast_array.value(2), 3000);
4430    }
4431
4432    #[test]
4433    fn test_cast_time32_millisecond_to_int64() {
4434        let array = Time32MillisecondArray::from(vec![1000, 2000, 3000]);
4435        let array = Arc::new(array) as Arc<dyn Array>;
4436        let to_type = DataType::Int64;
4437        let cast_options = CastOptions::default();
4438
4439        assert!(can_cast_types(array.data_type(), &to_type));
4440
4441        let result = cast_with_options(&array, &to_type, &cast_options);
4442        assert!(
4443            result.is_ok(),
4444            "Failed to cast Time32(Millisecond) to Int64: {:?}",
4445            result.err()
4446        );
4447
4448        let cast_array = result.unwrap();
4449        let cast_array = cast_array.as_any().downcast_ref::<Int64Array>().unwrap();
4450
4451        assert_eq!(cast_array.value(0), 1000);
4452        assert_eq!(cast_array.value(1), 2000);
4453        assert_eq!(cast_array.value(2), 3000);
4454    }
4455
4456    #[test]
4457    fn test_cast_time32_millisecond_to_time64_nanosecond() {
4458        let array =
4459            Time32MillisecondArray::from(vec![Some(1_000), Some(2_000), None, Some(43_200_000)]);
4460        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
4461        let c = b.as_primitive::<Time64NanosecondType>();
4462        assert_eq!(c.value(0), 1_000_000_000);
4463        assert_eq!(c.value(1), 2_000_000_000);
4464        assert!(c.is_null(2));
4465        assert_eq!(c.value(3), 43_200_000_000_000);
4466    }
4467
4468    #[test]
4469    fn test_cast_time32_millisecond_to_time64_microsecond() {
4470        let array =
4471            Time32MillisecondArray::from(vec![Some(1_000), Some(2_000), None, Some(43_200_000)]);
4472        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
4473        let c = b.as_primitive::<Time64MicrosecondType>();
4474        assert_eq!(c.value(0), 1_000_000);
4475        assert_eq!(c.value(1), 2_000_000);
4476        assert!(c.is_null(2));
4477        assert_eq!(c.value(3), 43_200_000_000);
4478    }
4479
4480    #[test]
4481    fn test_cast_time32_second_to_time64_nanosecond() {
4482        let array = Time32SecondArray::from(vec![Some(1), Some(60), None, Some(43_200)]);
4483        let b = cast(&array, &DataType::Time64(TimeUnit::Nanosecond)).unwrap();
4484        let c = b.as_primitive::<Time64NanosecondType>();
4485        assert_eq!(c.value(0), 1_000_000_000);
4486        assert_eq!(c.value(1), 60_000_000_000);
4487        assert!(c.is_null(2));
4488        assert_eq!(c.value(3), 43_200_000_000_000);
4489    }
4490
4491    #[test]
4492    fn test_cast_time32_second_to_time64_microsecond() {
4493        let array = Time32SecondArray::from(vec![Some(1), Some(60), None, Some(43_200)]);
4494        let b = cast(&array, &DataType::Time64(TimeUnit::Microsecond)).unwrap();
4495        let c = b.as_primitive::<Time64MicrosecondType>();
4496        assert_eq!(c.value(0), 1_000_000);
4497        assert_eq!(c.value(1), 60_000_000);
4498        assert!(c.is_null(2));
4499        assert_eq!(c.value(3), 43_200_000_000);
4500    }
4501
4502    #[test]
4503    fn test_cast_time32_second_to_time32_millisecond_overflow() {
4504        let array = Time32SecondArray::from(vec![i32::MAX]);
4505
4506        let b = cast(&array, &DataType::Time32(TimeUnit::Millisecond)).unwrap();
4507        let c = b.as_primitive::<Time32MillisecondType>();
4508        assert!(c.is_null(0));
4509
4510        let options = CastOptions {
4511            safe: false,
4512            ..Default::default()
4513        };
4514        let err = cast_with_options(&array, &DataType::Time32(TimeUnit::Millisecond), &options)
4515            .unwrap_err();
4516        assert!(err.to_string().contains("Overflow"), "{err}");
4517    }
4518
4519    fn assert_temporal_overflow_is_safe(array: &dyn Array, to_type: &DataType) {
4520        let result = cast(array, to_type).unwrap();
4521        assert_eq!(result.null_count(), array.len());
4522
4523        let options = CastOptions {
4524            safe: false,
4525            ..Default::default()
4526        };
4527        assert!(cast_with_options(array, to_type, &options).is_err());
4528    }
4529
4530    #[test]
4531    fn test_cast_time64_overflow() {
4532        let microseconds = Time64MicrosecondArray::from(vec![i64::MIN, i64::MAX]);
4533        for to_type in [
4534            DataType::Time32(TimeUnit::Second),
4535            DataType::Time32(TimeUnit::Millisecond),
4536            DataType::Time64(TimeUnit::Nanosecond),
4537        ] {
4538            assert_temporal_overflow_is_safe(&microseconds, &to_type);
4539        }
4540
4541        let nanoseconds = Time64NanosecondArray::from(vec![i64::MIN, i64::MAX]);
4542        for to_type in [
4543            DataType::Time32(TimeUnit::Second),
4544            DataType::Time32(TimeUnit::Millisecond),
4545        ] {
4546            assert_temporal_overflow_is_safe(&nanoseconds, &to_type);
4547        }
4548    }
4549
4550    #[test]
4551    fn test_cast_date64_to_timestamp_overflow() {
4552        let array = Date64Array::from(vec![i64::MIN, i64::MAX]);
4553        for to_type in [
4554            DataType::Timestamp(TimeUnit::Microsecond, None),
4555            DataType::Timestamp(TimeUnit::Nanosecond, None),
4556        ] {
4557            assert_temporal_overflow_is_safe(&array, &to_type);
4558        }
4559    }
4560
4561    #[test]
4562    fn test_cast_time64_to_time32_boundaries() {
4563        fn check<FROM, TO>(divisor: i64)
4564        where
4565            FROM: ArrowPrimitiveType<Native = i64>,
4566            TO: ArrowPrimitiveType<Native = i32>,
4567        {
4568            // Division truncates towards zero before the range check. Values
4569            // slightly outside the scaled i32 bounds can still be representable.
4570            let min = <i64 as From<i32>>::from(i32::MIN) * divisor - (divisor - 1);
4571            let max = <i64 as From<i32>>::from(i32::MAX) * divisor + (divisor - 1);
4572            let array = PrimitiveArray::<FROM>::new(
4573                vec![i64::MAX, min - 1, min, -divisor + 1, i64::MAX, max, max + 1].into(),
4574                Some(vec![true, true, true, true, false, true, true].into()),
4575            )
4576            .slice(1, 6);
4577            let expected = PrimitiveArray::<TO>::from_iter([
4578                None,
4579                Some(i32::MIN),
4580                Some(0),
4581                None,
4582                Some(i32::MAX),
4583                None,
4584            ]);
4585            let result = cast(&array, &TO::DATA_TYPE).unwrap();
4586            assert_eq!(result.as_primitive::<TO>(), &expected);
4587
4588            let options = CastOptions {
4589                safe: false,
4590                ..Default::default()
4591            };
4592            assert!(cast_with_options(&array, &TO::DATA_TYPE, &options).is_err());
4593            // The invalid physical value under the null must not cause an error.
4594            let result = cast_with_options(&array.slice(1, 4), &TO::DATA_TYPE, &options).unwrap();
4595            assert_eq!(result.as_primitive::<TO>(), &expected.slice(1, 4));
4596        }
4597        check::<Time64MicrosecondType, Time32SecondType>(MICROSECONDS);
4598        check::<Time64MicrosecondType, Time32MillisecondType>(MICROSECONDS / MILLISECONDS);
4599        check::<Time64NanosecondType, Time32SecondType>(NANOSECONDS);
4600        check::<Time64NanosecondType, Time32MillisecondType>(NANOSECONDS / MILLISECONDS);
4601    }
4602
4603    #[test]
4604    fn test_cast_temporal_scaling_boundaries() {
4605        fn check<FROM, TO>(multiplier: i64)
4606        where
4607            FROM: ArrowPrimitiveType<Native = i64>,
4608            TO: ArrowPrimitiveType<Native = i64>,
4609        {
4610            let min = i64::MIN / multiplier;
4611            let max = i64::MAX / multiplier;
4612            let array = PrimitiveArray::<FROM>::new(
4613                vec![i64::MAX, min - 1, min, -1, i64::MAX, max, max + 1].into(),
4614                Some(vec![true, true, true, true, false, true, true].into()),
4615            )
4616            .slice(1, 6);
4617            let expected = PrimitiveArray::<TO>::from_iter([
4618                None,
4619                Some(min * multiplier),
4620                Some(-multiplier),
4621                None,
4622                Some(max * multiplier),
4623                None,
4624            ]);
4625            let result = cast(&array, &TO::DATA_TYPE).unwrap();
4626            assert_eq!(result.as_primitive::<TO>(), &expected);
4627            let options = CastOptions {
4628                safe: false,
4629                ..Default::default()
4630            };
4631            assert!(cast_with_options(&array, &TO::DATA_TYPE, &options).is_err());
4632            let result = cast_with_options(&array.slice(1, 4), &TO::DATA_TYPE, &options).unwrap();
4633            assert_eq!(result.as_primitive::<TO>(), &expected.slice(1, 4));
4634        }
4635        check::<Time64MicrosecondType, Time64NanosecondType>(NANOSECONDS / MICROSECONDS);
4636        check::<Date64Type, TimestampMicrosecondType>(MICROSECONDS / MILLISECONDS);
4637        check::<Date64Type, TimestampNanosecondType>(NANOSECONDS / MILLISECONDS);
4638    }
4639
4640    #[test]
4641    fn test_cast_string_to_time32_second_to_int64() {
4642        // Mimic: select arrow_cast('03:12:44'::time, 'Time32(Second)')::bigint;
4643        // raised in https://github.com/apache/datafusion/issues/19036
4644        let array = StringArray::from(vec!["03:12:44"]);
4645        let array = Arc::new(array) as Arc<dyn Array>;
4646        let cast_options = CastOptions::default();
4647
4648        // 1. Cast String to Time32(Second)
4649        let time32_type = DataType::Time32(TimeUnit::Second);
4650        let time32_array = cast_with_options(&array, &time32_type, &cast_options).unwrap();
4651
4652        // 2. Cast Time32(Second) to Int64
4653        let int64_type = DataType::Int64;
4654        assert!(can_cast_types(time32_array.data_type(), &int64_type));
4655
4656        let result = cast_with_options(&time32_array, &int64_type, &cast_options);
4657
4658        assert!(
4659            result.is_ok(),
4660            "Failed to cast Time32(Second) to Int64: {:?}",
4661            result.err()
4662        );
4663
4664        let cast_array = result.unwrap();
4665        let cast_array = cast_array.as_any().downcast_ref::<Int64Array>().unwrap();
4666
4667        // 03:12:44 = 3*3600 + 12*60 + 44 = 10800 + 720 + 44 = 11564
4668        assert_eq!(cast_array.value(0), 11564);
4669    }
4670}