arrow_arith/
temporal.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines temporal kernels for time and date related functions.
19
20use std::sync::Arc;
21
22use arrow_array::cast::AsArray;
23use cast::as_primitive_array;
24use chrono::{Datelike, TimeZone, Timelike, Utc};
25
26use arrow_array::temporal_conversions::{
27    date32_to_datetime, date64_to_datetime, timestamp_ms_to_datetime, timestamp_ns_to_datetime,
28    timestamp_s_to_datetime, timestamp_us_to_datetime, MICROSECONDS, MICROSECONDS_IN_DAY,
29    MILLISECONDS, MILLISECONDS_IN_DAY, NANOSECONDS, NANOSECONDS_IN_DAY, SECONDS_IN_DAY,
30};
31use arrow_array::timezone::Tz;
32use arrow_array::types::*;
33use arrow_array::*;
34use arrow_buffer::ArrowNativeType;
35use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
36
37/// Valid parts to extract from date/time/timestamp arrays.
38///
39/// See [`date_part`].
40///
41/// Marked as non-exhaustive as may expand to support more types of
42/// date parts in the future.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44#[non_exhaustive]
45pub enum DatePart {
46    /// Quarter of the year, in range `1..=4`
47    Quarter,
48    /// Calendar year
49    Year,
50    /// ISO year, computed as per ISO 8601
51    YearISO,
52    /// Month in the year, in range `1..=12`
53    Month,
54    /// week of the year, in range `1..=53`, computed as per ISO 8601
55    Week,
56    /// ISO week of the year, in range `1..=53`
57    WeekISO,
58    /// Day of the month, in range `1..=31`
59    Day,
60    /// Day of the week, in range `0..=6`, where Sunday is `0`
61    DayOfWeekSunday0,
62    /// Day of the week, in range `0..=6`, where Monday is `0`
63    DayOfWeekMonday0,
64    /// Day of year, in range `1..=366`
65    DayOfYear,
66    /// Hour of the day, in range `0..=23`
67    Hour,
68    /// Minute of the hour, in range `0..=59`
69    Minute,
70    /// Second of the minute, in range `0..=59`
71    Second,
72    /// Millisecond of the second
73    Millisecond,
74    /// Microsecond of the second
75    Microsecond,
76    /// Nanosecond of the second
77    Nanosecond,
78}
79
80impl std::fmt::Display for DatePart {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        write!(f, "{:?}", self)
83    }
84}
85
86/// Returns function to extract relevant [`DatePart`] from types like a
87/// [`NaiveDateTime`] or [`DateTime`].
88///
89/// [`NaiveDateTime`]: chrono::NaiveDateTime
90/// [`DateTime`]: chrono::DateTime
91fn get_date_time_part_extract_fn<T>(part: DatePart) -> fn(T) -> i32
92where
93    T: ChronoDateExt + Datelike + Timelike,
94{
95    match part {
96        DatePart::Quarter => |d| d.quarter() as i32,
97        DatePart::Year => |d| d.year(),
98        DatePart::YearISO => |d| d.iso_week().year(),
99        DatePart::Month => |d| d.month() as i32,
100        DatePart::Week | DatePart::WeekISO => |d| d.iso_week().week() as i32,
101        DatePart::Day => |d| d.day() as i32,
102        DatePart::DayOfWeekSunday0 => |d| d.num_days_from_sunday(),
103        DatePart::DayOfWeekMonday0 => |d| d.num_days_from_monday(),
104        DatePart::DayOfYear => |d| d.ordinal() as i32,
105        DatePart::Hour => |d| d.hour() as i32,
106        DatePart::Minute => |d| d.minute() as i32,
107        DatePart::Second => |d| d.second() as i32,
108        DatePart::Millisecond => |d| (d.nanosecond() / 1_000_000) as i32,
109        DatePart::Microsecond => |d| (d.nanosecond() / 1_000) as i32,
110        DatePart::Nanosecond => |d| d.nanosecond() as i32,
111    }
112}
113
114/// Given an array, return a new array with the extracted [`DatePart`] as signed 32-bit
115/// integer values.
116///
117/// Currently only supports temporal types:
118///   - Date32/Date64
119///   - Time32/Time64
120///   - Timestamp
121///   - Interval
122///   - Duration
123///
124/// Returns an [`Int32Array`] unless input was a dictionary type, in which case returns
125/// the dictionary but with this function applied onto its values.
126///
127/// If array passed in is not of the above listed types (or is a dictionary array where the
128/// values array isn't of the above listed types), then this function will return an error.
129///
130/// # Examples
131///
132/// ```
133/// # use arrow_array::{Int32Array, TimestampMicrosecondArray};
134/// # use arrow_arith::temporal::{DatePart, date_part};
135/// let input: TimestampMicrosecondArray =
136///     vec![Some(1612025847000000), None, Some(1722015847000000)].into();
137///
138/// let week = date_part(&input, DatePart::Week).unwrap();
139/// let week_iso = date_part(&input, DatePart::WeekISO).unwrap();
140/// let expected: Int32Array = vec![Some(4), None, Some(30)].into();
141/// assert_eq!(week.as_ref(), &expected);
142/// assert_eq!(week_iso.as_ref(), &expected);
143/// let year_iso = date_part(&input, DatePart::YearISO).unwrap();
144/// let expected: Int32Array = vec![Some(2021), None, Some(2024)].into();
145/// assert_eq!(year_iso.as_ref(), &expected);
146/// ```
147pub fn date_part(array: &dyn Array, part: DatePart) -> Result<ArrayRef, ArrowError> {
148    downcast_temporal_array!(
149        array => {
150            let array = array.date_part(part)?;
151            let array = Arc::new(array) as ArrayRef;
152            Ok(array)
153        }
154        DataType::Interval(IntervalUnit::YearMonth) => {
155            let array = as_primitive_array::<IntervalYearMonthType>(array).date_part(part)?;
156            let array = Arc::new(array) as ArrayRef;
157            Ok(array)
158        }
159        DataType::Interval(IntervalUnit::DayTime) => {
160            let array = as_primitive_array::<IntervalDayTimeType>(array).date_part(part)?;
161            let array = Arc::new(array) as ArrayRef;
162            Ok(array)
163        }
164        DataType::Interval(IntervalUnit::MonthDayNano) => {
165            let array = as_primitive_array::<IntervalMonthDayNanoType>(array).date_part(part)?;
166            let array = Arc::new(array) as ArrayRef;
167            Ok(array)
168        }
169        DataType::Duration(TimeUnit::Second) => {
170            let array = as_primitive_array::<DurationSecondType>(array).date_part(part)?;
171            let array = Arc::new(array) as ArrayRef;
172            Ok(array)
173        }
174        DataType::Duration(TimeUnit::Millisecond) => {
175            let array = as_primitive_array::<DurationMillisecondType>(array).date_part(part)?;
176            let array = Arc::new(array) as ArrayRef;
177            Ok(array)
178        }
179        DataType::Duration(TimeUnit::Microsecond) => {
180            let array = as_primitive_array::<DurationMicrosecondType>(array).date_part(part)?;
181            let array = Arc::new(array) as ArrayRef;
182            Ok(array)
183        }
184        DataType::Duration(TimeUnit::Nanosecond) => {
185            let array = as_primitive_array::<DurationNanosecondType>(array).date_part(part)?;
186            let array = Arc::new(array) as ArrayRef;
187            Ok(array)
188        }
189        DataType::Dictionary(_, _) => {
190            let array = array.as_any_dictionary();
191            let values = date_part(array.values(), part)?;
192            let values = Arc::new(values) as ArrayRef;
193            let new_array = array.with_values(values);
194            Ok(new_array)
195        }
196        t => return_compute_error_with!(format!("{part} does not support"), t),
197    )
198}
199
200/// Used to integrate new [`date_part()`] method with deprecated shims such as
201/// [`hour()`] and [`week()`].
202fn date_part_primitive<T: ArrowTemporalType>(
203    array: &PrimitiveArray<T>,
204    part: DatePart,
205) -> Result<Int32Array, ArrowError> {
206    let array = date_part(array, part)?;
207    Ok(array.as_primitive::<Int32Type>().to_owned())
208}
209
210/// Extract optional [`Tz`] from timestamp data types, returning error
211/// if called with a non-timestamp type.
212fn get_tz(dt: &DataType) -> Result<Option<Tz>, ArrowError> {
213    match dt {
214        DataType::Timestamp(_, Some(tz)) => Ok(Some(tz.parse::<Tz>()?)),
215        DataType::Timestamp(_, None) => Ok(None),
216        _ => Err(ArrowError::CastError(format!("Not a timestamp type: {dt}"))),
217    }
218}
219
220/// Implement the specialized functions for extracting date part from temporal arrays.
221trait ExtractDatePartExt {
222    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError>;
223}
224
225impl ExtractDatePartExt for PrimitiveArray<Time32SecondType> {
226    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
227        #[inline]
228        fn range_check(s: i32) -> bool {
229            (0..SECONDS_IN_DAY as i32).contains(&s)
230        }
231        match part {
232            DatePart::Hour => Ok(self.unary_opt(|s| range_check(s).then_some(s / 3_600))),
233            DatePart::Minute => Ok(self.unary_opt(|s| range_check(s).then_some((s / 60) % 60))),
234            DatePart::Second => Ok(self.unary_opt(|s| range_check(s).then_some(s % 60))),
235            // Time32Second only encodes number of seconds, so these will always be 0 (if in valid range)
236            DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond => {
237                Ok(self.unary_opt(|s| range_check(s).then_some(0)))
238            }
239            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
240        }
241    }
242}
243
244impl ExtractDatePartExt for PrimitiveArray<Time32MillisecondType> {
245    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
246        #[inline]
247        fn range_check(ms: i32) -> bool {
248            (0..MILLISECONDS_IN_DAY as i32).contains(&ms)
249        }
250        let milliseconds = MILLISECONDS as i32;
251        match part {
252            DatePart::Hour => {
253                Ok(self.unary_opt(|ms| range_check(ms).then_some(ms / 3_600 / milliseconds)))
254            }
255            DatePart::Minute => {
256                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / 60 / milliseconds) % 60)))
257            }
258            DatePart::Second => {
259                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / milliseconds) % 60)))
260            }
261            DatePart::Millisecond => {
262                Ok(self.unary_opt(|ms| range_check(ms).then_some(ms % milliseconds)))
263            }
264            DatePart::Microsecond => {
265                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000)))
266            }
267            DatePart::Nanosecond => {
268                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000_000)))
269            }
270            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
271        }
272    }
273}
274
275impl ExtractDatePartExt for PrimitiveArray<Time64MicrosecondType> {
276    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
277        #[inline]
278        fn range_check(us: i64) -> bool {
279            (0..MICROSECONDS_IN_DAY).contains(&us)
280        }
281        match part {
282            DatePart::Hour => {
283                Ok(self
284                    .unary_opt(|us| range_check(us).then_some((us / 3_600 / MICROSECONDS) as i32)))
285            }
286            DatePart::Minute => Ok(self
287                .unary_opt(|us| range_check(us).then_some(((us / 60 / MICROSECONDS) % 60) as i32))),
288            DatePart::Second => {
289                Ok(self
290                    .unary_opt(|us| range_check(us).then_some(((us / MICROSECONDS) % 60) as i32)))
291            }
292            DatePart::Millisecond => Ok(self
293                .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) / 1_000) as i32))),
294            DatePart::Microsecond => {
295                Ok(self.unary_opt(|us| range_check(us).then_some((us % MICROSECONDS) as i32)))
296            }
297            DatePart::Nanosecond => Ok(self
298                .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) * 1_000) as i32))),
299            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
300        }
301    }
302}
303
304impl ExtractDatePartExt for PrimitiveArray<Time64NanosecondType> {
305    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
306        #[inline]
307        fn range_check(ns: i64) -> bool {
308            (0..NANOSECONDS_IN_DAY).contains(&ns)
309        }
310        match part {
311            DatePart::Hour => {
312                Ok(self
313                    .unary_opt(|ns| range_check(ns).then_some((ns / 3_600 / NANOSECONDS) as i32)))
314            }
315            DatePart::Minute => Ok(self
316                .unary_opt(|ns| range_check(ns).then_some(((ns / 60 / NANOSECONDS) % 60) as i32))),
317            DatePart::Second => Ok(
318                self.unary_opt(|ns| range_check(ns).then_some(((ns / NANOSECONDS) % 60) as i32))
319            ),
320            DatePart::Millisecond => Ok(self.unary_opt(|ns| {
321                range_check(ns).then_some(((ns % NANOSECONDS) / 1_000_000) as i32)
322            })),
323            DatePart::Microsecond => {
324                Ok(self
325                    .unary_opt(|ns| range_check(ns).then_some(((ns % NANOSECONDS) / 1_000) as i32)))
326            }
327            DatePart::Nanosecond => {
328                Ok(self.unary_opt(|ns| range_check(ns).then_some((ns % NANOSECONDS) as i32)))
329            }
330            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
331        }
332    }
333}
334
335impl ExtractDatePartExt for PrimitiveArray<Date32Type> {
336    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
337        // Date32 only encodes number of days, so these will always be 0
338        if let DatePart::Hour
339        | DatePart::Minute
340        | DatePart::Second
341        | DatePart::Millisecond
342        | DatePart::Microsecond
343        | DatePart::Nanosecond = part
344        {
345            Ok(Int32Array::new(
346                vec![0; self.len()].into(),
347                self.nulls().cloned(),
348            ))
349        } else {
350            let map_func = get_date_time_part_extract_fn(part);
351            Ok(self.unary_opt(|d| date32_to_datetime(d).map(map_func)))
352        }
353    }
354}
355
356impl ExtractDatePartExt for PrimitiveArray<Date64Type> {
357    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
358        let map_func = get_date_time_part_extract_fn(part);
359        Ok(self.unary_opt(|d| date64_to_datetime(d).map(map_func)))
360    }
361}
362
363impl ExtractDatePartExt for PrimitiveArray<TimestampSecondType> {
364    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
365        // TimestampSecond only encodes number of seconds, so these will always be 0
366        let array =
367            if let DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond = part {
368                Int32Array::new(vec![0; self.len()].into(), self.nulls().cloned())
369            } else if let Some(tz) = get_tz(self.data_type())? {
370                let map_func = get_date_time_part_extract_fn(part);
371                self.unary_opt(|d| {
372                    timestamp_s_to_datetime(d)
373                        .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
374                        .map(map_func)
375                })
376            } else {
377                let map_func = get_date_time_part_extract_fn(part);
378                self.unary_opt(|d| timestamp_s_to_datetime(d).map(map_func))
379            };
380        Ok(array)
381    }
382}
383
384impl ExtractDatePartExt for PrimitiveArray<TimestampMillisecondType> {
385    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
386        let array = if let Some(tz) = get_tz(self.data_type())? {
387            let map_func = get_date_time_part_extract_fn(part);
388            self.unary_opt(|d| {
389                timestamp_ms_to_datetime(d)
390                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
391                    .map(map_func)
392            })
393        } else {
394            let map_func = get_date_time_part_extract_fn(part);
395            self.unary_opt(|d| timestamp_ms_to_datetime(d).map(map_func))
396        };
397        Ok(array)
398    }
399}
400
401impl ExtractDatePartExt for PrimitiveArray<TimestampMicrosecondType> {
402    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
403        let array = if let Some(tz) = get_tz(self.data_type())? {
404            let map_func = get_date_time_part_extract_fn(part);
405            self.unary_opt(|d| {
406                timestamp_us_to_datetime(d)
407                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
408                    .map(map_func)
409            })
410        } else {
411            let map_func = get_date_time_part_extract_fn(part);
412            self.unary_opt(|d| timestamp_us_to_datetime(d).map(map_func))
413        };
414        Ok(array)
415    }
416}
417
418impl ExtractDatePartExt for PrimitiveArray<TimestampNanosecondType> {
419    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
420        let array = if let Some(tz) = get_tz(self.data_type())? {
421            let map_func = get_date_time_part_extract_fn(part);
422            self.unary_opt(|d| {
423                timestamp_ns_to_datetime(d)
424                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
425                    .map(map_func)
426            })
427        } else {
428            let map_func = get_date_time_part_extract_fn(part);
429            self.unary_opt(|d| timestamp_ns_to_datetime(d).map(map_func))
430        };
431        Ok(array)
432    }
433}
434
435impl ExtractDatePartExt for PrimitiveArray<IntervalYearMonthType> {
436    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
437        match part {
438            DatePart::Year => Ok(self.unary_opt(|d| Some(d / 12))),
439            DatePart::Month => Ok(self.unary_opt(|d| Some(d % 12))),
440
441            DatePart::Quarter
442            | DatePart::Week
443            | DatePart::WeekISO
444            | DatePart::YearISO
445            | DatePart::Day
446            | DatePart::DayOfWeekSunday0
447            | DatePart::DayOfWeekMonday0
448            | DatePart::DayOfYear
449            | DatePart::Hour
450            | DatePart::Minute
451            | DatePart::Second
452            | DatePart::Millisecond
453            | DatePart::Microsecond
454            | DatePart::Nanosecond => {
455                return_compute_error_with!(format!("{part} does not support"), self.data_type())
456            }
457        }
458    }
459}
460
461impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> {
462    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
463        match part {
464            DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))),
465            DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))),
466            DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))),
467            DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000)))),
468            DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000))),
469            DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds))),
470            DatePart::Microsecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000))),
471            DatePart::Nanosecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000_000))),
472
473            DatePart::Quarter
474            | DatePart::Year
475            | DatePart::YearISO
476            | DatePart::WeekISO
477            | DatePart::Month
478            | DatePart::DayOfWeekSunday0
479            | DatePart::DayOfWeekMonday0
480            | DatePart::DayOfYear => {
481                return_compute_error_with!(format!("{part} does not support"), self.data_type())
482            }
483        }
484    }
485}
486
487impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> {
488    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
489        match part {
490            DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))),
491            DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months))),
492            DatePart::Week => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days / 7))),
493            DatePart::Day => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days))),
494            DatePart::Hour => {
495                Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 60 * 1_000_000_000)).try_into().ok()))
496            }
497            DatePart::Minute => {
498                Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 1_000_000_000)).try_into().ok()))
499            }
500            DatePart::Second => {
501                Ok(self.unary_opt(|d| (d.nanoseconds / 1_000_000_000).try_into().ok()))
502            }
503            DatePart::Millisecond => {
504                Ok(self.unary_opt(|d| (d.nanoseconds / 1_000_000).try_into().ok()))
505            }
506            DatePart::Microsecond => {
507                Ok(self.unary_opt(|d| (d.nanoseconds / 1_000).try_into().ok()))
508            }
509            DatePart::Nanosecond => Ok(self.unary_opt(|d| d.nanoseconds.try_into().ok())),
510
511            DatePart::Quarter
512            | DatePart::WeekISO
513            | DatePart::YearISO
514            | DatePart::DayOfWeekSunday0
515            | DatePart::DayOfWeekMonday0
516            | DatePart::DayOfYear => {
517                return_compute_error_with!(format!("{part} does not support"), self.data_type())
518            }
519        }
520    }
521}
522
523impl ExtractDatePartExt for PrimitiveArray<DurationSecondType> {
524    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
525        match part {
526            DatePart::Week => Ok(self.unary_opt(|d| (d / (60 * 60 * 24 * 7)).try_into().ok())),
527            DatePart::Day => Ok(self.unary_opt(|d| (d / (60 * 60 * 24)).try_into().ok())),
528            DatePart::Hour => Ok(self.unary_opt(|d| (d / (60 * 60)).try_into().ok())),
529            DatePart::Minute => Ok(self.unary_opt(|d| (d / 60).try_into().ok())),
530            DatePart::Second => Ok(self.unary_opt(|d| d.try_into().ok())),
531            DatePart::Millisecond => {
532                Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
533            }
534            DatePart::Microsecond => {
535                Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
536            }
537            DatePart::Nanosecond => Ok(
538                self.unary_opt(|d| d.checked_mul(1_000_000_000).and_then(|d| d.try_into().ok()))
539            ),
540
541            DatePart::Year
542            | DatePart::YearISO
543            | DatePart::WeekISO
544            | DatePart::Quarter
545            | DatePart::Month
546            | DatePart::DayOfWeekSunday0
547            | DatePart::DayOfWeekMonday0
548            | DatePart::DayOfYear => {
549                return_compute_error_with!(format!("{part} does not support"), self.data_type())
550            }
551        }
552    }
553}
554
555impl ExtractDatePartExt for PrimitiveArray<DurationMillisecondType> {
556    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
557        match part {
558            DatePart::Week => {
559                Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24 * 7)).try_into().ok()))
560            }
561            DatePart::Day => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24)).try_into().ok())),
562            DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60)).try_into().ok())),
563            DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000 * 60)).try_into().ok())),
564            DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
565            DatePart::Millisecond => Ok(self.unary_opt(|d| d.try_into().ok())),
566            DatePart::Microsecond => {
567                Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
568            }
569            DatePart::Nanosecond => {
570                Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
571            }
572
573            DatePart::Year
574            | DatePart::YearISO
575            | DatePart::WeekISO
576            | DatePart::Quarter
577            | DatePart::Month
578            | DatePart::DayOfWeekSunday0
579            | DatePart::DayOfWeekMonday0
580            | DatePart::DayOfYear => {
581                return_compute_error_with!(format!("{part} does not support"), self.data_type())
582            }
583        }
584    }
585}
586
587impl ExtractDatePartExt for PrimitiveArray<DurationMicrosecondType> {
588    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
589        match part {
590            DatePart::Week => {
591                Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
592            }
593            DatePart::Day => {
594                Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24)).try_into().ok()))
595            }
596            DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60)).try_into().ok())),
597            DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000 * 60)).try_into().ok())),
598            DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
599            DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
600            DatePart::Microsecond => Ok(self.unary_opt(|d| d.try_into().ok())),
601            DatePart::Nanosecond => {
602                Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
603            }
604
605            DatePart::Year
606            | DatePart::YearISO
607            | DatePart::WeekISO
608            | DatePart::Quarter
609            | DatePart::Month
610            | DatePart::DayOfWeekSunday0
611            | DatePart::DayOfWeekMonday0
612            | DatePart::DayOfYear => {
613                return_compute_error_with!(format!("{part} does not support"), self.data_type())
614            }
615        }
616    }
617}
618
619impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
620    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
621        match part {
622            DatePart::Week => {
623                Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
624            }
625            DatePart::Day => {
626                Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24)).try_into().ok()))
627            }
628            DatePart::Hour => {
629                Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60)).try_into().ok()))
630            }
631            DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60)).try_into().ok())),
632            DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000_000).try_into().ok())),
633            DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
634            DatePart::Microsecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
635            DatePart::Nanosecond => Ok(self.unary_opt(|d| d.try_into().ok())),
636
637            DatePart::Year
638            | DatePart::YearISO
639            | DatePart::WeekISO
640            | DatePart::Quarter
641            | DatePart::Month
642            | DatePart::DayOfWeekSunday0
643            | DatePart::DayOfWeekMonday0
644            | DatePart::DayOfYear => {
645                return_compute_error_with!(format!("{part} does not support"), self.data_type())
646            }
647        }
648    }
649}
650
651macro_rules! return_compute_error_with {
652    ($msg:expr, $param:expr) => {
653        return { Err(ArrowError::ComputeError(format!("{}: {:?}", $msg, $param))) }
654    };
655}
656
657pub(crate) use return_compute_error_with;
658
659// Internal trait, which is used for mapping values from DateLike structures
660trait ChronoDateExt {
661    /// Returns the day of week; Monday is encoded as `0`, Tuesday as `1`, etc.
662    fn num_days_from_monday(&self) -> i32;
663
664    /// Returns the day of week; Sunday is encoded as `0`, Monday as `1`, etc.
665    fn num_days_from_sunday(&self) -> i32;
666}
667
668impl<T: Datelike> ChronoDateExt for T {
669    fn num_days_from_monday(&self) -> i32 {
670        self.weekday().num_days_from_monday() as i32
671    }
672
673    fn num_days_from_sunday(&self) -> i32 {
674        self.weekday().num_days_from_sunday() as i32
675    }
676}
677
678/// Extracts the hours of a given array as an array of integers within
679/// the range of [0, 23]. If the given array isn't temporal primitive or dictionary array,
680/// an `Err` will be returned.
681#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
682pub fn hour_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
683    date_part(array, DatePart::Hour)
684}
685
686/// Extracts the hours of a given temporal primitive array as an array of integers within
687/// the range of [0, 23].
688#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
689pub fn hour<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
690where
691    T: ArrowTemporalType + ArrowNumericType,
692    i64: From<T::Native>,
693{
694    date_part_primitive(array, DatePart::Hour)
695}
696
697/// Extracts the years of a given temporal array as an array of integers.
698/// If the given array isn't temporal primitive or dictionary array,
699/// an `Err` will be returned.
700#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
701pub fn year_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
702    date_part(array, DatePart::Year)
703}
704
705/// Extracts the years of a given temporal primitive array as an array of integers
706#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
707pub fn year<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
708where
709    T: ArrowTemporalType + ArrowNumericType,
710    i64: From<T::Native>,
711{
712    date_part_primitive(array, DatePart::Year)
713}
714
715/// Extracts the quarter of a given temporal array as an array of integersa within
716/// the range of [1, 4]. If the given array isn't temporal primitive or dictionary array,
717/// an `Err` will be returned.
718#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
719pub fn quarter_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
720    date_part(array, DatePart::Quarter)
721}
722
723/// Extracts the quarter of a given temporal primitive array as an array of integers within
724/// the range of [1, 4].
725#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
726pub fn quarter<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
727where
728    T: ArrowTemporalType + ArrowNumericType,
729    i64: From<T::Native>,
730{
731    date_part_primitive(array, DatePart::Quarter)
732}
733
734/// Extracts the month of a given temporal array as an array of integers.
735/// If the given array isn't temporal primitive or dictionary array,
736/// an `Err` will be returned.
737#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
738pub fn month_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
739    date_part(array, DatePart::Month)
740}
741
742/// Extracts the month of a given temporal primitive array as an array of integers within
743/// the range of [1, 12].
744#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
745pub fn month<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
746where
747    T: ArrowTemporalType + ArrowNumericType,
748    i64: From<T::Native>,
749{
750    date_part_primitive(array, DatePart::Month)
751}
752
753/// Extracts the day of week of a given temporal array as an array of
754/// integers.
755///
756/// Monday is encoded as `0`, Tuesday as `1`, etc.
757///
758/// See also [`num_days_from_sunday`] which starts at Sunday.
759///
760/// If the given array isn't temporal primitive or dictionary array,
761/// an `Err` will be returned.
762#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
763pub fn num_days_from_monday_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
764    date_part(array, DatePart::DayOfWeekMonday0)
765}
766
767/// Extracts the day of week of a given temporal primitive array as an array of
768/// integers.
769///
770/// Monday is encoded as `0`, Tuesday as `1`, etc.
771///
772/// See also [`num_days_from_sunday`] which starts at Sunday.
773#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
774pub fn num_days_from_monday<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
775where
776    T: ArrowTemporalType + ArrowNumericType,
777    i64: From<T::Native>,
778{
779    date_part_primitive(array, DatePart::DayOfWeekMonday0)
780}
781
782/// Extracts the day of week of a given temporal array as an array of
783/// integers, starting at Sunday.
784///
785/// Sunday is encoded as `0`, Monday as `1`, etc.
786///
787/// See also [`num_days_from_monday`] which starts at Monday.
788///
789/// If the given array isn't temporal primitive or dictionary array,
790/// an `Err` will be returned.
791#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
792pub fn num_days_from_sunday_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
793    date_part(array, DatePart::DayOfWeekSunday0)
794}
795
796/// Extracts the day of week of a given temporal primitive array as an array of
797/// integers, starting at Sunday.
798///
799/// Sunday is encoded as `0`, Monday as `1`, etc.
800///
801/// See also [`num_days_from_monday`] which starts at Monday.
802#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
803pub fn num_days_from_sunday<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
804where
805    T: ArrowTemporalType + ArrowNumericType,
806    i64: From<T::Native>,
807{
808    date_part_primitive(array, DatePart::DayOfWeekSunday0)
809}
810
811/// Extracts the day of a given temporal array as an array of integers.
812///
813/// If the given array isn't temporal primitive or dictionary array,
814/// an `Err` will be returned.
815#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
816pub fn day_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
817    date_part(array, DatePart::Day)
818}
819
820/// Extracts the day of a given temporal primitive array as an array of integers
821#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
822pub fn day<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
823where
824    T: ArrowTemporalType + ArrowNumericType,
825    i64: From<T::Native>,
826{
827    date_part_primitive(array, DatePart::Day)
828}
829
830/// Extracts the day of year of a given temporal array as an array of integers.
831///
832/// The day of year that ranges from 1 to 366.
833/// If the given array isn't temporal primitive or dictionary array,
834/// an `Err` will be returned.
835#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
836pub fn doy_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
837    date_part(array, DatePart::DayOfYear)
838}
839
840/// Extracts the day of year of a given temporal primitive array as an array of integers.
841///
842/// The day of year that ranges from 1 to 366
843#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
844pub fn doy<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
845where
846    T: ArrowTemporalType + ArrowNumericType,
847    T::Native: ArrowNativeType,
848    i64: From<T::Native>,
849{
850    date_part_primitive(array, DatePart::DayOfYear)
851}
852
853/// Extracts the minutes of a given temporal primitive array as an array of integers
854#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
855pub fn minute<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
856where
857    T: ArrowTemporalType + ArrowNumericType,
858    i64: From<T::Native>,
859{
860    date_part_primitive(array, DatePart::Minute)
861}
862
863/// Extracts the week of a given temporal array as an array of integers.
864/// If the given array isn't temporal primitive or dictionary array,
865/// an `Err` will be returned.
866#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
867pub fn week_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
868    date_part(array, DatePart::Week)
869}
870
871/// Extracts the week of a given temporal primitive array as an array of integers
872#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
873pub fn week<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
874where
875    T: ArrowTemporalType + ArrowNumericType,
876    i64: From<T::Native>,
877{
878    date_part_primitive(array, DatePart::Week)
879}
880
881/// Extracts the seconds of a given temporal primitive array as an array of integers
882#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
883pub fn second<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
884where
885    T: ArrowTemporalType + ArrowNumericType,
886    i64: From<T::Native>,
887{
888    date_part_primitive(array, DatePart::Second)
889}
890
891/// Extracts the nanoseconds of a given temporal primitive array as an array of integers
892#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
893pub fn nanosecond<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
894where
895    T: ArrowTemporalType + ArrowNumericType,
896    i64: From<T::Native>,
897{
898    date_part_primitive(array, DatePart::Nanosecond)
899}
900
901/// Extracts the nanoseconds of a given temporal primitive array as an array of integers.
902/// If the given array isn't temporal primitive or dictionary array,
903/// an `Err` will be returned.
904#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
905pub fn nanosecond_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
906    date_part(array, DatePart::Nanosecond)
907}
908
909/// Extracts the microseconds of a given temporal primitive array as an array of integers
910#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
911pub fn microsecond<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
912where
913    T: ArrowTemporalType + ArrowNumericType,
914    i64: From<T::Native>,
915{
916    date_part_primitive(array, DatePart::Microsecond)
917}
918
919/// Extracts the microseconds of a given temporal primitive array as an array of integers.
920/// If the given array isn't temporal primitive or dictionary array,
921/// an `Err` will be returned.
922#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
923pub fn microsecond_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
924    date_part(array, DatePart::Microsecond)
925}
926
927/// Extracts the milliseconds of a given temporal primitive array as an array of integers
928#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
929pub fn millisecond<T>(array: &PrimitiveArray<T>) -> Result<Int32Array, ArrowError>
930where
931    T: ArrowTemporalType + ArrowNumericType,
932    i64: From<T::Native>,
933{
934    date_part_primitive(array, DatePart::Millisecond)
935}
936
937/// Extracts the milliseconds of a given temporal primitive array as an array of integers.
938/// If the given array isn't temporal primitive or dictionary array,
939/// an `Err` will be returned.
940#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
941pub fn millisecond_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
942    date_part(array, DatePart::Millisecond)
943}
944
945/// Extracts the minutes of a given temporal array as an array of integers.
946/// If the given array isn't temporal primitive or dictionary array,
947/// an `Err` will be returned.
948#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
949pub fn minute_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
950    date_part(array, DatePart::Minute)
951}
952
953/// Extracts the seconds of a given temporal array as an array of integers.
954/// If the given array isn't temporal primitive or dictionary array,
955/// an `Err` will be returned.
956#[deprecated(since = "51.0.0", note = "Use `date_part` instead")]
957pub fn second_dyn(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
958    date_part(array, DatePart::Second)
959}
960
961#[cfg(test)]
962#[allow(deprecated)]
963mod tests {
964    use super::*;
965
966    #[test]
967    fn test_temporal_array_date64_hour() {
968        let a: PrimitiveArray<Date64Type> =
969            vec![Some(1514764800000), None, Some(1550636625000)].into();
970
971        let b = hour(&a).unwrap();
972        assert_eq!(0, b.value(0));
973        assert!(!b.is_valid(1));
974        assert_eq!(4, b.value(2));
975    }
976
977    #[test]
978    fn test_temporal_array_date32_hour() {
979        let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
980
981        let b = hour(&a).unwrap();
982        assert_eq!(0, b.value(0));
983        assert!(!b.is_valid(1));
984        assert_eq!(0, b.value(2));
985    }
986
987    #[test]
988    fn test_temporal_array_time32_second_hour() {
989        let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
990
991        let b = hour(&a).unwrap();
992        assert_eq!(10, b.value(0));
993        assert_eq!(23, b.value(1));
994    }
995
996    #[test]
997    fn test_temporal_array_time64_micro_hour() {
998        let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
999
1000        let b = hour(&a).unwrap();
1001        assert_eq!(10, b.value(0));
1002        assert_eq!(23, b.value(1));
1003    }
1004
1005    #[test]
1006    fn test_temporal_array_timestamp_micro_hour() {
1007        let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
1008
1009        let b = hour(&a).unwrap();
1010        assert_eq!(10, b.value(0));
1011        assert_eq!(23, b.value(1));
1012    }
1013
1014    #[test]
1015    fn test_temporal_array_date64_year() {
1016        let a: PrimitiveArray<Date64Type> =
1017            vec![Some(1514764800000), None, Some(1550636625000)].into();
1018
1019        let b = year(&a).unwrap();
1020        assert_eq!(2018, b.value(0));
1021        assert!(!b.is_valid(1));
1022        assert_eq!(2019, b.value(2));
1023    }
1024
1025    #[test]
1026    fn test_temporal_array_date32_year() {
1027        let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
1028
1029        let b = year(&a).unwrap();
1030        assert_eq!(2011, b.value(0));
1031        assert!(!b.is_valid(1));
1032        assert_eq!(2012, b.value(2));
1033    }
1034
1035    #[test]
1036    fn test_temporal_array_date64_quarter() {
1037        //1514764800000 -> 2018-01-01
1038        //1566275025000 -> 2019-08-20
1039        let a: PrimitiveArray<Date64Type> =
1040            vec![Some(1514764800000), None, Some(1566275025000)].into();
1041
1042        let b = quarter(&a).unwrap();
1043        assert_eq!(1, b.value(0));
1044        assert!(!b.is_valid(1));
1045        assert_eq!(3, b.value(2));
1046    }
1047
1048    #[test]
1049    fn test_temporal_array_date32_quarter() {
1050        let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
1051
1052        let b = quarter(&a).unwrap();
1053        assert_eq!(1, b.value(0));
1054        assert!(!b.is_valid(1));
1055        assert_eq!(4, b.value(2));
1056    }
1057
1058    #[test]
1059    fn test_temporal_array_timestamp_quarter_with_timezone() {
1060        // 24 * 60 * 60 = 86400
1061        let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
1062        let b = quarter(&a).unwrap();
1063        assert_eq!(2, b.value(0));
1064        let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
1065        let b = quarter(&a).unwrap();
1066        assert_eq!(1, b.value(0));
1067    }
1068
1069    #[test]
1070    fn test_temporal_array_date64_month() {
1071        //1514764800000 -> 2018-01-01
1072        //1550636625000 -> 2019-02-20
1073        let a: PrimitiveArray<Date64Type> =
1074            vec![Some(1514764800000), None, Some(1550636625000)].into();
1075
1076        let b = month(&a).unwrap();
1077        assert_eq!(1, b.value(0));
1078        assert!(!b.is_valid(1));
1079        assert_eq!(2, b.value(2));
1080    }
1081
1082    #[test]
1083    fn test_temporal_array_date32_month() {
1084        let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
1085
1086        let b = month(&a).unwrap();
1087        assert_eq!(1, b.value(0));
1088        assert!(!b.is_valid(1));
1089        assert_eq!(2, b.value(2));
1090    }
1091
1092    #[test]
1093    fn test_temporal_array_timestamp_month_with_timezone() {
1094        // 24 * 60 * 60 = 86400
1095        let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
1096        let b = month(&a).unwrap();
1097        assert_eq!(2, b.value(0));
1098        let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
1099        let b = month(&a).unwrap();
1100        assert_eq!(1, b.value(0));
1101    }
1102
1103    #[test]
1104    fn test_temporal_array_timestamp_day_with_timezone() {
1105        // 24 * 60 * 60 = 86400
1106        let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
1107        let b = day(&a).unwrap();
1108        assert_eq!(2, b.value(0));
1109        let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
1110        let b = day(&a).unwrap();
1111        assert_eq!(1, b.value(0));
1112    }
1113
1114    #[test]
1115    fn test_temporal_array_date64_weekday() {
1116        //1514764800000 -> 2018-01-01 (Monday)
1117        //1550636625000 -> 2019-02-20 (Wednesday)
1118        let a: PrimitiveArray<Date64Type> =
1119            vec![Some(1514764800000), None, Some(1550636625000)].into();
1120
1121        let b = num_days_from_monday(&a).unwrap();
1122        assert_eq!(0, b.value(0));
1123        assert!(!b.is_valid(1));
1124        assert_eq!(2, b.value(2));
1125    }
1126
1127    #[test]
1128    fn test_temporal_array_date64_weekday0() {
1129        //1483228800000 -> 2017-01-01 (Sunday)
1130        //1514764800000 -> 2018-01-01 (Monday)
1131        //1550636625000 -> 2019-02-20 (Wednesday)
1132        let a: PrimitiveArray<Date64Type> = vec![
1133            Some(1483228800000),
1134            None,
1135            Some(1514764800000),
1136            Some(1550636625000),
1137        ]
1138        .into();
1139
1140        let b = num_days_from_sunday(&a).unwrap();
1141        assert_eq!(0, b.value(0));
1142        assert!(!b.is_valid(1));
1143        assert_eq!(1, b.value(2));
1144        assert_eq!(3, b.value(3));
1145    }
1146
1147    #[test]
1148    fn test_temporal_array_date64_day() {
1149        //1514764800000 -> 2018-01-01
1150        //1550636625000 -> 2019-02-20
1151        let a: PrimitiveArray<Date64Type> =
1152            vec![Some(1514764800000), None, Some(1550636625000)].into();
1153
1154        let b = day(&a).unwrap();
1155        assert_eq!(1, b.value(0));
1156        assert!(!b.is_valid(1));
1157        assert_eq!(20, b.value(2));
1158    }
1159
1160    #[test]
1161    fn test_temporal_array_date32_day() {
1162        let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
1163
1164        let b = day(&a).unwrap();
1165        assert_eq!(1, b.value(0));
1166        assert!(!b.is_valid(1));
1167        assert_eq!(1, b.value(2));
1168    }
1169
1170    #[test]
1171    fn test_temporal_array_date64_doy() {
1172        //1483228800000 -> 2017-01-01 (Sunday)
1173        //1514764800000 -> 2018-01-01
1174        //1550636625000 -> 2019-02-20
1175        let a: PrimitiveArray<Date64Type> = vec![
1176            Some(1483228800000),
1177            Some(1514764800000),
1178            None,
1179            Some(1550636625000),
1180        ]
1181        .into();
1182
1183        let b = doy(&a).unwrap();
1184        assert_eq!(1, b.value(0));
1185        assert_eq!(1, b.value(1));
1186        assert!(!b.is_valid(2));
1187        assert_eq!(51, b.value(3));
1188    }
1189
1190    #[test]
1191    fn test_temporal_array_timestamp_micro_year() {
1192        let a: TimestampMicrosecondArray =
1193            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1194
1195        let b = year(&a).unwrap();
1196        assert_eq!(2021, b.value(0));
1197        assert!(!b.is_valid(1));
1198        assert_eq!(2024, b.value(2));
1199    }
1200
1201    #[test]
1202    fn test_temporal_array_date64_minute() {
1203        let a: PrimitiveArray<Date64Type> =
1204            vec![Some(1514764800000), None, Some(1550636625000)].into();
1205
1206        let b = minute(&a).unwrap();
1207        assert_eq!(0, b.value(0));
1208        assert!(!b.is_valid(1));
1209        assert_eq!(23, b.value(2));
1210    }
1211
1212    #[test]
1213    fn test_temporal_array_timestamp_micro_minute() {
1214        let a: TimestampMicrosecondArray =
1215            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1216
1217        let b = minute(&a).unwrap();
1218        assert_eq!(57, b.value(0));
1219        assert!(!b.is_valid(1));
1220        assert_eq!(44, b.value(2));
1221    }
1222
1223    #[test]
1224    fn test_temporal_array_date32_week() {
1225        let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
1226
1227        let b = week(&a).unwrap();
1228        assert_eq!(1, b.value(0));
1229        assert!(!b.is_valid(1));
1230        assert_eq!(2, b.value(2));
1231    }
1232
1233    #[test]
1234    fn test_temporal_array_date64_week() {
1235        // 1646116175000 -> 2022.03.01 , 1641171600000 -> 2022.01.03
1236        // 1640998800000 -> 2022.01.01
1237        let a: PrimitiveArray<Date64Type> = vec![
1238            Some(1646116175000),
1239            None,
1240            Some(1641171600000),
1241            Some(1640998800000),
1242        ]
1243        .into();
1244
1245        let b = week(&a).unwrap();
1246        assert_eq!(9, b.value(0));
1247        assert!(!b.is_valid(1));
1248        assert_eq!(1, b.value(2));
1249        assert_eq!(52, b.value(3));
1250    }
1251
1252    #[test]
1253    fn test_temporal_array_timestamp_micro_week() {
1254        //1612025847000000 -> 2021.1.30
1255        //1722015847000000 -> 2024.7.27
1256        let a: TimestampMicrosecondArray =
1257            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1258
1259        let b = week(&a).unwrap();
1260        assert_eq!(4, b.value(0));
1261        assert!(!b.is_valid(1));
1262        assert_eq!(30, b.value(2));
1263    }
1264
1265    #[test]
1266    fn test_temporal_array_date64_second() {
1267        let a: PrimitiveArray<Date64Type> =
1268            vec![Some(1514764800000), None, Some(1550636625000)].into();
1269
1270        let b = second(&a).unwrap();
1271        assert_eq!(0, b.value(0));
1272        assert!(!b.is_valid(1));
1273        assert_eq!(45, b.value(2));
1274    }
1275
1276    #[test]
1277    fn test_temporal_array_timestamp_micro_second() {
1278        let a: TimestampMicrosecondArray =
1279            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1280
1281        let b = second(&a).unwrap();
1282        assert_eq!(27, b.value(0));
1283        assert!(!b.is_valid(1));
1284        assert_eq!(7, b.value(2));
1285    }
1286
1287    #[test]
1288    fn test_temporal_array_timestamp_second_with_timezone() {
1289        let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1290        let b = second(&a).unwrap();
1291        assert_eq!(10, b.value(0));
1292        assert_eq!(20, b.value(1));
1293    }
1294
1295    #[test]
1296    fn test_temporal_array_timestamp_minute_with_timezone() {
1297        let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1298        let b = minute(&a).unwrap();
1299        assert_eq!(50, b.value(0));
1300        assert_eq!(51, b.value(1));
1301    }
1302
1303    #[test]
1304    fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1305        let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1306        let b = minute(&a).unwrap();
1307        assert_eq!(5, b.value(0));
1308    }
1309
1310    #[test]
1311    fn test_temporal_array_timestamp_hour_with_timezone() {
1312        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1313        let b = hour(&a).unwrap();
1314        assert_eq!(11, b.value(0));
1315    }
1316
1317    #[test]
1318    fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1319        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1320        let b = hour(&a).unwrap();
1321        assert_eq!(11, b.value(0));
1322    }
1323
1324    #[test]
1325    fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1326        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1327        let b = hour(&a).unwrap();
1328        assert_eq!(11, b.value(0));
1329    }
1330
1331    #[test]
1332    fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1333        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1334        let err = hour(&a).unwrap_err().to_string();
1335        assert!(err.contains("Invalid timezone"), "{}", err);
1336    }
1337
1338    #[test]
1339    fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1340        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1341        let err = hour(&a).unwrap_err().to_string();
1342        assert!(err.contains("Invalid timezone"), "{}", err);
1343    }
1344
1345    #[test]
1346    fn test_temporal_array_timestamp_week_without_timezone() {
1347        // 1970-01-01T00:00:00                     -> 1970-01-01T00:00:00 Thursday (week 1)
1348        // 1970-01-01T00:00:00 + 4 days            -> 1970-01-05T00:00:00 Monday   (week 2)
1349        // 1970-01-01T00:00:00 + 4 days - 1 second -> 1970-01-04T23:59:59 Sunday   (week 1)
1350        let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1351        let b = week(&a).unwrap();
1352        assert_eq!(1, b.value(0));
1353        assert_eq!(2, b.value(1));
1354        assert_eq!(1, b.value(2));
1355    }
1356
1357    #[test]
1358    fn test_temporal_array_timestamp_week_with_timezone() {
1359        // 1970-01-01T01:00:00+01:00                     -> 1970-01-01T01:00:00+01:00 Thursday (week 1)
1360        // 1970-01-01T01:00:00+01:00 + 4 days            -> 1970-01-05T01:00:00+01:00 Monday   (week 2)
1361        // 1970-01-01T01:00:00+01:00 + 4 days - 1 second -> 1970-01-05T00:59:59+01:00 Monday   (week 2)
1362        let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1363            .with_timezone("+01:00".to_string());
1364        let b = week(&a).unwrap();
1365        assert_eq!(1, b.value(0));
1366        assert_eq!(2, b.value(1));
1367        assert_eq!(2, b.value(2));
1368    }
1369
1370    #[test]
1371    fn test_hour_minute_second_dictionary_array() {
1372        let a = TimestampSecondArray::from(vec![
1373            60 * 60 * 10 + 61,
1374            60 * 60 * 20 + 122,
1375            60 * 60 * 30 + 183,
1376        ])
1377        .with_timezone("+01:00".to_string());
1378
1379        let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1380        let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1381
1382        let b = hour_dyn(&dict).unwrap();
1383
1384        let expected_dict =
1385            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1386        let expected = Arc::new(expected_dict) as ArrayRef;
1387        assert_eq!(&expected, &b);
1388
1389        let b = date_part(&dict, DatePart::Minute).unwrap();
1390
1391        let b_old = minute_dyn(&dict).unwrap();
1392
1393        let expected_dict =
1394            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1395        let expected = Arc::new(expected_dict) as ArrayRef;
1396        assert_eq!(&expected, &b);
1397        assert_eq!(&expected, &b_old);
1398
1399        let b = date_part(&dict, DatePart::Second).unwrap();
1400
1401        let b_old = second_dyn(&dict).unwrap();
1402
1403        let expected_dict =
1404            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1405        let expected = Arc::new(expected_dict) as ArrayRef;
1406        assert_eq!(&expected, &b);
1407        assert_eq!(&expected, &b_old);
1408
1409        let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1410
1411        let expected_dict =
1412            DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1413        let expected = Arc::new(expected_dict) as ArrayRef;
1414        assert_eq!(&expected, &b);
1415    }
1416
1417    #[test]
1418    fn test_year_dictionary_array() {
1419        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1420
1421        let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1422        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1423
1424        let b = year_dyn(&dict).unwrap();
1425
1426        let expected_dict = DictionaryArray::new(
1427            keys,
1428            Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1429        );
1430        let expected = Arc::new(expected_dict) as ArrayRef;
1431        assert_eq!(&expected, &b);
1432    }
1433
1434    #[test]
1435    fn test_quarter_month_dictionary_array() {
1436        //1514764800000 -> 2018-01-01
1437        //1566275025000 -> 2019-08-20
1438        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1439
1440        let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1441        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1442
1443        let b = quarter_dyn(&dict).unwrap();
1444
1445        let expected =
1446            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1447        assert_eq!(b.as_ref(), &expected);
1448
1449        let b = month_dyn(&dict).unwrap();
1450
1451        let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1452        assert_eq!(b.as_ref(), &expected);
1453    }
1454
1455    #[test]
1456    fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1457        //1514764800000 -> 2018-01-01 (Monday)
1458        //1550636625000 -> 2019-02-20 (Wednesday)
1459        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1460
1461        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1462        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1463
1464        let b = num_days_from_monday_dyn(&dict).unwrap();
1465
1466        let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1467        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1468        assert_eq!(b.as_ref(), &expected);
1469
1470        let b = num_days_from_sunday_dyn(&dict).unwrap();
1471
1472        let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), None]);
1473        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1474        assert_eq!(b.as_ref(), &expected);
1475
1476        let b = day_dyn(&dict).unwrap();
1477
1478        let a = Int32Array::from(vec![Some(1), Some(20), Some(20), Some(1), None]);
1479        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1480        assert_eq!(b.as_ref(), &expected);
1481
1482        let b = doy_dyn(&dict).unwrap();
1483
1484        let a = Int32Array::from(vec![Some(1), Some(51), Some(51), Some(1), None]);
1485        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1486        assert_eq!(b.as_ref(), &expected);
1487
1488        let b = week_dyn(&dict).unwrap();
1489
1490        let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1491        let expected = DictionaryArray::new(keys, Arc::new(a));
1492        assert_eq!(b.as_ref(), &expected);
1493    }
1494
1495    #[test]
1496    fn test_temporal_array_date64_nanosecond() {
1497        // new Date(1667328721453)
1498        // Tue Nov 01 2022 11:52:01 GMT-0700 (Pacific Daylight Time)
1499        //
1500        // new Date(1667328721453).getMilliseconds()
1501        // 453
1502
1503        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1504
1505        let b = nanosecond(&a).unwrap();
1506        assert!(!b.is_valid(0));
1507        assert_eq!(453_000_000, b.value(1));
1508
1509        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1510        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1511        let b = nanosecond_dyn(&dict).unwrap();
1512
1513        let a = Int32Array::from(vec![None, Some(453_000_000)]);
1514        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1515        let expected = Arc::new(expected_dict) as ArrayRef;
1516        assert_eq!(&expected, &b);
1517    }
1518
1519    #[test]
1520    fn test_temporal_array_date64_microsecond() {
1521        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1522
1523        let b = microsecond(&a).unwrap();
1524        assert!(!b.is_valid(0));
1525        assert_eq!(453_000, b.value(1));
1526
1527        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1528        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1529        let b = microsecond_dyn(&dict).unwrap();
1530
1531        let a = Int32Array::from(vec![None, Some(453_000)]);
1532        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1533        let expected = Arc::new(expected_dict) as ArrayRef;
1534        assert_eq!(&expected, &b);
1535    }
1536
1537    #[test]
1538    fn test_temporal_array_date64_millisecond() {
1539        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1540
1541        let b = millisecond(&a).unwrap();
1542        assert!(!b.is_valid(0));
1543        assert_eq!(453, b.value(1));
1544
1545        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1546        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1547        let b = millisecond_dyn(&dict).unwrap();
1548
1549        let a = Int32Array::from(vec![None, Some(453)]);
1550        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1551        let expected = Arc::new(expected_dict) as ArrayRef;
1552        assert_eq!(&expected, &b);
1553    }
1554
1555    #[test]
1556    fn test_temporal_array_time64_nanoseconds() {
1557        // 23:32:50.123456789
1558        let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1559
1560        let actual = date_part(&input, DatePart::Hour).unwrap();
1561        let actual = actual.as_primitive::<Int32Type>();
1562        assert_eq!(23, actual.value(0));
1563
1564        let actual = date_part(&input, DatePart::Minute).unwrap();
1565        let actual = actual.as_primitive::<Int32Type>();
1566        assert_eq!(32, actual.value(0));
1567
1568        let actual = date_part(&input, DatePart::Second).unwrap();
1569        let actual = actual.as_primitive::<Int32Type>();
1570        assert_eq!(50, actual.value(0));
1571
1572        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1573        let actual = actual.as_primitive::<Int32Type>();
1574        assert_eq!(123, actual.value(0));
1575
1576        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1577        let actual = actual.as_primitive::<Int32Type>();
1578        assert_eq!(123_456, actual.value(0));
1579
1580        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1581        let actual = actual.as_primitive::<Int32Type>();
1582        assert_eq!(123_456_789, actual.value(0));
1583
1584        // invalid values should turn into null
1585        let input: Time64NanosecondArray = vec![
1586            Some(-1),
1587            Some(86_400_000_000_000),
1588            Some(86_401_000_000_000),
1589            None,
1590        ]
1591        .into();
1592        let actual = date_part(&input, DatePart::Hour).unwrap();
1593        let actual = actual.as_primitive::<Int32Type>();
1594        let expected: Int32Array = vec![None, None, None, None].into();
1595        assert_eq!(&expected, actual);
1596    }
1597
1598    #[test]
1599    fn test_temporal_array_time64_microseconds() {
1600        // 23:32:50.123456
1601        let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1602
1603        let actual = date_part(&input, DatePart::Hour).unwrap();
1604        let actual = actual.as_primitive::<Int32Type>();
1605        assert_eq!(23, actual.value(0));
1606
1607        let actual = date_part(&input, DatePart::Minute).unwrap();
1608        let actual = actual.as_primitive::<Int32Type>();
1609        assert_eq!(32, actual.value(0));
1610
1611        let actual = date_part(&input, DatePart::Second).unwrap();
1612        let actual = actual.as_primitive::<Int32Type>();
1613        assert_eq!(50, actual.value(0));
1614
1615        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1616        let actual = actual.as_primitive::<Int32Type>();
1617        assert_eq!(123, actual.value(0));
1618
1619        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1620        let actual = actual.as_primitive::<Int32Type>();
1621        assert_eq!(123_456, actual.value(0));
1622
1623        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1624        let actual = actual.as_primitive::<Int32Type>();
1625        assert_eq!(123_456_000, actual.value(0));
1626
1627        // invalid values should turn into null
1628        let input: Time64MicrosecondArray =
1629            vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1630        let actual = date_part(&input, DatePart::Hour).unwrap();
1631        let actual = actual.as_primitive::<Int32Type>();
1632        let expected: Int32Array = vec![None, None, None, None].into();
1633        assert_eq!(&expected, actual);
1634    }
1635
1636    #[test]
1637    fn test_temporal_array_time32_milliseconds() {
1638        // 23:32:50.123
1639        let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1640
1641        let actual = date_part(&input, DatePart::Hour).unwrap();
1642        let actual = actual.as_primitive::<Int32Type>();
1643        assert_eq!(23, actual.value(0));
1644
1645        let actual = date_part(&input, DatePart::Minute).unwrap();
1646        let actual = actual.as_primitive::<Int32Type>();
1647        assert_eq!(32, actual.value(0));
1648
1649        let actual = date_part(&input, DatePart::Second).unwrap();
1650        let actual = actual.as_primitive::<Int32Type>();
1651        assert_eq!(50, actual.value(0));
1652
1653        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1654        let actual = actual.as_primitive::<Int32Type>();
1655        assert_eq!(123, actual.value(0));
1656
1657        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1658        let actual = actual.as_primitive::<Int32Type>();
1659        assert_eq!(123_000, actual.value(0));
1660
1661        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1662        let actual = actual.as_primitive::<Int32Type>();
1663        assert_eq!(123_000_000, actual.value(0));
1664
1665        // invalid values should turn into null
1666        let input: Time32MillisecondArray =
1667            vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1668        let actual = date_part(&input, DatePart::Hour).unwrap();
1669        let actual = actual.as_primitive::<Int32Type>();
1670        let expected: Int32Array = vec![None, None, None, None].into();
1671        assert_eq!(&expected, actual);
1672    }
1673
1674    #[test]
1675    fn test_temporal_array_time32_seconds() {
1676        // 23:32:50
1677        let input: Time32SecondArray = vec![84_770].into();
1678
1679        let actual = date_part(&input, DatePart::Hour).unwrap();
1680        let actual = actual.as_primitive::<Int32Type>();
1681        assert_eq!(23, actual.value(0));
1682
1683        let actual = date_part(&input, DatePart::Minute).unwrap();
1684        let actual = actual.as_primitive::<Int32Type>();
1685        assert_eq!(32, actual.value(0));
1686
1687        let actual = date_part(&input, DatePart::Second).unwrap();
1688        let actual = actual.as_primitive::<Int32Type>();
1689        assert_eq!(50, actual.value(0));
1690
1691        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1692        let actual = actual.as_primitive::<Int32Type>();
1693        assert_eq!(0, actual.value(0));
1694
1695        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1696        let actual = actual.as_primitive::<Int32Type>();
1697        assert_eq!(0, actual.value(0));
1698
1699        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1700        let actual = actual.as_primitive::<Int32Type>();
1701        assert_eq!(0, actual.value(0));
1702
1703        // invalid values should turn into null
1704        let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1705        let actual = date_part(&input, DatePart::Hour).unwrap();
1706        let actual = actual.as_primitive::<Int32Type>();
1707        let expected: Int32Array = vec![None, None, None, None].into();
1708        assert_eq!(&expected, actual);
1709    }
1710
1711    #[test]
1712    fn test_temporal_array_time_invalid_parts() {
1713        fn ensure_returns_error(array: &dyn Array) {
1714            let invalid_parts = [
1715                DatePart::Quarter,
1716                DatePart::Year,
1717                DatePart::Month,
1718                DatePart::Week,
1719                DatePart::Day,
1720                DatePart::DayOfWeekSunday0,
1721                DatePart::DayOfWeekMonday0,
1722                DatePart::DayOfYear,
1723            ];
1724
1725            for part in invalid_parts {
1726                let err = date_part(array, part).unwrap_err();
1727                let expected = format!(
1728                    "Compute error: {part} does not support: {}",
1729                    array.data_type()
1730                );
1731                assert_eq!(expected, err.to_string());
1732            }
1733        }
1734
1735        ensure_returns_error(&Time32SecondArray::from(vec![0]));
1736        ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1737        ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1738        ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1739    }
1740
1741    #[test]
1742    fn test_interval_year_month_array() {
1743        let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1744
1745        let actual = date_part(&input, DatePart::Year).unwrap();
1746        let actual = actual.as_primitive::<Int32Type>();
1747        assert_eq!(0, actual.value(0));
1748        assert_eq!(0, actual.value(1));
1749        assert_eq!(2, actual.value(2));
1750
1751        let actual = date_part(&input, DatePart::Month).unwrap();
1752        let actual = actual.as_primitive::<Int32Type>();
1753        assert_eq!(0, actual.value(0));
1754        assert_eq!(5, actual.value(1));
1755        assert_eq!(0, actual.value(2));
1756
1757        assert!(date_part(&input, DatePart::Day).is_err());
1758        assert!(date_part(&input, DatePart::Week).is_err());
1759    }
1760
1761    // IntervalDayTimeType week, day, hour, minute, second, milli, u, nano;
1762    // invalid month, year; ignores the other part
1763    #[test]
1764    fn test_interval_day_time_array() {
1765        let input: IntervalDayTimeArray = vec![
1766            IntervalDayTime::ZERO,
1767            IntervalDayTime::new(10, 42),
1768            IntervalDayTime::new(10, 1042),
1769            IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1),
1770        ]
1771        .into();
1772
1773        // Time doesn't affect days.
1774        let actual = date_part(&input, DatePart::Day).unwrap();
1775        let actual = actual.as_primitive::<Int32Type>();
1776        assert_eq!(0, actual.value(0));
1777        assert_eq!(10, actual.value(1));
1778        assert_eq!(10, actual.value(2));
1779        assert_eq!(10, actual.value(3));
1780
1781        let actual = date_part(&input, DatePart::Week).unwrap();
1782        let actual = actual.as_primitive::<Int32Type>();
1783        assert_eq!(0, actual.value(0));
1784        assert_eq!(1, actual.value(1));
1785        assert_eq!(1, actual.value(2));
1786        assert_eq!(1, actual.value(3));
1787
1788        // Days doesn't affect time.
1789        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1790        let actual = actual.as_primitive::<Int32Type>();
1791        assert_eq!(0, actual.value(0));
1792        assert_eq!(42_000_000, actual.value(1));
1793        assert_eq!(1_042_000_000, actual.value(2));
1794        // Overflow returns zero.
1795        assert_eq!(0, actual.value(3));
1796
1797        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1798        let actual = actual.as_primitive::<Int32Type>();
1799        assert_eq!(0, actual.value(0));
1800        assert_eq!(42_000, actual.value(1));
1801        assert_eq!(1_042_000, actual.value(2));
1802        // Overflow returns zero.
1803        assert_eq!(0, actual.value(3));
1804
1805        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1806        let actual = actual.as_primitive::<Int32Type>();
1807        assert_eq!(0, actual.value(0));
1808        assert_eq!(42, actual.value(1));
1809        assert_eq!(1042, actual.value(2));
1810        assert_eq!(MILLISECONDS_IN_DAY as i32 + 1, actual.value(3));
1811
1812        let actual = date_part(&input, DatePart::Second).unwrap();
1813        let actual = actual.as_primitive::<Int32Type>();
1814        assert_eq!(0, actual.value(0));
1815        assert_eq!(0, actual.value(1));
1816        assert_eq!(1, actual.value(2));
1817        assert_eq!(24 * 60 * 60, actual.value(3));
1818
1819        let actual = date_part(&input, DatePart::Minute).unwrap();
1820        let actual = actual.as_primitive::<Int32Type>();
1821        assert_eq!(0, actual.value(0));
1822        assert_eq!(0, actual.value(1));
1823        assert_eq!(0, actual.value(2));
1824        assert_eq!(24 * 60, actual.value(3));
1825
1826        let actual = date_part(&input, DatePart::Hour).unwrap();
1827        let actual = actual.as_primitive::<Int32Type>();
1828        assert_eq!(0, actual.value(0));
1829        assert_eq!(0, actual.value(1));
1830        assert_eq!(0, actual.value(2));
1831        assert_eq!(24, actual.value(3));
1832
1833        // Month and year are not valid (since days in month varies).
1834        assert!(date_part(&input, DatePart::Month).is_err());
1835        assert!(date_part(&input, DatePart::Year).is_err());
1836    }
1837
1838    // IntervalMonthDayNanoType year -> nano;
1839    // days don't affect months, time doesn't affect days, time doesn't affect months (and vice versa)
1840    #[test]
1841    fn test_interval_month_day_nano_array() {
1842        let input: IntervalMonthDayNanoArray = vec![
1843            IntervalMonthDayNano::ZERO,
1844            IntervalMonthDayNano::new(5, 10, 42),
1845            IntervalMonthDayNano::new(16, 35, MILLISECONDS_IN_DAY * 1_000_000 + 1),
1846        ]
1847        .into();
1848
1849        // Year and month follow from month, but are not affected by days or nanos.
1850        let actual = date_part(&input, DatePart::Year).unwrap();
1851        let actual = actual.as_primitive::<Int32Type>();
1852        assert_eq!(0, actual.value(0));
1853        assert_eq!(0, actual.value(1));
1854        assert_eq!(1, actual.value(2));
1855
1856        let actual = date_part(&input, DatePart::Month).unwrap();
1857        let actual = actual.as_primitive::<Int32Type>();
1858        assert_eq!(0, actual.value(0));
1859        assert_eq!(5, actual.value(1));
1860        assert_eq!(16, actual.value(2));
1861
1862        // Week and day follow from day, but are not affected by months or nanos.
1863        let actual = date_part(&input, DatePart::Week).unwrap();
1864        let actual = actual.as_primitive::<Int32Type>();
1865        assert_eq!(0, actual.value(0));
1866        assert_eq!(1, actual.value(1));
1867        assert_eq!(5, actual.value(2));
1868
1869        let actual = date_part(&input, DatePart::Day).unwrap();
1870        let actual = actual.as_primitive::<Int32Type>();
1871        assert_eq!(0, actual.value(0));
1872        assert_eq!(10, actual.value(1));
1873        assert_eq!(35, actual.value(2));
1874
1875        // Times follow from nanos, but are not affected by months or days.
1876        let actual = date_part(&input, DatePart::Hour).unwrap();
1877        let actual = actual.as_primitive::<Int32Type>();
1878        assert_eq!(0, actual.value(0));
1879        assert_eq!(0, actual.value(1));
1880        assert_eq!(24, actual.value(2));
1881
1882        let actual = date_part(&input, DatePart::Minute).unwrap();
1883        let actual = actual.as_primitive::<Int32Type>();
1884        assert_eq!(0, actual.value(0));
1885        assert_eq!(0, actual.value(1));
1886        assert_eq!(24 * 60, actual.value(2));
1887
1888        let actual = date_part(&input, DatePart::Second).unwrap();
1889        let actual = actual.as_primitive::<Int32Type>();
1890        assert_eq!(0, actual.value(0));
1891        assert_eq!(0, actual.value(1));
1892        assert_eq!(24 * 60 * 60, actual.value(2));
1893
1894        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1895        let actual = actual.as_primitive::<Int32Type>();
1896        assert_eq!(0, actual.value(0));
1897        assert_eq!(0, actual.value(1));
1898        assert_eq!(24 * 60 * 60 * 1_000, actual.value(2));
1899
1900        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1901        let actual = actual.as_primitive::<Int32Type>();
1902        assert_eq!(0, actual.value(0));
1903        assert_eq!(0, actual.value(1));
1904        // Overflow gives zero.
1905        assert_eq!(0, actual.value(2));
1906
1907        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1908        let actual = actual.as_primitive::<Int32Type>();
1909        assert_eq!(0, actual.value(0));
1910        assert_eq!(42, actual.value(1));
1911        // Overflow gives zero.
1912        assert_eq!(0, actual.value(2));
1913    }
1914
1915    #[test]
1916    fn test_interval_array_invalid_parts() {
1917        fn ensure_returns_error(array: &dyn Array) {
1918            let invalid_parts = [
1919                DatePart::Quarter,
1920                DatePart::DayOfWeekSunday0,
1921                DatePart::DayOfWeekMonday0,
1922                DatePart::DayOfYear,
1923            ];
1924
1925            for part in invalid_parts {
1926                let err = date_part(array, part).unwrap_err();
1927                let expected = format!(
1928                    "Compute error: {part} does not support: {}",
1929                    array.data_type()
1930                );
1931                assert_eq!(expected, err.to_string());
1932            }
1933        }
1934
1935        ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
1936        ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
1937        ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
1938            IntervalMonthDayNano::ZERO,
1939        ]));
1940    }
1941
1942    #[test]
1943    fn test_duration_second() {
1944        let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1945
1946        let actual = date_part(&input, DatePart::Second).unwrap();
1947        let actual = actual.as_primitive::<Int32Type>();
1948        assert_eq!(0, actual.value(0));
1949        assert_eq!(42, actual.value(1));
1950        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1951
1952        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1953        let actual = actual.as_primitive::<Int32Type>();
1954        assert_eq!(0, actual.value(0));
1955        assert_eq!(42_000, actual.value(1));
1956        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1957
1958        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1959        let actual = actual.as_primitive::<Int32Type>();
1960        assert_eq!(0, actual.value(0));
1961        assert_eq!(42_000_000, actual.value(1));
1962        assert_eq!(0, actual.value(2));
1963
1964        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1965        let actual = actual.as_primitive::<Int32Type>();
1966        assert_eq!(0, actual.value(0));
1967        assert_eq!(0, actual.value(1));
1968        assert_eq!(0, actual.value(2));
1969    }
1970
1971    #[test]
1972    fn test_duration_millisecond() {
1973        let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1974
1975        let actual = date_part(&input, DatePart::Second).unwrap();
1976        let actual = actual.as_primitive::<Int32Type>();
1977        assert_eq!(0, actual.value(0));
1978        assert_eq!(0, actual.value(1));
1979        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1980
1981        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1982        let actual = actual.as_primitive::<Int32Type>();
1983        assert_eq!(0, actual.value(0));
1984        assert_eq!(42, actual.value(1));
1985        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1986
1987        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1988        let actual = actual.as_primitive::<Int32Type>();
1989        assert_eq!(0, actual.value(0));
1990        assert_eq!(42_000, actual.value(1));
1991        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1992
1993        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1994        let actual = actual.as_primitive::<Int32Type>();
1995        assert_eq!(0, actual.value(0));
1996        assert_eq!(42_000_000, actual.value(1));
1997        assert_eq!(0, actual.value(2));
1998    }
1999
2000    #[test]
2001    fn test_duration_microsecond() {
2002        let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2003
2004        let actual = date_part(&input, DatePart::Second).unwrap();
2005        let actual = actual.as_primitive::<Int32Type>();
2006        assert_eq!(0, actual.value(0));
2007        assert_eq!(0, actual.value(1));
2008        assert_eq!(0, actual.value(2));
2009
2010        let actual = date_part(&input, DatePart::Millisecond).unwrap();
2011        let actual = actual.as_primitive::<Int32Type>();
2012        assert_eq!(0, actual.value(0));
2013        assert_eq!(0, actual.value(1));
2014        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2015
2016        let actual = date_part(&input, DatePart::Microsecond).unwrap();
2017        let actual = actual.as_primitive::<Int32Type>();
2018        assert_eq!(0, actual.value(0));
2019        assert_eq!(42, actual.value(1));
2020        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2021
2022        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2023        let actual = actual.as_primitive::<Int32Type>();
2024        assert_eq!(0, actual.value(0));
2025        assert_eq!(42_000, actual.value(1));
2026        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
2027    }
2028
2029    #[test]
2030    fn test_duration_nanosecond() {
2031        let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2032
2033        let actual = date_part(&input, DatePart::Second).unwrap();
2034        let actual = actual.as_primitive::<Int32Type>();
2035        assert_eq!(0, actual.value(0));
2036        assert_eq!(0, actual.value(1));
2037        assert_eq!(0, actual.value(2));
2038
2039        let actual = date_part(&input, DatePart::Millisecond).unwrap();
2040        let actual = actual.as_primitive::<Int32Type>();
2041        assert_eq!(0, actual.value(0));
2042        assert_eq!(0, actual.value(1));
2043        assert_eq!(0, actual.value(2));
2044
2045        let actual = date_part(&input, DatePart::Microsecond).unwrap();
2046        let actual = actual.as_primitive::<Int32Type>();
2047        assert_eq!(0, actual.value(0));
2048        assert_eq!(0, actual.value(1));
2049        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2050
2051        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2052        let actual = actual.as_primitive::<Int32Type>();
2053        assert_eq!(0, actual.value(0));
2054        assert_eq!(42, actual.value(1));
2055        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2056    }
2057
2058    #[test]
2059    fn test_duration_invalid_parts() {
2060        fn ensure_returns_error(array: &dyn Array) {
2061            let invalid_parts = [
2062                DatePart::Year,
2063                DatePart::Quarter,
2064                DatePart::Month,
2065                DatePart::DayOfWeekSunday0,
2066                DatePart::DayOfWeekMonday0,
2067                DatePart::DayOfYear,
2068            ];
2069
2070            for part in invalid_parts {
2071                let err = date_part(array, part).unwrap_err();
2072                let expected = format!(
2073                    "Compute error: {part} does not support: {}",
2074                    array.data_type()
2075                );
2076                assert_eq!(expected, err.to_string());
2077            }
2078        }
2079
2080        ensure_returns_error(&DurationSecondArray::from(vec![0]));
2081        ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
2082        ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
2083        ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
2084    }
2085
2086    const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
2087    const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
2088    const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
2089    const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
2090    // In 2018 the ISO year and calendar year start on the same date— 2018-01-01 or 2018-W01-1
2091    #[test]
2092    fn test_temporal_array_date64_week_iso() {
2093        let a: PrimitiveArray<Date64Type> = vec![
2094            Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2095            Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2096        ]
2097        .into();
2098
2099        let b = date_part(&a, DatePart::WeekISO).unwrap();
2100        let actual = b.as_primitive::<Int32Type>();
2101        assert_eq!(1, actual.value(0));
2102        assert_eq!(8, actual.value(1));
2103    }
2104
2105    #[test]
2106    fn test_temporal_array_date64_year_iso() {
2107        let a: PrimitiveArray<Date64Type> = vec![
2108            Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2109            Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2110        ]
2111        .into();
2112
2113        let b = date_part(&a, DatePart::YearISO).unwrap();
2114        let actual = b.as_primitive::<Int32Type>();
2115        assert_eq!(2018, actual.value(0));
2116        assert_eq!(2019, actual.value(1));
2117    }
2118
2119    #[test]
2120    fn test_temporal_array_timestamp_week_iso() {
2121        let a = TimestampSecondArray::from(vec![
2122            TIMESTAMP_SECOND_1970_01_01, // 0 and is Thursday
2123            SECONDS_IN_DAY * 4,          //  Monday of week 2
2124            SECONDS_IN_DAY * 4 - 1,      // Sunday of week 1
2125        ]);
2126        let b = date_part(&a, DatePart::WeekISO).unwrap();
2127        let actual = b.as_primitive::<Int32Type>();
2128        assert_eq!(1, actual.value(0));
2129        assert_eq!(2, actual.value(1));
2130        assert_eq!(1, actual.value(2));
2131    }
2132
2133    #[test]
2134    fn test_temporal_array_timestamp_year_iso() {
2135        let a = TimestampSecondArray::from(vec![
2136            TIMESTAMP_SECOND_1970_01_01,
2137            SECONDS_IN_DAY * 4,
2138            SECONDS_IN_DAY * 4 - 1,
2139        ]);
2140        let b = date_part(&a, DatePart::YearISO).unwrap();
2141        let actual = b.as_primitive::<Int32Type>();
2142        assert_eq!(1970, actual.value(0));
2143        assert_eq!(1970, actual.value(1));
2144        assert_eq!(1970, actual.value(2));
2145    }
2146
2147    const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
2148    const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
2149    // January 1st 2016 is a Friday, so 2015 week 53 runs from
2150    // 2015-12-28 to 2016-01-03 inclusive, and
2151    // 2016 week 1 runs from 2016-01-04 to 2016-01-10 inclusive.
2152    #[test]
2153    fn test_temporal_array_date64_week_iso_edge_cases() {
2154        let a: PrimitiveArray<Date64Type> = vec![
2155            Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2156            Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2157            Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2158        ]
2159        .into();
2160
2161        let b = date_part(&a, DatePart::WeekISO).unwrap();
2162        let actual = b.as_primitive::<Int32Type>();
2163        assert_eq!(53, actual.value(0));
2164        assert_eq!(53, actual.value(1));
2165        assert_eq!(1, actual.value(2));
2166    }
2167
2168    #[test]
2169    fn test_temporal_array_date64_year_iso_edge_cases() {
2170        let a: PrimitiveArray<Date64Type> = vec![
2171            Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2172            Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2173            Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2174        ]
2175        .into();
2176
2177        let b = date_part(&a, DatePart::YearISO).unwrap();
2178        let actual = b.as_primitive::<Int32Type>();
2179        assert_eq!(2015, actual.value(0));
2180        assert_eq!(2015, actual.value(1));
2181        assert_eq!(2016, actual.value(2));
2182    }
2183
2184    #[test]
2185    fn test_temporal_array_timestamp_week_iso_edge_cases() {
2186        let a = TimestampSecondArray::from(vec![
2187            TIMESTAMP_SECOND_2015_12_28,
2188            TIMESTAMP_SECOND_2016_01_03,
2189            TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2190        ]);
2191        let b = date_part(&a, DatePart::WeekISO).unwrap();
2192        let actual = b.as_primitive::<Int32Type>();
2193        assert_eq!(53, actual.value(0));
2194        assert_eq!(53, actual.value(1));
2195        assert_eq!(1, actual.value(2));
2196    }
2197
2198    #[test]
2199    fn test_temporal_array_timestamp_year_iso_edge_cases() {
2200        let a = TimestampSecondArray::from(vec![
2201            TIMESTAMP_SECOND_2015_12_28,
2202            TIMESTAMP_SECOND_2016_01_03,
2203            TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2204        ]);
2205        let b = date_part(&a, DatePart::YearISO).unwrap();
2206        let actual = b.as_primitive::<Int32Type>();
2207        assert_eq!(2015, actual.value(0));
2208        assert_eq!(2015, actual.value(1));
2209        assert_eq!(2016, actual.value(2));
2210    }
2211}