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