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    MICROSECONDS, MICROSECONDS_IN_DAY, MILLISECONDS, MILLISECONDS_IN_DAY, NANOSECONDS,
28    NANOSECONDS_IN_DAY, SECONDS_IN_DAY, date32_to_datetime, date64_to_datetime,
29    timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_s_to_datetime,
30    timestamp_us_to_datetime,
31};
32use arrow_array::timezone::Tz;
33use arrow_array::types::*;
34use arrow_array::*;
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/// Extract optional [`Tz`] from timestamp data types, returning error
201/// if called with a non-timestamp type.
202fn get_tz(dt: &DataType) -> Result<Option<Tz>, ArrowError> {
203    match dt {
204        DataType::Timestamp(_, Some(tz)) => Ok(Some(tz.parse::<Tz>()?)),
205        DataType::Timestamp(_, None) => Ok(None),
206        _ => Err(ArrowError::CastError(format!("Not a timestamp type: {dt}"))),
207    }
208}
209
210/// Implement the specialized functions for extracting date part from temporal arrays.
211trait ExtractDatePartExt {
212    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError>;
213}
214
215impl ExtractDatePartExt for PrimitiveArray<Time32SecondType> {
216    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
217        #[inline]
218        fn range_check(s: i32) -> bool {
219            (0..SECONDS_IN_DAY as i32).contains(&s)
220        }
221        match part {
222            DatePart::Hour => Ok(self.unary_opt(|s| range_check(s).then_some(s / 3_600))),
223            DatePart::Minute => Ok(self.unary_opt(|s| range_check(s).then_some((s / 60) % 60))),
224            DatePart::Second => Ok(self.unary_opt(|s| range_check(s).then_some(s % 60))),
225            // Time32Second only encodes number of seconds, so these will always be 0 (if in valid range)
226            DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond => {
227                Ok(self.unary_opt(|s| range_check(s).then_some(0)))
228            }
229            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
230        }
231    }
232}
233
234impl ExtractDatePartExt for PrimitiveArray<Time32MillisecondType> {
235    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
236        #[inline]
237        fn range_check(ms: i32) -> bool {
238            (0..MILLISECONDS_IN_DAY as i32).contains(&ms)
239        }
240        let milliseconds = MILLISECONDS as i32;
241        match part {
242            DatePart::Hour => {
243                Ok(self.unary_opt(|ms| range_check(ms).then_some(ms / 3_600 / milliseconds)))
244            }
245            DatePart::Minute => {
246                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / 60 / milliseconds) % 60)))
247            }
248            DatePart::Second => {
249                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / milliseconds) % 60)))
250            }
251            DatePart::Millisecond => {
252                Ok(self.unary_opt(|ms| range_check(ms).then_some(ms % milliseconds)))
253            }
254            DatePart::Microsecond => {
255                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000)))
256            }
257            DatePart::Nanosecond => {
258                Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000_000)))
259            }
260            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
261        }
262    }
263}
264
265impl ExtractDatePartExt for PrimitiveArray<Time64MicrosecondType> {
266    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
267        #[inline]
268        fn range_check(us: i64) -> bool {
269            (0..MICROSECONDS_IN_DAY).contains(&us)
270        }
271        match part {
272            DatePart::Hour => {
273                Ok(self
274                    .unary_opt(|us| range_check(us).then_some((us / 3_600 / MICROSECONDS) as i32)))
275            }
276            DatePart::Minute => Ok(self
277                .unary_opt(|us| range_check(us).then_some(((us / 60 / MICROSECONDS) % 60) as i32))),
278            DatePart::Second => {
279                Ok(self
280                    .unary_opt(|us| range_check(us).then_some(((us / MICROSECONDS) % 60) as i32)))
281            }
282            DatePart::Millisecond => Ok(self
283                .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) / 1_000) as i32))),
284            DatePart::Microsecond => {
285                Ok(self.unary_opt(|us| range_check(us).then_some((us % MICROSECONDS) as i32)))
286            }
287            DatePart::Nanosecond => Ok(self
288                .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) * 1_000) as i32))),
289            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
290        }
291    }
292}
293
294impl ExtractDatePartExt for PrimitiveArray<Time64NanosecondType> {
295    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
296        #[inline]
297        fn range_check(ns: i64) -> bool {
298            (0..NANOSECONDS_IN_DAY).contains(&ns)
299        }
300        match part {
301            DatePart::Hour => {
302                Ok(self
303                    .unary_opt(|ns| range_check(ns).then_some((ns / 3_600 / NANOSECONDS) as i32)))
304            }
305            DatePart::Minute => Ok(self
306                .unary_opt(|ns| range_check(ns).then_some(((ns / 60 / NANOSECONDS) % 60) as i32))),
307            DatePart::Second => Ok(
308                self.unary_opt(|ns| range_check(ns).then_some(((ns / NANOSECONDS) % 60) as i32))
309            ),
310            DatePart::Millisecond => Ok(self.unary_opt(|ns| {
311                range_check(ns).then_some(((ns % NANOSECONDS) / 1_000_000) as i32)
312            })),
313            DatePart::Microsecond => {
314                Ok(self
315                    .unary_opt(|ns| range_check(ns).then_some(((ns % NANOSECONDS) / 1_000) as i32)))
316            }
317            DatePart::Nanosecond => {
318                Ok(self.unary_opt(|ns| range_check(ns).then_some((ns % NANOSECONDS) as i32)))
319            }
320            _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
321        }
322    }
323}
324
325impl ExtractDatePartExt for PrimitiveArray<Date32Type> {
326    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
327        // Date32 only encodes number of days, so these will always be 0
328        if let DatePart::Hour
329        | DatePart::Minute
330        | DatePart::Second
331        | DatePart::Millisecond
332        | DatePart::Microsecond
333        | DatePart::Nanosecond = part
334        {
335            Ok(Int32Array::new(
336                vec![0; self.len()].into(),
337                self.nulls().cloned(),
338            ))
339        } else {
340            let map_func = get_date_time_part_extract_fn(part);
341            Ok(self.unary_opt(|d| date32_to_datetime(d).map(map_func)))
342        }
343    }
344}
345
346impl ExtractDatePartExt for PrimitiveArray<Date64Type> {
347    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
348        let map_func = get_date_time_part_extract_fn(part);
349        Ok(self.unary_opt(|d| date64_to_datetime(d).map(map_func)))
350    }
351}
352
353impl ExtractDatePartExt for PrimitiveArray<TimestampSecondType> {
354    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
355        // TimestampSecond only encodes number of seconds, so these will always be 0
356        let array =
357            if let DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond = part {
358                Int32Array::new(vec![0; self.len()].into(), self.nulls().cloned())
359            } else if let Some(tz) = get_tz(self.data_type())? {
360                let map_func = get_date_time_part_extract_fn(part);
361                self.unary_opt(|d| {
362                    timestamp_s_to_datetime(d)
363                        .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
364                        .map(map_func)
365                })
366            } else {
367                let map_func = get_date_time_part_extract_fn(part);
368                self.unary_opt(|d| timestamp_s_to_datetime(d).map(map_func))
369            };
370        Ok(array)
371    }
372}
373
374impl ExtractDatePartExt for PrimitiveArray<TimestampMillisecondType> {
375    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
376        let array = if let Some(tz) = get_tz(self.data_type())? {
377            let map_func = get_date_time_part_extract_fn(part);
378            self.unary_opt(|d| {
379                timestamp_ms_to_datetime(d)
380                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
381                    .map(map_func)
382            })
383        } else {
384            let map_func = get_date_time_part_extract_fn(part);
385            self.unary_opt(|d| timestamp_ms_to_datetime(d).map(map_func))
386        };
387        Ok(array)
388    }
389}
390
391impl ExtractDatePartExt for PrimitiveArray<TimestampMicrosecondType> {
392    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
393        let array = if let Some(tz) = get_tz(self.data_type())? {
394            let map_func = get_date_time_part_extract_fn(part);
395            self.unary_opt(|d| {
396                timestamp_us_to_datetime(d)
397                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
398                    .map(map_func)
399            })
400        } else {
401            let map_func = get_date_time_part_extract_fn(part);
402            self.unary_opt(|d| timestamp_us_to_datetime(d).map(map_func))
403        };
404        Ok(array)
405    }
406}
407
408impl ExtractDatePartExt for PrimitiveArray<TimestampNanosecondType> {
409    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
410        let array = if let Some(tz) = get_tz(self.data_type())? {
411            let map_func = get_date_time_part_extract_fn(part);
412            self.unary_opt(|d| {
413                timestamp_ns_to_datetime(d)
414                    .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
415                    .map(map_func)
416            })
417        } else {
418            let map_func = get_date_time_part_extract_fn(part);
419            self.unary_opt(|d| timestamp_ns_to_datetime(d).map(map_func))
420        };
421        Ok(array)
422    }
423}
424
425impl ExtractDatePartExt for PrimitiveArray<IntervalYearMonthType> {
426    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
427        match part {
428            DatePart::Year => Ok(self.unary_opt(|d| Some(d / 12))),
429            DatePart::Month => Ok(self.unary_opt(|d| Some(d % 12))),
430
431            DatePart::Quarter
432            | DatePart::Week
433            | DatePart::WeekISO
434            | DatePart::YearISO
435            | DatePart::Day
436            | DatePart::DayOfWeekSunday0
437            | DatePart::DayOfWeekMonday0
438            | DatePart::DayOfYear
439            | DatePart::Hour
440            | DatePart::Minute
441            | DatePart::Second
442            | DatePart::Millisecond
443            | DatePart::Microsecond
444            | DatePart::Nanosecond => {
445                return_compute_error_with!(format!("{part} does not support"), self.data_type())
446            }
447        }
448    }
449}
450
451impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> {
452    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
453        match part {
454            DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))),
455            DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))),
456            DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))),
457            DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))),
458            DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))),
459            DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))),
460            DatePart::Microsecond => {
461                Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000)))
462            }
463            DatePart::Nanosecond => {
464                Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000)))
465            }
466
467            DatePart::Quarter
468            | DatePart::Year
469            | DatePart::YearISO
470            | DatePart::WeekISO
471            | DatePart::Month
472            | DatePart::DayOfWeekSunday0
473            | DatePart::DayOfWeekMonday0
474            | DatePart::DayOfYear => {
475                return_compute_error_with!(format!("{part} does not support"), self.data_type())
476            }
477        }
478    }
479}
480
481impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> {
482    fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
483        match part {
484            DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))),
485            DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months % 12))),
486            DatePart::Week => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days / 7))),
487            DatePart::Day => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days))),
488            DatePart::Hour => {
489                Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 60 * 1_000_000_000)).try_into().ok()))
490            }
491            DatePart::Minute => {
492                Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 1_000_000_000) % 60).try_into().ok()))
493            }
494            DatePart::Second => {
495                Ok(self.unary_opt(|d| ((d.nanoseconds / 1_000_000_000) % 60).try_into().ok()))
496            }
497            DatePart::Millisecond => Ok(self.unary_opt(|d| {
498                (d.nanoseconds % (60 * 1_000_000_000) / 1_000_000)
499                    .try_into()
500                    .ok()
501            })),
502            DatePart::Microsecond => Ok(self.unary_opt(|d| {
503                (d.nanoseconds % (60 * 1_000_000_000) / 1_000)
504                    .try_into()
505                    .ok()
506            })),
507            DatePart::Nanosecond => {
508                Ok(self.unary_opt(|d| (d.nanoseconds % (60 * 1_000_000_000)).try_into().ok()))
509            }
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#[cfg(test)]
679mod tests {
680    use super::*;
681
682    /// Used to integrate new [`date_part()`] method with deprecated shims such as
683    /// [`hour()`] and [`week()`].
684    fn date_part_primitive<T: ArrowTemporalType>(
685        array: &PrimitiveArray<T>,
686        part: DatePart,
687    ) -> Result<Int32Array, ArrowError> {
688        let array = date_part(array, part)?;
689        Ok(array.as_primitive::<Int32Type>().to_owned())
690    }
691
692    #[test]
693    fn test_temporal_array_date64_hour() {
694        let a: PrimitiveArray<Date64Type> =
695            vec![Some(1514764800000), None, Some(1550636625000)].into();
696
697        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
698        assert_eq!(0, b.value(0));
699        assert!(!b.is_valid(1));
700        assert_eq!(4, b.value(2));
701    }
702
703    #[test]
704    fn test_temporal_array_date32_hour() {
705        let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
706
707        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
708        assert_eq!(0, b.value(0));
709        assert!(!b.is_valid(1));
710        assert_eq!(0, b.value(2));
711    }
712
713    #[test]
714    fn test_temporal_array_time32_second_hour() {
715        let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
716
717        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
718        assert_eq!(10, b.value(0));
719        assert_eq!(23, b.value(1));
720    }
721
722    #[test]
723    fn test_temporal_array_time64_micro_hour() {
724        let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
725
726        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
727        assert_eq!(10, b.value(0));
728        assert_eq!(23, b.value(1));
729    }
730
731    #[test]
732    fn test_temporal_array_timestamp_micro_hour() {
733        let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
734
735        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
736        assert_eq!(10, b.value(0));
737        assert_eq!(23, b.value(1));
738    }
739
740    #[test]
741    fn test_temporal_array_date64_year() {
742        let a: PrimitiveArray<Date64Type> =
743            vec![Some(1514764800000), None, Some(1550636625000)].into();
744
745        let b = date_part_primitive(&a, DatePart::Year).unwrap();
746        assert_eq!(2018, b.value(0));
747        assert!(!b.is_valid(1));
748        assert_eq!(2019, b.value(2));
749    }
750
751    #[test]
752    fn test_temporal_array_date32_year() {
753        let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
754
755        let b = date_part_primitive(&a, DatePart::Year).unwrap();
756        assert_eq!(2011, b.value(0));
757        assert!(!b.is_valid(1));
758        assert_eq!(2012, b.value(2));
759    }
760
761    #[test]
762    fn test_temporal_array_date64_quarter() {
763        //1514764800000 -> 2018-01-01
764        //1566275025000 -> 2019-08-20
765        let a: PrimitiveArray<Date64Type> =
766            vec![Some(1514764800000), None, Some(1566275025000)].into();
767
768        let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
769        assert_eq!(1, b.value(0));
770        assert!(!b.is_valid(1));
771        assert_eq!(3, b.value(2));
772    }
773
774    #[test]
775    fn test_temporal_array_date32_quarter() {
776        let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
777
778        let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
779        assert_eq!(1, b.value(0));
780        assert!(!b.is_valid(1));
781        assert_eq!(4, b.value(2));
782    }
783
784    #[test]
785    fn test_temporal_array_timestamp_quarter_with_timezone() {
786        // 24 * 60 * 60 = 86400
787        let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
788        let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
789        assert_eq!(2, b.value(0));
790        let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
791        let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
792        assert_eq!(1, b.value(0));
793    }
794
795    #[test]
796    fn test_temporal_array_date64_month() {
797        //1514764800000 -> 2018-01-01
798        //1550636625000 -> 2019-02-20
799        let a: PrimitiveArray<Date64Type> =
800            vec![Some(1514764800000), None, Some(1550636625000)].into();
801
802        let b = date_part_primitive(&a, DatePart::Month).unwrap();
803        assert_eq!(1, b.value(0));
804        assert!(!b.is_valid(1));
805        assert_eq!(2, b.value(2));
806    }
807
808    #[test]
809    fn test_temporal_array_date32_month() {
810        let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
811
812        let b = date_part_primitive(&a, DatePart::Month).unwrap();
813        assert_eq!(1, b.value(0));
814        assert!(!b.is_valid(1));
815        assert_eq!(2, b.value(2));
816    }
817
818    #[test]
819    fn test_temporal_array_timestamp_month_with_timezone() {
820        // 24 * 60 * 60 = 86400
821        let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
822        let b = date_part_primitive(&a, DatePart::Month).unwrap();
823        assert_eq!(2, b.value(0));
824        let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
825        let b = date_part_primitive(&a, DatePart::Month).unwrap();
826        assert_eq!(1, b.value(0));
827    }
828
829    #[test]
830    fn test_temporal_array_timestamp_day_with_timezone() {
831        // 24 * 60 * 60 = 86400
832        let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
833        let b = date_part_primitive(&a, DatePart::Day).unwrap();
834        assert_eq!(2, b.value(0));
835        let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
836        let b = date_part_primitive(&a, DatePart::Day).unwrap();
837        assert_eq!(1, b.value(0));
838    }
839
840    #[test]
841    fn test_temporal_array_date64_weekday() {
842        //1514764800000 -> 2018-01-01 (Monday)
843        //1550636625000 -> 2019-02-20 (Wednesday)
844        let a: PrimitiveArray<Date64Type> =
845            vec![Some(1514764800000), None, Some(1550636625000)].into();
846
847        let b = date_part_primitive(&a, DatePart::DayOfWeekMonday0).unwrap();
848        assert_eq!(0, b.value(0));
849        assert!(!b.is_valid(1));
850        assert_eq!(2, b.value(2));
851    }
852
853    #[test]
854    fn test_temporal_array_date64_weekday0() {
855        //1483228800000 -> 2017-01-01 (Sunday)
856        //1514764800000 -> 2018-01-01 (Monday)
857        //1550636625000 -> 2019-02-20 (Wednesday)
858        let a: PrimitiveArray<Date64Type> = vec![
859            Some(1483228800000),
860            None,
861            Some(1514764800000),
862            Some(1550636625000),
863        ]
864        .into();
865
866        let b = date_part_primitive(&a, DatePart::DayOfWeekSunday0).unwrap();
867        assert_eq!(0, b.value(0));
868        assert!(!b.is_valid(1));
869        assert_eq!(1, b.value(2));
870        assert_eq!(3, b.value(3));
871    }
872
873    #[test]
874    fn test_temporal_array_date64_day() {
875        //1514764800000 -> 2018-01-01
876        //1550636625000 -> 2019-02-20
877        let a: PrimitiveArray<Date64Type> =
878            vec![Some(1514764800000), None, Some(1550636625000)].into();
879
880        let b = date_part_primitive(&a, DatePart::Day).unwrap();
881        assert_eq!(1, b.value(0));
882        assert!(!b.is_valid(1));
883        assert_eq!(20, b.value(2));
884    }
885
886    #[test]
887    fn test_temporal_array_date32_day() {
888        let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
889
890        let b = date_part_primitive(&a, DatePart::Day).unwrap();
891        assert_eq!(1, b.value(0));
892        assert!(!b.is_valid(1));
893        assert_eq!(1, b.value(2));
894    }
895
896    #[test]
897    fn test_temporal_array_date64_doy() {
898        //1483228800000 -> 2017-01-01 (Sunday)
899        //1514764800000 -> 2018-01-01
900        //1550636625000 -> 2019-02-20
901        let a: PrimitiveArray<Date64Type> = vec![
902            Some(1483228800000),
903            Some(1514764800000),
904            None,
905            Some(1550636625000),
906        ]
907        .into();
908
909        let b = date_part_primitive(&a, DatePart::DayOfYear).unwrap();
910        assert_eq!(1, b.value(0));
911        assert_eq!(1, b.value(1));
912        assert!(!b.is_valid(2));
913        assert_eq!(51, b.value(3));
914    }
915
916    #[test]
917    fn test_temporal_array_timestamp_micro_year() {
918        let a: TimestampMicrosecondArray =
919            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
920
921        let b = date_part_primitive(&a, DatePart::Year).unwrap();
922        assert_eq!(2021, b.value(0));
923        assert!(!b.is_valid(1));
924        assert_eq!(2024, b.value(2));
925    }
926
927    #[test]
928    fn test_temporal_array_date64_minute() {
929        let a: PrimitiveArray<Date64Type> =
930            vec![Some(1514764800000), None, Some(1550636625000)].into();
931
932        let b = date_part_primitive(&a, DatePart::Minute).unwrap();
933        assert_eq!(0, b.value(0));
934        assert!(!b.is_valid(1));
935        assert_eq!(23, b.value(2));
936    }
937
938    #[test]
939    fn test_temporal_array_timestamp_micro_minute() {
940        let a: TimestampMicrosecondArray =
941            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
942
943        let b = date_part_primitive(&a, DatePart::Minute).unwrap();
944        assert_eq!(57, b.value(0));
945        assert!(!b.is_valid(1));
946        assert_eq!(44, b.value(2));
947    }
948
949    #[test]
950    fn test_temporal_array_date32_week() {
951        let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
952
953        let b = date_part_primitive(&a, DatePart::Week).unwrap();
954        assert_eq!(1, b.value(0));
955        assert!(!b.is_valid(1));
956        assert_eq!(2, b.value(2));
957    }
958
959    #[test]
960    fn test_temporal_array_date64_week() {
961        // 1646116175000 -> 2022.03.01 , 1641171600000 -> 2022.01.03
962        // 1640998800000 -> 2022.01.01
963        let a: PrimitiveArray<Date64Type> = vec![
964            Some(1646116175000),
965            None,
966            Some(1641171600000),
967            Some(1640998800000),
968        ]
969        .into();
970
971        let b = date_part_primitive(&a, DatePart::Week).unwrap();
972        assert_eq!(9, b.value(0));
973        assert!(!b.is_valid(1));
974        assert_eq!(1, b.value(2));
975        assert_eq!(52, b.value(3));
976    }
977
978    #[test]
979    fn test_temporal_array_timestamp_micro_week() {
980        //1612025847000000 -> 2021.1.30
981        //1722015847000000 -> 2024.7.27
982        let a: TimestampMicrosecondArray =
983            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
984
985        let b = date_part_primitive(&a, DatePart::Week).unwrap();
986        assert_eq!(4, b.value(0));
987        assert!(!b.is_valid(1));
988        assert_eq!(30, b.value(2));
989    }
990
991    #[test]
992    fn test_temporal_array_date64_second() {
993        let a: PrimitiveArray<Date64Type> =
994            vec![Some(1514764800000), None, Some(1550636625000)].into();
995
996        let b = date_part_primitive(&a, DatePart::Second).unwrap();
997        assert_eq!(0, b.value(0));
998        assert!(!b.is_valid(1));
999        assert_eq!(45, b.value(2));
1000    }
1001
1002    #[test]
1003    fn test_temporal_array_timestamp_micro_second() {
1004        let a: TimestampMicrosecondArray =
1005            vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1006
1007        let b = date_part_primitive(&a, DatePart::Second).unwrap();
1008        assert_eq!(27, b.value(0));
1009        assert!(!b.is_valid(1));
1010        assert_eq!(7, b.value(2));
1011    }
1012
1013    #[test]
1014    fn test_temporal_array_timestamp_second_with_timezone() {
1015        let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1016        let b = date_part_primitive(&a, DatePart::Second).unwrap();
1017        assert_eq!(10, b.value(0));
1018        assert_eq!(20, b.value(1));
1019    }
1020
1021    #[test]
1022    fn test_temporal_array_timestamp_minute_with_timezone() {
1023        let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1024        let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1025        assert_eq!(50, b.value(0));
1026        assert_eq!(51, b.value(1));
1027    }
1028
1029    #[test]
1030    fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1031        let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1032        let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1033        assert_eq!(5, b.value(0));
1034    }
1035
1036    #[test]
1037    fn test_temporal_array_timestamp_hour_with_timezone() {
1038        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1039        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1040        assert_eq!(11, b.value(0));
1041    }
1042
1043    #[test]
1044    fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1045        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1046        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1047        assert_eq!(11, b.value(0));
1048    }
1049
1050    #[test]
1051    fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1052        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1053        let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1054        assert_eq!(11, b.value(0));
1055    }
1056
1057    #[test]
1058    fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1059        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1060        let err = date_part_primitive(&a, DatePart::Hour)
1061            .unwrap_err()
1062            .to_string();
1063        assert!(err.contains("Invalid timezone"), "{}", err);
1064    }
1065
1066    #[test]
1067    fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1068        let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1069        let err = date_part_primitive(&a, DatePart::Hour)
1070            .unwrap_err()
1071            .to_string();
1072        assert!(err.contains("Invalid timezone"), "{}", err);
1073    }
1074
1075    #[test]
1076    fn test_temporal_array_timestamp_week_without_timezone() {
1077        // 1970-01-01T00:00:00                     -> 1970-01-01T00:00:00 Thursday (week 1)
1078        // 1970-01-01T00:00:00 + 4 days            -> 1970-01-05T00:00:00 Monday   (week 2)
1079        // 1970-01-01T00:00:00 + 4 days - 1 second -> 1970-01-04T23:59:59 Sunday   (week 1)
1080        let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1081        let b = date_part_primitive(&a, DatePart::Week).unwrap();
1082        assert_eq!(1, b.value(0));
1083        assert_eq!(2, b.value(1));
1084        assert_eq!(1, b.value(2));
1085    }
1086
1087    #[test]
1088    fn test_temporal_array_timestamp_week_with_timezone() {
1089        // 1970-01-01T01:00:00+01:00                     -> 1970-01-01T01:00:00+01:00 Thursday (week 1)
1090        // 1970-01-01T01:00:00+01:00 + 4 days            -> 1970-01-05T01:00:00+01:00 Monday   (week 2)
1091        // 1970-01-01T01:00:00+01:00 + 4 days - 1 second -> 1970-01-05T00:59:59+01:00 Monday   (week 2)
1092        let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1093            .with_timezone("+01:00".to_string());
1094        let b = date_part_primitive(&a, DatePart::Week).unwrap();
1095        assert_eq!(1, b.value(0));
1096        assert_eq!(2, b.value(1));
1097        assert_eq!(2, b.value(2));
1098    }
1099
1100    #[test]
1101    fn test_hour_minute_second_dictionary_array() {
1102        let a = TimestampSecondArray::from(vec![
1103            60 * 60 * 10 + 61,
1104            60 * 60 * 20 + 122,
1105            60 * 60 * 30 + 183,
1106        ])
1107        .with_timezone("+01:00".to_string());
1108
1109        let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1110        let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1111
1112        let b = date_part(&dict, DatePart::Hour).unwrap();
1113
1114        let expected_dict =
1115            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1116        let expected = Arc::new(expected_dict) as ArrayRef;
1117        assert_eq!(&expected, &b);
1118
1119        let b = date_part(&dict, DatePart::Minute).unwrap();
1120
1121        let b_old = date_part(&dict, DatePart::Minute).unwrap();
1122
1123        let expected_dict =
1124            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1125        let expected = Arc::new(expected_dict) as ArrayRef;
1126        assert_eq!(&expected, &b);
1127        assert_eq!(&expected, &b_old);
1128
1129        let b = date_part(&dict, DatePart::Second).unwrap();
1130
1131        let b_old = date_part(&dict, DatePart::Second).unwrap();
1132
1133        let expected_dict =
1134            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1135        let expected = Arc::new(expected_dict) as ArrayRef;
1136        assert_eq!(&expected, &b);
1137        assert_eq!(&expected, &b_old);
1138
1139        let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1140
1141        let expected_dict =
1142            DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1143        let expected = Arc::new(expected_dict) as ArrayRef;
1144        assert_eq!(&expected, &b);
1145    }
1146
1147    #[test]
1148    fn test_year_dictionary_array() {
1149        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1150
1151        let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1152        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1153
1154        let b = date_part(&dict, DatePart::Year).unwrap();
1155
1156        let expected_dict = DictionaryArray::new(
1157            keys,
1158            Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1159        );
1160        let expected = Arc::new(expected_dict) as ArrayRef;
1161        assert_eq!(&expected, &b);
1162    }
1163
1164    #[test]
1165    fn test_quarter_month_dictionary_array() {
1166        //1514764800000 -> 2018-01-01
1167        //1566275025000 -> 2019-08-20
1168        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1169
1170        let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1171        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1172
1173        let b = date_part(&dict, DatePart::Quarter).unwrap();
1174
1175        let expected =
1176            DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1177        assert_eq!(b.as_ref(), &expected);
1178
1179        let b = date_part(&dict, DatePart::Month).unwrap();
1180
1181        let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1182        assert_eq!(b.as_ref(), &expected);
1183    }
1184
1185    #[test]
1186    fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1187        //1514764800000 -> 2018-01-01 (Monday)
1188        //1550636625000 -> 2019-02-20 (Wednesday)
1189        let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1190
1191        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1192        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1193
1194        let b = date_part(&dict, DatePart::DayOfWeekMonday0).unwrap();
1195
1196        let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1197        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1198        assert_eq!(b.as_ref(), &expected);
1199
1200        let b = date_part(&dict, DatePart::DayOfWeekSunday0).unwrap();
1201
1202        let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), None]);
1203        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1204        assert_eq!(b.as_ref(), &expected);
1205
1206        let b = date_part(&dict, DatePart::Day).unwrap();
1207
1208        let a = Int32Array::from(vec![Some(1), Some(20), Some(20), Some(1), None]);
1209        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1210        assert_eq!(b.as_ref(), &expected);
1211
1212        let b = date_part(&dict, DatePart::DayOfYear).unwrap();
1213
1214        let a = Int32Array::from(vec![Some(1), Some(51), Some(51), Some(1), None]);
1215        let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1216        assert_eq!(b.as_ref(), &expected);
1217
1218        let b = date_part(&dict, DatePart::Week).unwrap();
1219
1220        let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1221        let expected = DictionaryArray::new(keys, Arc::new(a));
1222        assert_eq!(b.as_ref(), &expected);
1223    }
1224
1225    #[test]
1226    fn test_temporal_array_date64_nanosecond() {
1227        // new Date(1667328721453)
1228        // Tue Nov 01 2022 11:52:01 GMT-0700 (Pacific Daylight Time)
1229        //
1230        // new Date(1667328721453).getMilliseconds()
1231        // 453
1232
1233        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1234
1235        let b = date_part_primitive(&a, DatePart::Nanosecond).unwrap();
1236        assert!(!b.is_valid(0));
1237        assert_eq!(453_000_000, b.value(1));
1238
1239        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1240        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1241        let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1242
1243        let a = Int32Array::from(vec![None, Some(453_000_000)]);
1244        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1245        let expected = Arc::new(expected_dict) as ArrayRef;
1246        assert_eq!(&expected, &b);
1247    }
1248
1249    #[test]
1250    fn test_temporal_array_date64_microsecond() {
1251        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1252
1253        let b = date_part_primitive(&a, DatePart::Microsecond).unwrap();
1254        assert!(!b.is_valid(0));
1255        assert_eq!(453_000, b.value(1));
1256
1257        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1258        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1259        let b = date_part(&dict, DatePart::Microsecond).unwrap();
1260
1261        let a = Int32Array::from(vec![None, Some(453_000)]);
1262        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1263        let expected = Arc::new(expected_dict) as ArrayRef;
1264        assert_eq!(&expected, &b);
1265    }
1266
1267    #[test]
1268    fn test_temporal_array_date64_millisecond() {
1269        let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1270
1271        let b = date_part_primitive(&a, DatePart::Millisecond).unwrap();
1272        assert!(!b.is_valid(0));
1273        assert_eq!(453, b.value(1));
1274
1275        let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1276        let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1277        let b = date_part(&dict, DatePart::Millisecond).unwrap();
1278
1279        let a = Int32Array::from(vec![None, Some(453)]);
1280        let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1281        let expected = Arc::new(expected_dict) as ArrayRef;
1282        assert_eq!(&expected, &b);
1283    }
1284
1285    #[test]
1286    fn test_temporal_array_time64_nanoseconds() {
1287        // 23:32:50.123456789
1288        let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1289
1290        let actual = date_part(&input, DatePart::Hour).unwrap();
1291        let actual = actual.as_primitive::<Int32Type>();
1292        assert_eq!(23, actual.value(0));
1293
1294        let actual = date_part(&input, DatePart::Minute).unwrap();
1295        let actual = actual.as_primitive::<Int32Type>();
1296        assert_eq!(32, actual.value(0));
1297
1298        let actual = date_part(&input, DatePart::Second).unwrap();
1299        let actual = actual.as_primitive::<Int32Type>();
1300        assert_eq!(50, actual.value(0));
1301
1302        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1303        let actual = actual.as_primitive::<Int32Type>();
1304        assert_eq!(123, actual.value(0));
1305
1306        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1307        let actual = actual.as_primitive::<Int32Type>();
1308        assert_eq!(123_456, actual.value(0));
1309
1310        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1311        let actual = actual.as_primitive::<Int32Type>();
1312        assert_eq!(123_456_789, actual.value(0));
1313
1314        // invalid values should turn into null
1315        let input: Time64NanosecondArray = vec![
1316            Some(-1),
1317            Some(86_400_000_000_000),
1318            Some(86_401_000_000_000),
1319            None,
1320        ]
1321        .into();
1322        let actual = date_part(&input, DatePart::Hour).unwrap();
1323        let actual = actual.as_primitive::<Int32Type>();
1324        let expected: Int32Array = vec![None, None, None, None].into();
1325        assert_eq!(&expected, actual);
1326    }
1327
1328    #[test]
1329    fn test_temporal_array_time64_microseconds() {
1330        // 23:32:50.123456
1331        let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1332
1333        let actual = date_part(&input, DatePart::Hour).unwrap();
1334        let actual = actual.as_primitive::<Int32Type>();
1335        assert_eq!(23, actual.value(0));
1336
1337        let actual = date_part(&input, DatePart::Minute).unwrap();
1338        let actual = actual.as_primitive::<Int32Type>();
1339        assert_eq!(32, actual.value(0));
1340
1341        let actual = date_part(&input, DatePart::Second).unwrap();
1342        let actual = actual.as_primitive::<Int32Type>();
1343        assert_eq!(50, actual.value(0));
1344
1345        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1346        let actual = actual.as_primitive::<Int32Type>();
1347        assert_eq!(123, actual.value(0));
1348
1349        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1350        let actual = actual.as_primitive::<Int32Type>();
1351        assert_eq!(123_456, actual.value(0));
1352
1353        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1354        let actual = actual.as_primitive::<Int32Type>();
1355        assert_eq!(123_456_000, actual.value(0));
1356
1357        // invalid values should turn into null
1358        let input: Time64MicrosecondArray =
1359            vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1360        let actual = date_part(&input, DatePart::Hour).unwrap();
1361        let actual = actual.as_primitive::<Int32Type>();
1362        let expected: Int32Array = vec![None, None, None, None].into();
1363        assert_eq!(&expected, actual);
1364    }
1365
1366    #[test]
1367    fn test_temporal_array_time32_milliseconds() {
1368        // 23:32:50.123
1369        let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1370
1371        let actual = date_part(&input, DatePart::Hour).unwrap();
1372        let actual = actual.as_primitive::<Int32Type>();
1373        assert_eq!(23, actual.value(0));
1374
1375        let actual = date_part(&input, DatePart::Minute).unwrap();
1376        let actual = actual.as_primitive::<Int32Type>();
1377        assert_eq!(32, actual.value(0));
1378
1379        let actual = date_part(&input, DatePart::Second).unwrap();
1380        let actual = actual.as_primitive::<Int32Type>();
1381        assert_eq!(50, actual.value(0));
1382
1383        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1384        let actual = actual.as_primitive::<Int32Type>();
1385        assert_eq!(123, actual.value(0));
1386
1387        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1388        let actual = actual.as_primitive::<Int32Type>();
1389        assert_eq!(123_000, actual.value(0));
1390
1391        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1392        let actual = actual.as_primitive::<Int32Type>();
1393        assert_eq!(123_000_000, actual.value(0));
1394
1395        // invalid values should turn into null
1396        let input: Time32MillisecondArray =
1397            vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1398        let actual = date_part(&input, DatePart::Hour).unwrap();
1399        let actual = actual.as_primitive::<Int32Type>();
1400        let expected: Int32Array = vec![None, None, None, None].into();
1401        assert_eq!(&expected, actual);
1402    }
1403
1404    #[test]
1405    fn test_temporal_array_time32_seconds() {
1406        // 23:32:50
1407        let input: Time32SecondArray = vec![84_770].into();
1408
1409        let actual = date_part(&input, DatePart::Hour).unwrap();
1410        let actual = actual.as_primitive::<Int32Type>();
1411        assert_eq!(23, actual.value(0));
1412
1413        let actual = date_part(&input, DatePart::Minute).unwrap();
1414        let actual = actual.as_primitive::<Int32Type>();
1415        assert_eq!(32, actual.value(0));
1416
1417        let actual = date_part(&input, DatePart::Second).unwrap();
1418        let actual = actual.as_primitive::<Int32Type>();
1419        assert_eq!(50, actual.value(0));
1420
1421        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1422        let actual = actual.as_primitive::<Int32Type>();
1423        assert_eq!(0, actual.value(0));
1424
1425        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1426        let actual = actual.as_primitive::<Int32Type>();
1427        assert_eq!(0, actual.value(0));
1428
1429        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1430        let actual = actual.as_primitive::<Int32Type>();
1431        assert_eq!(0, actual.value(0));
1432
1433        // invalid values should turn into null
1434        let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1435        let actual = date_part(&input, DatePart::Hour).unwrap();
1436        let actual = actual.as_primitive::<Int32Type>();
1437        let expected: Int32Array = vec![None, None, None, None].into();
1438        assert_eq!(&expected, actual);
1439    }
1440
1441    #[test]
1442    fn test_temporal_array_time_invalid_parts() {
1443        fn ensure_returns_error(array: &dyn Array) {
1444            let invalid_parts = [
1445                DatePart::Quarter,
1446                DatePart::Year,
1447                DatePart::Month,
1448                DatePart::Week,
1449                DatePart::Day,
1450                DatePart::DayOfWeekSunday0,
1451                DatePart::DayOfWeekMonday0,
1452                DatePart::DayOfYear,
1453            ];
1454
1455            for part in invalid_parts {
1456                let err = date_part(array, part).unwrap_err();
1457                let expected = format!(
1458                    "Compute error: {part} does not support: {}",
1459                    array.data_type()
1460                );
1461                assert_eq!(expected, err.to_string());
1462            }
1463        }
1464
1465        ensure_returns_error(&Time32SecondArray::from(vec![0]));
1466        ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1467        ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1468        ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1469    }
1470
1471    #[test]
1472    fn test_interval_year_month_array() {
1473        let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1474
1475        let actual = date_part(&input, DatePart::Year).unwrap();
1476        let actual = actual.as_primitive::<Int32Type>();
1477        assert_eq!(0, actual.value(0));
1478        assert_eq!(0, actual.value(1));
1479        assert_eq!(2, actual.value(2));
1480
1481        let actual = date_part(&input, DatePart::Month).unwrap();
1482        let actual = actual.as_primitive::<Int32Type>();
1483        assert_eq!(0, actual.value(0));
1484        assert_eq!(5, actual.value(1));
1485        assert_eq!(0, actual.value(2));
1486
1487        assert!(date_part(&input, DatePart::Day).is_err());
1488        assert!(date_part(&input, DatePart::Week).is_err());
1489    }
1490
1491    // IntervalDayTimeType week, day, hour, minute, second, milli, u, nano;
1492    // invalid month, year; ignores the other part
1493    #[test]
1494    fn test_interval_day_time_array() {
1495        let input: IntervalDayTimeArray = vec![
1496            IntervalDayTime::ZERO,
1497            IntervalDayTime::new(10, 42),   // 10d, 42ms
1498            IntervalDayTime::new(10, 1042), // 10d, 1s, 42ms
1499            IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1), // 10d, 24h, 1ms
1500            IntervalDayTime::new(
1501                6,
1502                (MILLISECONDS * 60 * 60 * 4 + MILLISECONDS * 60 * 22 + MILLISECONDS * 11 + 3)
1503                    as i32,
1504            ), // 6d, 4h, 22m, 11s, 3ms
1505        ]
1506        .into();
1507
1508        // Time doesn't affect days.
1509        let actual = date_part(&input, DatePart::Day).unwrap();
1510        let actual = actual.as_primitive::<Int32Type>();
1511        assert_eq!(0, actual.value(0));
1512        assert_eq!(10, actual.value(1));
1513        assert_eq!(10, actual.value(2));
1514        assert_eq!(10, actual.value(3));
1515        assert_eq!(6, actual.value(4));
1516
1517        let actual = date_part(&input, DatePart::Week).unwrap();
1518        let actual = actual.as_primitive::<Int32Type>();
1519        assert_eq!(0, actual.value(0));
1520        assert_eq!(1, actual.value(1));
1521        assert_eq!(1, actual.value(2));
1522        assert_eq!(1, actual.value(3));
1523        assert_eq!(0, actual.value(4));
1524
1525        // Days doesn't affect time.
1526        let actual = date_part(&input, DatePart::Hour).unwrap();
1527        let actual = actual.as_primitive::<Int32Type>();
1528        assert_eq!(0, actual.value(0));
1529        assert_eq!(0, actual.value(1));
1530        assert_eq!(0, actual.value(2));
1531        assert_eq!(24, actual.value(3));
1532        assert_eq!(4, actual.value(4));
1533
1534        let actual = date_part(&input, DatePart::Minute).unwrap();
1535        let actual = actual.as_primitive::<Int32Type>();
1536        assert_eq!(0, actual.value(0));
1537        assert_eq!(0, actual.value(1));
1538        assert_eq!(0, actual.value(2));
1539        assert_eq!(0, actual.value(3));
1540        assert_eq!(22, actual.value(4));
1541
1542        let actual = date_part(&input, DatePart::Second).unwrap();
1543        let actual = actual.as_primitive::<Int32Type>();
1544        assert_eq!(0, actual.value(0));
1545        assert_eq!(0, actual.value(1));
1546        assert_eq!(1, actual.value(2));
1547        assert_eq!(0, actual.value(3));
1548        assert_eq!(11, actual.value(4));
1549
1550        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1551        let actual = actual.as_primitive::<Int32Type>();
1552        assert_eq!(0, actual.value(0));
1553        assert_eq!(42, actual.value(1));
1554        assert_eq!(1042, actual.value(2));
1555        assert_eq!(1, actual.value(3));
1556        assert_eq!(11003, actual.value(4));
1557
1558        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1559        let actual = actual.as_primitive::<Int32Type>();
1560        assert_eq!(0, actual.value(0));
1561        assert_eq!(42_000, actual.value(1));
1562        assert_eq!(1_042_000, actual.value(2));
1563        assert_eq!(1_000, actual.value(3));
1564        assert_eq!(11_003_000, actual.value(4));
1565
1566        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1567        let actual = actual.as_primitive::<Int32Type>();
1568        assert_eq!(0, actual.value(0));
1569        assert_eq!(42_000_000, actual.value(1));
1570        assert_eq!(1_042_000_000, actual.value(2));
1571        assert_eq!(1_000_000, actual.value(3));
1572        // Overflow returns zero.
1573        assert_eq!(0, actual.value(4));
1574
1575        // Month and year are not valid (since days in month varies).
1576        assert!(date_part(&input, DatePart::Month).is_err());
1577        assert!(date_part(&input, DatePart::Year).is_err());
1578    }
1579
1580    // IntervalMonthDayNanoType year -> nano;
1581    // days don't affect months, time doesn't affect days, time doesn't affect months (and vice versa)
1582    #[test]
1583    fn test_interval_month_day_nano_array() {
1584        let input: IntervalMonthDayNanoArray = vec![
1585            IntervalMonthDayNano::ZERO,
1586            IntervalMonthDayNano::new(5, 10, 42), // 5m, 1w, 3d, 42ns
1587            IntervalMonthDayNano::new(16, 35, NANOSECONDS_IN_DAY + 1), // 1y, 4m, 5w, 24h, 1ns
1588            IntervalMonthDayNano::new(
1589                0,
1590                0,
1591                NANOSECONDS * 60 * 60 * 4
1592                    + NANOSECONDS * 60 * 22
1593                    + NANOSECONDS * 11
1594                    + 1_000_000 * 33
1595                    + 1_000 * 44
1596                    + 5,
1597            ), // 4hr, 22m, 11s, 33ms, 44us, 5ns
1598        ]
1599        .into();
1600
1601        // Year and month follow from month, but are not affected by days or nanos.
1602        let actual = date_part(&input, DatePart::Year).unwrap();
1603        let actual = actual.as_primitive::<Int32Type>();
1604        assert_eq!(0, actual.value(0));
1605        assert_eq!(0, actual.value(1));
1606        assert_eq!(1, actual.value(2));
1607        assert_eq!(0, actual.value(3));
1608
1609        let actual = date_part(&input, DatePart::Month).unwrap();
1610        let actual = actual.as_primitive::<Int32Type>();
1611        assert_eq!(0, actual.value(0));
1612        assert_eq!(5, actual.value(1));
1613        assert_eq!(4, actual.value(2));
1614        assert_eq!(0, actual.value(3));
1615
1616        // Week and day follow from day, but are not affected by months or nanos.
1617        let actual = date_part(&input, DatePart::Week).unwrap();
1618        let actual = actual.as_primitive::<Int32Type>();
1619        assert_eq!(0, actual.value(0));
1620        assert_eq!(1, actual.value(1));
1621        assert_eq!(5, actual.value(2));
1622        assert_eq!(0, actual.value(3));
1623
1624        let actual = date_part(&input, DatePart::Day).unwrap();
1625        let actual = actual.as_primitive::<Int32Type>();
1626        assert_eq!(0, actual.value(0));
1627        assert_eq!(10, actual.value(1));
1628        assert_eq!(35, actual.value(2));
1629        assert_eq!(0, actual.value(3));
1630
1631        // Times follow from nanos, but are not affected by months or days.
1632        let actual = date_part(&input, DatePart::Hour).unwrap();
1633        let actual = actual.as_primitive::<Int32Type>();
1634        assert_eq!(0, actual.value(0));
1635        assert_eq!(0, actual.value(1));
1636        assert_eq!(24, actual.value(2));
1637        assert_eq!(4, actual.value(3));
1638
1639        let actual = date_part(&input, DatePart::Minute).unwrap();
1640        let actual = actual.as_primitive::<Int32Type>();
1641        assert_eq!(0, actual.value(0));
1642        assert_eq!(0, actual.value(1));
1643        assert_eq!(0, actual.value(2));
1644        assert_eq!(22, actual.value(3));
1645
1646        let actual = date_part(&input, DatePart::Second).unwrap();
1647        let actual = actual.as_primitive::<Int32Type>();
1648        assert_eq!(0, actual.value(0));
1649        assert_eq!(0, actual.value(1));
1650        assert_eq!(0, actual.value(2));
1651        assert_eq!(11, actual.value(3));
1652
1653        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1654        let actual = actual.as_primitive::<Int32Type>();
1655        assert_eq!(0, actual.value(0));
1656        assert_eq!(0, actual.value(1));
1657        assert_eq!(0, actual.value(2));
1658        assert_eq!(11_033, actual.value(3));
1659
1660        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1661        let actual = actual.as_primitive::<Int32Type>();
1662        assert_eq!(0, actual.value(0));
1663        assert_eq!(0, actual.value(1));
1664        assert_eq!(0, actual.value(2));
1665        assert_eq!(11_033_044, actual.value(3));
1666
1667        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1668        let actual = actual.as_primitive::<Int32Type>();
1669        assert_eq!(0, actual.value(0));
1670        assert_eq!(42, actual.value(1));
1671        assert_eq!(1, actual.value(2));
1672        // Overflow returns zero.
1673        assert_eq!(0, actual.value(3));
1674    }
1675
1676    #[test]
1677    fn test_interval_array_invalid_parts() {
1678        fn ensure_returns_error(array: &dyn Array) {
1679            let invalid_parts = [
1680                DatePart::Quarter,
1681                DatePart::DayOfWeekSunday0,
1682                DatePart::DayOfWeekMonday0,
1683                DatePart::DayOfYear,
1684            ];
1685
1686            for part in invalid_parts {
1687                let err = date_part(array, part).unwrap_err();
1688                let expected = format!(
1689                    "Compute error: {part} does not support: {}",
1690                    array.data_type()
1691                );
1692                assert_eq!(expected, err.to_string());
1693            }
1694        }
1695
1696        ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
1697        ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
1698        ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
1699            IntervalMonthDayNano::ZERO,
1700        ]));
1701    }
1702
1703    #[test]
1704    fn test_duration_second() {
1705        let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1706
1707        let actual = date_part(&input, DatePart::Second).unwrap();
1708        let actual = actual.as_primitive::<Int32Type>();
1709        assert_eq!(0, actual.value(0));
1710        assert_eq!(42, actual.value(1));
1711        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1712
1713        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1714        let actual = actual.as_primitive::<Int32Type>();
1715        assert_eq!(0, actual.value(0));
1716        assert_eq!(42_000, actual.value(1));
1717        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1718
1719        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1720        let actual = actual.as_primitive::<Int32Type>();
1721        assert_eq!(0, actual.value(0));
1722        assert_eq!(42_000_000, actual.value(1));
1723        assert_eq!(0, actual.value(2));
1724
1725        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1726        let actual = actual.as_primitive::<Int32Type>();
1727        assert_eq!(0, actual.value(0));
1728        assert_eq!(0, actual.value(1));
1729        assert_eq!(0, actual.value(2));
1730    }
1731
1732    #[test]
1733    fn test_duration_millisecond() {
1734        let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1735
1736        let actual = date_part(&input, DatePart::Second).unwrap();
1737        let actual = actual.as_primitive::<Int32Type>();
1738        assert_eq!(0, actual.value(0));
1739        assert_eq!(0, actual.value(1));
1740        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1741
1742        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1743        let actual = actual.as_primitive::<Int32Type>();
1744        assert_eq!(0, actual.value(0));
1745        assert_eq!(42, actual.value(1));
1746        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1747
1748        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1749        let actual = actual.as_primitive::<Int32Type>();
1750        assert_eq!(0, actual.value(0));
1751        assert_eq!(42_000, actual.value(1));
1752        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1753
1754        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1755        let actual = actual.as_primitive::<Int32Type>();
1756        assert_eq!(0, actual.value(0));
1757        assert_eq!(42_000_000, actual.value(1));
1758        assert_eq!(0, actual.value(2));
1759    }
1760
1761    #[test]
1762    fn test_duration_microsecond() {
1763        let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1764
1765        let actual = date_part(&input, DatePart::Second).unwrap();
1766        let actual = actual.as_primitive::<Int32Type>();
1767        assert_eq!(0, actual.value(0));
1768        assert_eq!(0, actual.value(1));
1769        assert_eq!(0, actual.value(2));
1770
1771        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1772        let actual = actual.as_primitive::<Int32Type>();
1773        assert_eq!(0, actual.value(0));
1774        assert_eq!(0, actual.value(1));
1775        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1776
1777        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1778        let actual = actual.as_primitive::<Int32Type>();
1779        assert_eq!(0, actual.value(0));
1780        assert_eq!(42, actual.value(1));
1781        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1782
1783        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1784        let actual = actual.as_primitive::<Int32Type>();
1785        assert_eq!(0, actual.value(0));
1786        assert_eq!(42_000, actual.value(1));
1787        assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1788    }
1789
1790    #[test]
1791    fn test_duration_nanosecond() {
1792        let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1793
1794        let actual = date_part(&input, DatePart::Second).unwrap();
1795        let actual = actual.as_primitive::<Int32Type>();
1796        assert_eq!(0, actual.value(0));
1797        assert_eq!(0, actual.value(1));
1798        assert_eq!(0, actual.value(2));
1799
1800        let actual = date_part(&input, DatePart::Millisecond).unwrap();
1801        let actual = actual.as_primitive::<Int32Type>();
1802        assert_eq!(0, actual.value(0));
1803        assert_eq!(0, actual.value(1));
1804        assert_eq!(0, actual.value(2));
1805
1806        let actual = date_part(&input, DatePart::Microsecond).unwrap();
1807        let actual = actual.as_primitive::<Int32Type>();
1808        assert_eq!(0, actual.value(0));
1809        assert_eq!(0, actual.value(1));
1810        assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1811
1812        let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1813        let actual = actual.as_primitive::<Int32Type>();
1814        assert_eq!(0, actual.value(0));
1815        assert_eq!(42, actual.value(1));
1816        assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1817    }
1818
1819    #[test]
1820    fn test_duration_invalid_parts() {
1821        fn ensure_returns_error(array: &dyn Array) {
1822            let invalid_parts = [
1823                DatePart::Year,
1824                DatePart::Quarter,
1825                DatePart::Month,
1826                DatePart::DayOfWeekSunday0,
1827                DatePart::DayOfWeekMonday0,
1828                DatePart::DayOfYear,
1829            ];
1830
1831            for part in invalid_parts {
1832                let err = date_part(array, part).unwrap_err();
1833                let expected = format!(
1834                    "Compute error: {part} does not support: {}",
1835                    array.data_type()
1836                );
1837                assert_eq!(expected, err.to_string());
1838            }
1839        }
1840
1841        ensure_returns_error(&DurationSecondArray::from(vec![0]));
1842        ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
1843        ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
1844        ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
1845    }
1846
1847    const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
1848    const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
1849    const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
1850    const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
1851    // In 2018 the ISO year and calendar year start on the same date— 2018-01-01 or 2018-W01-1
1852    #[test]
1853    fn test_temporal_array_date64_week_iso() {
1854        let a: PrimitiveArray<Date64Type> = vec![
1855            Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
1856            Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
1857        ]
1858        .into();
1859
1860        let b = date_part(&a, DatePart::WeekISO).unwrap();
1861        let actual = b.as_primitive::<Int32Type>();
1862        assert_eq!(1, actual.value(0));
1863        assert_eq!(8, actual.value(1));
1864    }
1865
1866    #[test]
1867    fn test_temporal_array_date64_year_iso() {
1868        let a: PrimitiveArray<Date64Type> = vec![
1869            Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
1870            Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
1871        ]
1872        .into();
1873
1874        let b = date_part(&a, DatePart::YearISO).unwrap();
1875        let actual = b.as_primitive::<Int32Type>();
1876        assert_eq!(2018, actual.value(0));
1877        assert_eq!(2019, actual.value(1));
1878    }
1879
1880    #[test]
1881    fn test_temporal_array_timestamp_week_iso() {
1882        let a = TimestampSecondArray::from(vec![
1883            TIMESTAMP_SECOND_1970_01_01, // 0 and is Thursday
1884            SECONDS_IN_DAY * 4,          //  Monday of week 2
1885            SECONDS_IN_DAY * 4 - 1,      // Sunday of week 1
1886        ]);
1887        let b = date_part(&a, DatePart::WeekISO).unwrap();
1888        let actual = b.as_primitive::<Int32Type>();
1889        assert_eq!(1, actual.value(0));
1890        assert_eq!(2, actual.value(1));
1891        assert_eq!(1, actual.value(2));
1892    }
1893
1894    #[test]
1895    fn test_temporal_array_timestamp_year_iso() {
1896        let a = TimestampSecondArray::from(vec![
1897            TIMESTAMP_SECOND_1970_01_01,
1898            SECONDS_IN_DAY * 4,
1899            SECONDS_IN_DAY * 4 - 1,
1900        ]);
1901        let b = date_part(&a, DatePart::YearISO).unwrap();
1902        let actual = b.as_primitive::<Int32Type>();
1903        assert_eq!(1970, actual.value(0));
1904        assert_eq!(1970, actual.value(1));
1905        assert_eq!(1970, actual.value(2));
1906    }
1907
1908    const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
1909    const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
1910    // January 1st 2016 is a Friday, so 2015 week 53 runs from
1911    // 2015-12-28 to 2016-01-03 inclusive, and
1912    // 2016 week 1 runs from 2016-01-04 to 2016-01-10 inclusive.
1913    #[test]
1914    fn test_temporal_array_date64_week_iso_edge_cases() {
1915        let a: PrimitiveArray<Date64Type> = vec![
1916            Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
1917            Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
1918            Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
1919        ]
1920        .into();
1921
1922        let b = date_part(&a, DatePart::WeekISO).unwrap();
1923        let actual = b.as_primitive::<Int32Type>();
1924        assert_eq!(53, actual.value(0));
1925        assert_eq!(53, actual.value(1));
1926        assert_eq!(1, actual.value(2));
1927    }
1928
1929    #[test]
1930    fn test_temporal_array_date64_year_iso_edge_cases() {
1931        let a: PrimitiveArray<Date64Type> = vec![
1932            Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
1933            Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
1934            Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
1935        ]
1936        .into();
1937
1938        let b = date_part(&a, DatePart::YearISO).unwrap();
1939        let actual = b.as_primitive::<Int32Type>();
1940        assert_eq!(2015, actual.value(0));
1941        assert_eq!(2015, actual.value(1));
1942        assert_eq!(2016, actual.value(2));
1943    }
1944
1945    #[test]
1946    fn test_temporal_array_timestamp_week_iso_edge_cases() {
1947        let a = TimestampSecondArray::from(vec![
1948            TIMESTAMP_SECOND_2015_12_28,
1949            TIMESTAMP_SECOND_2016_01_03,
1950            TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
1951        ]);
1952        let b = date_part(&a, DatePart::WeekISO).unwrap();
1953        let actual = b.as_primitive::<Int32Type>();
1954        assert_eq!(53, actual.value(0));
1955        assert_eq!(53, actual.value(1));
1956        assert_eq!(1, actual.value(2));
1957    }
1958
1959    #[test]
1960    fn test_temporal_array_timestamp_year_iso_edge_cases() {
1961        let a = TimestampSecondArray::from(vec![
1962            TIMESTAMP_SECOND_2015_12_28,
1963            TIMESTAMP_SECOND_2016_01_03,
1964            TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
1965        ]);
1966        let b = date_part(&a, DatePart::YearISO).unwrap();
1967        let actual = b.as_primitive::<Int32Type>();
1968        assert_eq!(2015, actual.value(0));
1969        assert_eq!(2015, actual.value(1));
1970        assert_eq!(2016, actual.value(2));
1971    }
1972}