Coverage Report

Created: 2025-08-26 07:03

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