arrow_arith/
temporal.rs

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