arrow_arith/
temporal.rs

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