1use std::str::FromStr;
21use std::sync::Arc;
22
23use arrow_array::cast::AsArray;
24use cast::as_primitive_array;
25use chrono::{Datelike, TimeZone, Timelike, Utc};
26
27use arrow_array::temporal_conversions::{
28 MICROSECONDS, MICROSECONDS_IN_DAY, MILLISECONDS, MILLISECONDS_IN_DAY, NANOSECONDS,
29 NANOSECONDS_IN_DAY, SECONDS_IN_DAY, date32_to_datetime, date64_to_datetime,
30 timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_s_to_datetime,
31 timestamp_us_to_datetime,
32};
33use arrow_array::timezone::Tz;
34use arrow_array::types::*;
35use arrow_array::*;
36use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45#[non_exhaustive]
46pub enum DatePart {
47 Quarter,
49 Year,
51 YearISO,
53 Month,
55 Week,
57 WeekISO,
59 Day,
61 DayOfWeekSunday0,
63 DayOfWeekMonday0,
65 DayOfWeekSunday1,
67 DayOfWeekMonday1,
69 DayOfYear,
71 Hour,
73 Minute,
75 Second,
77 Millisecond,
79 Microsecond,
81 Nanosecond,
83}
84
85impl std::fmt::Display for DatePart {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 write!(f, "{self:?}")
88 }
89}
90
91impl FromStr for DatePart {
107 type Err = ArrowError;
108
109 fn from_str(s: &str) -> Result<Self, ArrowError> {
110 Ok(match s.to_lowercase().as_str() {
111 "y" | "yr" | "yrs" | "year" | "years" => Self::Year,
112 "isoyear" => Self::YearISO,
113 "qtr" | "quarter" | "quarters" => Self::Quarter,
114 "mon" | "mons" | "month" | "months" => Self::Month,
115 "w" | "week" | "weeks" => Self::Week,
116 "isoweek" => Self::WeekISO,
117 "d" | "day" | "days" => Self::Day,
118 "dow" | "dayofweek" => Self::DayOfWeekSunday0,
119 "dow1" | "dayofweek1" => Self::DayOfWeekSunday1,
120 "isodow0" => Self::DayOfWeekMonday0,
121 "isodow" => Self::DayOfWeekMonday1,
122 "doy" | "dayofyear" => Self::DayOfYear,
123 "h" | "hr" | "hrs" | "hour" | "hours" => Self::Hour,
124 "m" | "min" | "mins" | "minute" | "minutes" => Self::Minute,
125 "s" | "sec" | "secs" | "second" | "seconds" => Self::Second,
126 "ms" | "msec" | "msecs" | "msecond" | "mseconds" | "millisecond" | "milliseconds" => {
127 Self::Millisecond
128 }
129 "us" | "usec" | "usecs" | "usecond" | "useconds" | "microsecond" | "microseconds" => {
130 Self::Microsecond
131 }
132 "nanosecond" | "nanoseconds" => Self::Nanosecond,
133 _ => {
134 return Err(ArrowError::InvalidArgumentError(format!(
135 "Unknown date part: {s}"
136 )));
137 }
138 })
139 }
140}
141
142fn get_date_time_part_extract_fn<T>(part: DatePart) -> fn(T) -> i32
148where
149 T: ChronoDateExt + Datelike + Timelike,
150{
151 match part {
152 DatePart::Year => |d| d.year(),
153 DatePart::Quarter => |d| Datelike::quarter(&d) as i32,
156 DatePart::YearISO => |d| d.iso_week().year(),
157 DatePart::Month => |d| d.month() as i32,
158 DatePart::Week | DatePart::WeekISO => |d| d.iso_week().week() as i32,
159 DatePart::Day => |d| d.day() as i32,
160 DatePart::DayOfWeekSunday0 => |d| d.num_days_from_sunday(),
161 DatePart::DayOfWeekMonday0 => |d| d.num_days_from_monday(),
162 DatePart::DayOfWeekSunday1 => |d| d.num_days_from_sunday() + 1,
163 DatePart::DayOfWeekMonday1 => |d| d.num_days_from_monday() + 1,
164 DatePart::DayOfYear => |d| d.ordinal() as i32,
165 DatePart::Hour => |d| d.hour() as i32,
166 DatePart::Minute => |d| d.minute() as i32,
167 DatePart::Second => |d| d.second() as i32,
168 DatePart::Millisecond => |d| (d.nanosecond() / 1_000_000) as i32,
169 DatePart::Microsecond => |d| (d.nanosecond() / 1_000) as i32,
170 DatePart::Nanosecond => |d| d.nanosecond() as i32,
171 }
172}
173
174pub fn date_part(array: &dyn Array, part: DatePart) -> Result<ArrayRef, ArrowError> {
212 downcast_temporal_array!(
213 array => {
214 let array = array.date_part(part)?;
215 let array = Arc::new(array) as ArrayRef;
216 Ok(array)
217 }
218 DataType::Interval(IntervalUnit::YearMonth) => {
219 let array = as_primitive_array::<IntervalYearMonthType>(array).date_part(part)?;
220 let array = Arc::new(array) as ArrayRef;
221 Ok(array)
222 }
223 DataType::Interval(IntervalUnit::DayTime) => {
224 let array = as_primitive_array::<IntervalDayTimeType>(array).date_part(part)?;
225 let array = Arc::new(array) as ArrayRef;
226 Ok(array)
227 }
228 DataType::Interval(IntervalUnit::MonthDayNano) => {
229 let array = as_primitive_array::<IntervalMonthDayNanoType>(array).date_part(part)?;
230 let array = Arc::new(array) as ArrayRef;
231 Ok(array)
232 }
233 DataType::Duration(TimeUnit::Second) => {
234 let array = as_primitive_array::<DurationSecondType>(array).date_part(part)?;
235 let array = Arc::new(array) as ArrayRef;
236 Ok(array)
237 }
238 DataType::Duration(TimeUnit::Millisecond) => {
239 let array = as_primitive_array::<DurationMillisecondType>(array).date_part(part)?;
240 let array = Arc::new(array) as ArrayRef;
241 Ok(array)
242 }
243 DataType::Duration(TimeUnit::Microsecond) => {
244 let array = as_primitive_array::<DurationMicrosecondType>(array).date_part(part)?;
245 let array = Arc::new(array) as ArrayRef;
246 Ok(array)
247 }
248 DataType::Duration(TimeUnit::Nanosecond) => {
249 let array = as_primitive_array::<DurationNanosecondType>(array).date_part(part)?;
250 let array = Arc::new(array) as ArrayRef;
251 Ok(array)
252 }
253 DataType::Dictionary(_, _) => {
254 let array = array.as_any_dictionary();
255 let values = date_part(array.values(), part)?;
256 let new_array = array.with_values(values);
257 Ok(new_array)
258 }
259 DataType::RunEndEncoded(_, _) => {
260 let array = array.as_any_ree();
261 let values = date_part(array.values(), part)?;
262 let new_array = array.with_values(values);
263 Ok(new_array)
264 }
265 t => return_compute_error_with!(format!("{part} does not support"), t),
266 )
267}
268
269fn get_tz(dt: &DataType) -> Result<Option<Tz>, ArrowError> {
272 match dt {
273 DataType::Timestamp(_, Some(tz)) => Ok(Some(tz.parse::<Tz>()?)),
274 DataType::Timestamp(_, None) => Ok(None),
275 _ => Err(ArrowError::CastError(format!("Not a timestamp type: {dt}"))),
276 }
277}
278
279trait ExtractDatePartExt {
281 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError>;
282}
283
284impl ExtractDatePartExt for PrimitiveArray<Time32SecondType> {
285 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
286 #[inline]
287 fn range_check(s: i32) -> bool {
288 (0..SECONDS_IN_DAY as i32).contains(&s)
289 }
290 match part {
291 DatePart::Hour => Ok(self.unary_opt(|s| range_check(s).then_some(s / 3_600))),
292 DatePart::Minute => Ok(self.unary_opt(|s| range_check(s).then_some((s / 60) % 60))),
293 DatePart::Second => Ok(self.unary_opt(|s| range_check(s).then_some(s % 60))),
294 DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond => {
296 Ok(self.unary_opt(|s| range_check(s).then_some(0)))
297 }
298 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
299 }
300 }
301}
302
303impl ExtractDatePartExt for PrimitiveArray<Time32MillisecondType> {
304 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
305 #[inline]
306 fn range_check(ms: i32) -> bool {
307 (0..MILLISECONDS_IN_DAY as i32).contains(&ms)
308 }
309 let milliseconds = MILLISECONDS as i32;
310 match part {
311 DatePart::Hour => {
312 Ok(self.unary_opt(|ms| range_check(ms).then_some(ms / 3_600 / milliseconds)))
313 }
314 DatePart::Minute => {
315 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / 60 / milliseconds) % 60)))
316 }
317 DatePart::Second => {
318 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / milliseconds) % 60)))
319 }
320 DatePart::Millisecond => {
321 Ok(self.unary_opt(|ms| range_check(ms).then_some(ms % milliseconds)))
322 }
323 DatePart::Microsecond => {
324 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000)))
325 }
326 DatePart::Nanosecond => {
327 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000_000)))
328 }
329 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
330 }
331 }
332}
333
334impl ExtractDatePartExt for PrimitiveArray<Time64MicrosecondType> {
335 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
336 #[inline]
337 fn range_check(us: i64) -> bool {
338 (0..MICROSECONDS_IN_DAY).contains(&us)
339 }
340 match part {
341 DatePart::Hour => {
342 Ok(self
343 .unary_opt(|us| range_check(us).then_some((us / 3_600 / MICROSECONDS) as i32)))
344 }
345 DatePart::Minute => Ok(self
346 .unary_opt(|us| range_check(us).then_some(((us / 60 / MICROSECONDS) % 60) as i32))),
347 DatePart::Second => {
348 Ok(self
349 .unary_opt(|us| range_check(us).then_some(((us / MICROSECONDS) % 60) as i32)))
350 }
351 DatePart::Millisecond => Ok(self
352 .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) / 1_000) as i32))),
353 DatePart::Microsecond => {
354 Ok(self.unary_opt(|us| range_check(us).then_some((us % MICROSECONDS) as i32)))
355 }
356 DatePart::Nanosecond => Ok(self
357 .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) * 1_000) as i32))),
358 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
359 }
360 }
361}
362
363impl ExtractDatePartExt for PrimitiveArray<Time64NanosecondType> {
364 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
365 #[inline]
366 fn range_check(ns: i64) -> bool {
367 (0..NANOSECONDS_IN_DAY).contains(&ns)
368 }
369 match part {
370 DatePart::Hour => {
371 Ok(self
372 .unary_opt(|ns| range_check(ns).then_some((ns / 3_600 / NANOSECONDS) as i32)))
373 }
374 DatePart::Minute => Ok(self
375 .unary_opt(|ns| range_check(ns).then_some(((ns / 60 / NANOSECONDS) % 60) as i32))),
376 DatePart::Second => Ok(
377 self.unary_opt(|ns| range_check(ns).then_some(((ns / NANOSECONDS) % 60) as i32))
378 ),
379 DatePart::Millisecond => Ok(self.unary_opt(|ns| {
380 range_check(ns).then_some(((ns % NANOSECONDS) / 1_000_000) as i32)
381 })),
382 DatePart::Microsecond => {
383 Ok(self
384 .unary_opt(|ns| range_check(ns).then_some(((ns % NANOSECONDS) / 1_000) as i32)))
385 }
386 DatePart::Nanosecond => {
387 Ok(self.unary_opt(|ns| range_check(ns).then_some((ns % NANOSECONDS) as i32)))
388 }
389 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
390 }
391 }
392}
393
394impl ExtractDatePartExt for PrimitiveArray<Date32Type> {
395 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
396 if let DatePart::Hour
398 | DatePart::Minute
399 | DatePart::Second
400 | DatePart::Millisecond
401 | DatePart::Microsecond
402 | DatePart::Nanosecond = part
403 {
404 Ok(Int32Array::new(
405 vec![0; self.len()].into(),
406 self.nulls().cloned(),
407 ))
408 } else {
409 let map_func = get_date_time_part_extract_fn(part);
410 Ok(self.unary_opt(|d| date32_to_datetime(d).map(map_func)))
411 }
412 }
413}
414
415impl ExtractDatePartExt for PrimitiveArray<Date64Type> {
416 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
417 let map_func = get_date_time_part_extract_fn(part);
418 Ok(self.unary_opt(|d| date64_to_datetime(d).map(map_func)))
419 }
420}
421
422const fn units_per_second<T: ArrowTimestampType>() -> i64 {
424 match T::UNIT {
425 TimeUnit::Second => 1,
426 TimeUnit::Millisecond => MILLISECONDS,
427 TimeUnit::Microsecond => MICROSECONDS,
428 TimeUnit::Nanosecond => NANOSECONDS,
429 }
430}
431
432fn timestamp_time_part<T: ArrowTimestampType>(
440 array: &PrimitiveArray<T>,
441 part: DatePart,
442) -> Option<Int32Array> {
443 Some(match part {
444 DatePart::Hour => {
445 array.unary(|v| v.div_euclid(units_per_second::<T>() * 3_600).rem_euclid(24) as i32)
446 }
447 DatePart::Minute => {
448 array.unary(|v| v.div_euclid(units_per_second::<T>() * 60).rem_euclid(60) as i32)
449 }
450 DatePart::Second => {
451 array.unary(|v| v.div_euclid(units_per_second::<T>()).rem_euclid(60) as i32)
452 }
453 DatePart::Millisecond => {
454 array.unary(|v| subsecond(v, units_per_second::<T>(), MILLISECONDS))
455 }
456 DatePart::Microsecond => {
457 array.unary(|v| subsecond(v, units_per_second::<T>(), MICROSECONDS))
458 }
459 DatePart::Nanosecond => array.unary(|v| subsecond(v, units_per_second::<T>(), NANOSECONDS)),
460 _ => return None,
461 })
462}
463
464#[inline]
468fn subsecond(v: i64, units: i64, target: i64) -> i32 {
469 let fraction = v.rem_euclid(units);
470 let scaled = if target >= units {
471 fraction * (target / units)
472 } else {
473 fraction / (units / target)
474 };
475 scaled as i32
476}
477
478impl ExtractDatePartExt for PrimitiveArray<TimestampSecondType> {
479 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
480 let array =
482 if let DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond = part {
483 Int32Array::new(vec![0; self.len()].into(), self.nulls().cloned())
484 } else if let Some(tz) = get_tz(self.data_type())? {
485 let map_func = get_date_time_part_extract_fn(part);
486 self.unary_opt(|d| {
487 timestamp_s_to_datetime(d)
488 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
489 .map(map_func)
490 })
491 } else if let Some(array) = timestamp_time_part(self, part) {
492 array
493 } else {
494 let map_func = get_date_time_part_extract_fn(part);
495 self.unary_opt(|d| timestamp_s_to_datetime(d).map(map_func))
496 };
497 Ok(array)
498 }
499}
500
501impl ExtractDatePartExt for PrimitiveArray<TimestampMillisecondType> {
502 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
503 let array = if let Some(tz) = get_tz(self.data_type())? {
504 let map_func = get_date_time_part_extract_fn(part);
505 self.unary_opt(|d| {
506 timestamp_ms_to_datetime(d)
507 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
508 .map(map_func)
509 })
510 } else if let Some(array) = timestamp_time_part(self, part) {
511 array
512 } else {
513 let map_func = get_date_time_part_extract_fn(part);
514 self.unary_opt(|d| timestamp_ms_to_datetime(d).map(map_func))
515 };
516 Ok(array)
517 }
518}
519
520impl ExtractDatePartExt for PrimitiveArray<TimestampMicrosecondType> {
521 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
522 let array = if let Some(tz) = get_tz(self.data_type())? {
523 let map_func = get_date_time_part_extract_fn(part);
524 self.unary_opt(|d| {
525 timestamp_us_to_datetime(d)
526 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
527 .map(map_func)
528 })
529 } else if let Some(array) = timestamp_time_part(self, part) {
530 array
531 } else {
532 let map_func = get_date_time_part_extract_fn(part);
533 self.unary_opt(|d| timestamp_us_to_datetime(d).map(map_func))
534 };
535 Ok(array)
536 }
537}
538
539impl ExtractDatePartExt for PrimitiveArray<TimestampNanosecondType> {
540 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
541 let array = if let Some(tz) = get_tz(self.data_type())? {
542 let map_func = get_date_time_part_extract_fn(part);
543 self.unary_opt(|d| {
544 timestamp_ns_to_datetime(d)
545 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
546 .map(map_func)
547 })
548 } else if let Some(array) = timestamp_time_part(self, part) {
549 array
550 } else {
551 let map_func = get_date_time_part_extract_fn(part);
552 self.unary_opt(|d| timestamp_ns_to_datetime(d).map(map_func))
553 };
554 Ok(array)
555 }
556}
557
558impl ExtractDatePartExt for PrimitiveArray<IntervalYearMonthType> {
559 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
560 match part {
561 DatePart::Year => Ok(self.unary_opt(|d| Some(d / 12))),
562 DatePart::Month => Ok(self.unary_opt(|d| Some(d % 12))),
563
564 DatePart::Quarter
565 | DatePart::Week
566 | DatePart::WeekISO
567 | DatePart::YearISO
568 | DatePart::Day
569 | DatePart::DayOfWeekSunday0
570 | DatePart::DayOfWeekMonday0
571 | DatePart::DayOfWeekSunday1
572 | DatePart::DayOfWeekMonday1
573 | DatePart::DayOfYear
574 | DatePart::Hour
575 | DatePart::Minute
576 | DatePart::Second
577 | DatePart::Millisecond
578 | DatePart::Microsecond
579 | DatePart::Nanosecond => {
580 return_compute_error_with!(format!("{part} does not support"), self.data_type())
581 }
582 }
583 }
584}
585
586impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> {
587 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
588 match part {
589 DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))),
590 DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))),
591 DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))),
592 DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))),
593 DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))),
594 DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))),
595 DatePart::Microsecond => {
596 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000)))
597 }
598 DatePart::Nanosecond => {
599 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000)))
600 }
601
602 DatePart::Quarter
603 | DatePart::Year
604 | DatePart::YearISO
605 | DatePart::WeekISO
606 | DatePart::Month
607 | DatePart::DayOfWeekSunday0
608 | DatePart::DayOfWeekMonday0
609 | DatePart::DayOfWeekSunday1
610 | DatePart::DayOfWeekMonday1
611 | DatePart::DayOfYear => {
612 return_compute_error_with!(format!("{part} does not support"), self.data_type())
613 }
614 }
615 }
616}
617
618impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> {
619 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
620 match part {
621 DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))),
622 DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months % 12))),
623 DatePart::Week => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days / 7))),
624 DatePart::Day => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days))),
625 DatePart::Hour => {
626 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 60 * 1_000_000_000)).try_into().ok()))
627 }
628 DatePart::Minute => {
629 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 1_000_000_000) % 60).try_into().ok()))
630 }
631 DatePart::Second => {
632 Ok(self.unary_opt(|d| ((d.nanoseconds / 1_000_000_000) % 60).try_into().ok()))
633 }
634 DatePart::Millisecond => Ok(self.unary_opt(|d| {
635 (d.nanoseconds % (60 * 1_000_000_000) / 1_000_000)
636 .try_into()
637 .ok()
638 })),
639 DatePart::Microsecond => Ok(self.unary_opt(|d| {
640 (d.nanoseconds % (60 * 1_000_000_000) / 1_000)
641 .try_into()
642 .ok()
643 })),
644 DatePart::Nanosecond => {
645 Ok(self.unary_opt(|d| (d.nanoseconds % (60 * 1_000_000_000)).try_into().ok()))
646 }
647
648 DatePart::Quarter
649 | DatePart::WeekISO
650 | DatePart::YearISO
651 | DatePart::DayOfWeekSunday0
652 | DatePart::DayOfWeekMonday0
653 | DatePart::DayOfWeekSunday1
654 | DatePart::DayOfWeekMonday1
655 | DatePart::DayOfYear => {
656 return_compute_error_with!(format!("{part} does not support"), self.data_type())
657 }
658 }
659 }
660}
661
662impl ExtractDatePartExt for PrimitiveArray<DurationSecondType> {
663 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
664 match part {
665 DatePart::Week => Ok(self.unary_opt(|d| (d / (60 * 60 * 24 * 7)).try_into().ok())),
666 DatePart::Day => Ok(self.unary_opt(|d| (d / (60 * 60 * 24)).try_into().ok())),
667 DatePart::Hour => Ok(self.unary_opt(|d| (d / (60 * 60)).try_into().ok())),
668 DatePart::Minute => Ok(self.unary_opt(|d| (d / 60).try_into().ok())),
669 DatePart::Second => Ok(self.unary_opt(|d| d.try_into().ok())),
670 DatePart::Millisecond => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
671 DatePart::Microsecond => {
672 Ok(self.unary_opt(|d| d.checked_mul(1_000_000)?.try_into().ok()))
673 }
674 DatePart::Nanosecond => {
675 Ok(self.unary_opt(|d| d.checked_mul(1_000_000_000)?.try_into().ok()))
676 }
677
678 DatePart::Year
679 | DatePart::YearISO
680 | DatePart::WeekISO
681 | DatePart::Quarter
682 | DatePart::Month
683 | DatePart::DayOfWeekSunday0
684 | DatePart::DayOfWeekMonday0
685 | DatePart::DayOfWeekSunday1
686 | DatePart::DayOfWeekMonday1
687 | DatePart::DayOfYear => {
688 return_compute_error_with!(format!("{part} does not support"), self.data_type())
689 }
690 }
691 }
692}
693
694impl ExtractDatePartExt for PrimitiveArray<DurationMillisecondType> {
695 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
696 match part {
697 DatePart::Week => {
698 Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24 * 7)).try_into().ok()))
699 }
700 DatePart::Day => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24)).try_into().ok())),
701 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60)).try_into().ok())),
702 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000 * 60)).try_into().ok())),
703 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
704 DatePart::Millisecond => Ok(self.unary_opt(|d| d.try_into().ok())),
705 DatePart::Microsecond => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
706 DatePart::Nanosecond => {
707 Ok(self.unary_opt(|d| d.checked_mul(1_000_000)?.try_into().ok()))
708 }
709
710 DatePart::Year
711 | DatePart::YearISO
712 | DatePart::WeekISO
713 | DatePart::Quarter
714 | DatePart::Month
715 | DatePart::DayOfWeekSunday0
716 | DatePart::DayOfWeekMonday0
717 | DatePart::DayOfWeekSunday1
718 | DatePart::DayOfWeekMonday1
719 | DatePart::DayOfYear => {
720 return_compute_error_with!(format!("{part} does not support"), self.data_type())
721 }
722 }
723 }
724}
725
726impl ExtractDatePartExt for PrimitiveArray<DurationMicrosecondType> {
727 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
728 match part {
729 DatePart::Week => {
730 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
731 }
732 DatePart::Day => {
733 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24)).try_into().ok()))
734 }
735 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60)).try_into().ok())),
736 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000 * 60)).try_into().ok())),
737 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
738 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
739 DatePart::Microsecond => Ok(self.unary_opt(|d| d.try_into().ok())),
740 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
741
742 DatePart::Year
743 | DatePart::YearISO
744 | DatePart::WeekISO
745 | DatePart::Quarter
746 | DatePart::Month
747 | DatePart::DayOfWeekSunday0
748 | DatePart::DayOfWeekMonday0
749 | DatePart::DayOfWeekSunday1
750 | DatePart::DayOfWeekMonday1
751 | DatePart::DayOfYear => {
752 return_compute_error_with!(format!("{part} does not support"), self.data_type())
753 }
754 }
755 }
756}
757
758impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
759 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
760 match part {
761 DatePart::Week => {
762 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
763 }
764 DatePart::Day => {
765 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24)).try_into().ok()))
766 }
767 DatePart::Hour => {
768 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60)).try_into().ok()))
769 }
770 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60)).try_into().ok())),
771 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000_000).try_into().ok())),
772 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
773 DatePart::Microsecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
774 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.try_into().ok())),
775
776 DatePart::Year
777 | DatePart::YearISO
778 | DatePart::WeekISO
779 | DatePart::Quarter
780 | DatePart::Month
781 | DatePart::DayOfWeekSunday0
782 | DatePart::DayOfWeekMonday0
783 | DatePart::DayOfWeekSunday1
784 | DatePart::DayOfWeekMonday1
785 | DatePart::DayOfYear => {
786 return_compute_error_with!(format!("{part} does not support"), self.data_type())
787 }
788 }
789 }
790}
791
792macro_rules! return_compute_error_with {
793 ($msg:expr, $param:expr) => {
794 return { Err(ArrowError::ComputeError(format!("{}: {}", $msg, $param))) }
795 };
796}
797
798pub(crate) use return_compute_error_with;
799
800trait ChronoDateExt {
802 fn num_days_from_monday(&self) -> i32;
804
805 fn num_days_from_sunday(&self) -> i32;
807}
808
809impl<T: Datelike> ChronoDateExt for T {
810 fn num_days_from_monday(&self) -> i32 {
811 self.weekday().num_days_from_monday() as i32
812 }
813
814 fn num_days_from_sunday(&self) -> i32 {
815 self.weekday().num_days_from_sunday() as i32
816 }
817}
818
819#[cfg(test)]
820mod tests {
821 use super::*;
822
823 use arrow_array::temporal_conversions::as_datetime;
824 use chrono::NaiveDate;
825
826 fn date_part_primitive<T: ArrowTemporalType>(
829 array: &PrimitiveArray<T>,
830 part: DatePart,
831 ) -> Result<Int32Array, ArrowError> {
832 let array = date_part(array, part)?;
833 Ok(array.as_primitive::<Int32Type>().to_owned())
834 }
835
836 const TIME_PARTS: [DatePart; 6] = [
838 DatePart::Hour,
839 DatePart::Minute,
840 DatePart::Second,
841 DatePart::Millisecond,
842 DatePart::Microsecond,
843 DatePart::Nanosecond,
844 ];
845
846 fn check_timestamp_time_parts<T: ArrowTimestampType>(units_per_second: i64) {
850 let mut values = vec![i64::MIN, i64::MAX];
851 for boundary in [1_000, 1_000_000] {
852 for delta in [-1, 0, 1] {
853 values.extend([boundary + delta, -boundary + delta]);
854 }
855 }
856 for base in [0, 60, 3_600, 86_400] {
857 for delta in [-1, 0, 1] {
858 for seconds in [base + delta, -base + delta] {
859 for fraction in [-1, 0, 1, units_per_second - 1] {
860 let value = i128::from(seconds) * i128::from(units_per_second)
861 + i128::from(fraction);
862 if let Ok(value) = i64::try_from(value) {
863 values.push(value);
864 }
865 }
866 }
867 }
868 }
869 let mut seed = 42_u64;
872 for _ in 0..256 {
873 seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
874 values.push(seed as i64);
875 let seconds = (seed % 4_000_000_000) as i64 - 2_000_000_000;
876 values.push(seconds * units_per_second + (seed % units_per_second as u64) as i64);
877 }
878 values.retain(|&v| as_datetime::<T>(v).is_some());
881 let no_nulls = PrimitiveArray::<T>::new(values.clone().into(), None);
882 let mixed = PrimitiveArray::<T>::from_iter(
883 values
884 .iter()
885 .enumerate()
886 .map(|(i, &v)| (i % 5 != 0).then_some(v)),
887 );
888 for array in [no_nulls, mixed.slice(1, mixed.len() - 2)] {
889 for part in TIME_PARTS {
890 let map_func = get_date_time_part_extract_fn(part);
891 let expected: Int32Array = array.unary_opt(|v| as_datetime::<T>(v).map(map_func));
892 let actual = date_part(&array, part).unwrap();
893 assert_eq!(
894 actual.as_primitive::<Int32Type>(),
895 &expected,
896 "{} {part}",
897 T::DATA_TYPE
898 );
899 }
900 }
901
902 let zoned = PrimitiveArray::<T>::from_iter_values([0]).with_timezone("+05:45");
905 for (part, expected) in [(DatePart::Hour, 5), (DatePart::Minute, 45)] {
906 assert_eq!(
907 date_part_primitive(&zoned, part).unwrap(),
908 Int32Array::from(vec![expected])
909 );
910 }
911 let invalid = PrimitiveArray::<T>::from_iter_values([0]).with_timezone("invalid timezone");
912 assert!(date_part(&invalid, DatePart::Second).is_err());
913 }
914
915 #[test]
916 fn test_timestamp_time_parts_match_chrono() {
917 check_timestamp_time_parts::<TimestampSecondType>(1);
918 check_timestamp_time_parts::<TimestampMillisecondType>(MILLISECONDS);
919 check_timestamp_time_parts::<TimestampMicrosecondType>(MICROSECONDS);
920 check_timestamp_time_parts::<TimestampNanosecondType>(NANOSECONDS);
921 }
922
923 #[test]
924 fn test_timestamp_time_parts_extremes() {
925 fn check<T: ArrowTimestampType>(min: (u32, u32, u32, u32), max: (u32, u32, u32, u32)) {
927 let time = |(h, m, s, ns)| NaiveDate::default().and_hms_nano_opt(h, m, s, ns).unwrap();
928 let expected = [Some(time(min)), None, Some(time(max))];
929 let array = PrimitiveArray::<T>::from_iter([Some(i64::MIN), None, Some(i64::MAX)]);
930 for part in TIME_PARTS {
931 let map_func = get_date_time_part_extract_fn(part);
932 assert_eq!(
933 date_part_primitive(&array, part).unwrap(),
934 Int32Array::from_iter(expected.iter().map(|t| t.map(map_func))),
935 "{} {part}",
936 T::DATA_TYPE
937 );
938 }
939 }
940
941 check::<TimestampSecondType>((8, 29, 52, 0), (15, 30, 7, 0));
945 check::<TimestampMillisecondType>((16, 47, 4, 192_000_000), (7, 12, 55, 807_000_000));
946 check::<TimestampMicrosecondType>((19, 59, 5, 224_192_000), (4, 0, 54, 775_807_000));
947 }
948
949 #[test]
950 fn test_temporal_array_date64_hour() {
951 let a: PrimitiveArray<Date64Type> =
952 vec![Some(1514764800000), None, Some(1550636625000)].into();
953
954 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
955 assert_eq!(0, b.value(0));
956 assert!(!b.is_valid(1));
957 assert_eq!(4, b.value(2));
958 }
959
960 #[test]
961 fn test_temporal_array_date32_hour() {
962 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
963
964 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
965 assert_eq!(0, b.value(0));
966 assert!(!b.is_valid(1));
967 assert_eq!(0, b.value(2));
968 }
969
970 #[test]
971 fn test_temporal_array_time32_second_hour() {
972 let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
973
974 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
975 assert_eq!(10, b.value(0));
976 assert_eq!(23, b.value(1));
977 }
978
979 #[test]
980 fn test_temporal_array_time64_micro_hour() {
981 let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
982
983 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
984 assert_eq!(10, b.value(0));
985 assert_eq!(23, b.value(1));
986 }
987
988 #[test]
989 fn test_temporal_array_timestamp_micro_hour() {
990 let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
991
992 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
993 assert_eq!(10, b.value(0));
994 assert_eq!(23, b.value(1));
995 }
996
997 #[test]
998 fn test_temporal_array_date64_year() {
999 let a: PrimitiveArray<Date64Type> =
1000 vec![Some(1514764800000), None, Some(1550636625000)].into();
1001
1002 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1003 assert_eq!(2018, b.value(0));
1004 assert!(!b.is_valid(1));
1005 assert_eq!(2019, b.value(2));
1006 }
1007
1008 #[test]
1009 fn test_temporal_array_date32_year() {
1010 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
1011
1012 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1013 assert_eq!(2011, b.value(0));
1014 assert!(!b.is_valid(1));
1015 assert_eq!(2012, b.value(2));
1016 }
1017
1018 #[test]
1019 fn test_temporal_array_date64_quarter() {
1020 let a: PrimitiveArray<Date64Type> =
1023 vec![Some(1514764800000), None, Some(1566275025000)].into();
1024
1025 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1026 assert_eq!(1, b.value(0));
1027 assert!(!b.is_valid(1));
1028 assert_eq!(3, b.value(2));
1029 }
1030
1031 #[test]
1032 fn test_temporal_array_date32_quarter() {
1033 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
1034
1035 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1036 assert_eq!(1, b.value(0));
1037 assert!(!b.is_valid(1));
1038 assert_eq!(4, b.value(2));
1039 }
1040
1041 #[test]
1042 fn test_temporal_array_timestamp_quarter_with_timezone() {
1043 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
1045 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1046 assert_eq!(2, b.value(0));
1047 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
1048 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1049 assert_eq!(1, b.value(0));
1050 }
1051
1052 #[test]
1053 fn test_all_quarters_date64() {
1054 let a: PrimitiveArray<Date64Type> = vec![
1060 Some(1767225600000),
1061 Some(1775001600000),
1062 Some(1782864000000),
1063 Some(1790812800000),
1064 None,
1065 ]
1066 .into();
1067
1068 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1069 assert_eq!(1, b.value(0)); assert_eq!(2, b.value(1)); assert_eq!(3, b.value(2)); assert_eq!(4, b.value(3)); assert!(!b.is_valid(4));
1074 }
1075
1076 #[test]
1077 fn test_all_quarters_date32() {
1078 let a: PrimitiveArray<Date32Type> =
1084 vec![Some(20454), Some(20544), Some(20635), Some(20727), None].into();
1085
1086 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1087 assert_eq!(1, b.value(0));
1088 assert_eq!(2, b.value(1));
1089 assert_eq!(3, b.value(2));
1090 assert_eq!(4, b.value(3));
1091 assert!(!b.is_valid(4));
1092 }
1093
1094 #[test]
1095 fn test_quarter_timestamp_microsecond() {
1096 let a: TimestampMicrosecondArray =
1100 vec![Some(1767225600000000), None, Some(1782864000000000)].into();
1101
1102 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1103 assert_eq!(1, b.value(0));
1104 assert!(!b.is_valid(1));
1105 assert_eq!(3, b.value(2));
1106 }
1107
1108 #[test]
1109 fn test_quarter_timestamp_nanosecond() {
1110 let a: TimestampNanosecondArray =
1114 vec![Some(1775001600000000000), None, Some(1790812800000000000)].into();
1115
1116 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
1117 assert_eq!(2, b.value(0));
1118 assert!(!b.is_valid(1));
1119 assert_eq!(4, b.value(2));
1120 }
1121
1122 #[test]
1123 fn test_temporal_array_date64_month() {
1124 let a: PrimitiveArray<Date64Type> =
1127 vec![Some(1514764800000), None, Some(1550636625000)].into();
1128
1129 let b = date_part_primitive(&a, DatePart::Month).unwrap();
1130 assert_eq!(1, b.value(0));
1131 assert!(!b.is_valid(1));
1132 assert_eq!(2, b.value(2));
1133 }
1134
1135 #[test]
1136 fn test_temporal_array_date32_month() {
1137 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
1138
1139 let b = date_part_primitive(&a, DatePart::Month).unwrap();
1140 assert_eq!(1, b.value(0));
1141 assert!(!b.is_valid(1));
1142 assert_eq!(2, b.value(2));
1143 }
1144
1145 #[test]
1146 fn test_temporal_array_timestamp_month_with_timezone() {
1147 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
1149 let b = date_part_primitive(&a, DatePart::Month).unwrap();
1150 assert_eq!(2, b.value(0));
1151 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
1152 let b = date_part_primitive(&a, DatePart::Month).unwrap();
1153 assert_eq!(1, b.value(0));
1154 }
1155
1156 #[test]
1157 fn test_temporal_array_timestamp_day_with_timezone() {
1158 let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
1160 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1161 assert_eq!(2, b.value(0));
1162 let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
1163 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1164 assert_eq!(1, b.value(0));
1165 }
1166
1167 #[test]
1168 fn test_temporal_array_date64_weekday() {
1169 let a: PrimitiveArray<Date64Type> =
1172 vec![Some(1514764800000), None, Some(1550636625000)].into();
1173
1174 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday0).unwrap();
1175 assert_eq!(0, b.value(0));
1176 assert!(!b.is_valid(1));
1177 assert_eq!(2, b.value(2));
1178 }
1179
1180 #[test]
1181 fn test_temporal_array_date64_dayofweek1() {
1182 let a: PrimitiveArray<Date64Type> = vec![
1186 Some(1514764800000),
1187 None,
1188 Some(1550636625000),
1189 Some(1483228800000),
1190 ]
1191 .into();
1192
1193 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday1).unwrap();
1194 assert_eq!(2, b.value(0));
1195 assert!(!b.is_valid(1));
1196 assert_eq!(4, b.value(2));
1197 assert_eq!(1, b.value(3));
1198 }
1199
1200 #[test]
1201 fn test_temporal_array_date64_isodow() {
1202 let a: PrimitiveArray<Date64Type> = vec![
1206 Some(1514764800000),
1207 None,
1208 Some(1550636625000),
1209 Some(1483228800000),
1210 ]
1211 .into();
1212
1213 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday1).unwrap();
1214 assert_eq!(1, b.value(0));
1215 assert!(!b.is_valid(1));
1216 assert_eq!(3, b.value(2));
1217 assert_eq!(7, b.value(3));
1218 }
1219
1220 #[test]
1221 fn test_temporal_array_date64_weekday0() {
1222 let a: PrimitiveArray<Date64Type> = vec![
1226 Some(1483228800000),
1227 None,
1228 Some(1514764800000),
1229 Some(1550636625000),
1230 ]
1231 .into();
1232
1233 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday0).unwrap();
1234 assert_eq!(0, b.value(0));
1235 assert!(!b.is_valid(1));
1236 assert_eq!(1, b.value(2));
1237 assert_eq!(3, b.value(3));
1238 }
1239
1240 #[test]
1241 fn test_temporal_array_date64_day() {
1242 let a: PrimitiveArray<Date64Type> =
1245 vec![Some(1514764800000), None, Some(1550636625000)].into();
1246
1247 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1248 assert_eq!(1, b.value(0));
1249 assert!(!b.is_valid(1));
1250 assert_eq!(20, b.value(2));
1251 }
1252
1253 #[test]
1254 fn test_temporal_array_date32_day() {
1255 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
1256
1257 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1258 assert_eq!(1, b.value(0));
1259 assert!(!b.is_valid(1));
1260 assert_eq!(1, b.value(2));
1261 }
1262
1263 #[test]
1264 fn test_temporal_array_date64_doy() {
1265 let a: PrimitiveArray<Date64Type> = vec![
1269 Some(1483228800000),
1270 Some(1514764800000),
1271 None,
1272 Some(1550636625000),
1273 ]
1274 .into();
1275
1276 let b = date_part_primitive(&a, DatePart::DayOfYear).unwrap();
1277 assert_eq!(1, b.value(0));
1278 assert_eq!(1, b.value(1));
1279 assert!(!b.is_valid(2));
1280 assert_eq!(51, b.value(3));
1281 }
1282
1283 #[test]
1284 fn test_temporal_array_timestamp_micro_year() {
1285 let a: TimestampMicrosecondArray =
1286 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1287
1288 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1289 assert_eq!(2021, b.value(0));
1290 assert!(!b.is_valid(1));
1291 assert_eq!(2024, b.value(2));
1292 }
1293
1294 #[test]
1295 fn test_temporal_array_date64_minute() {
1296 let a: PrimitiveArray<Date64Type> =
1297 vec![Some(1514764800000), None, Some(1550636625000)].into();
1298
1299 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1300 assert_eq!(0, b.value(0));
1301 assert!(!b.is_valid(1));
1302 assert_eq!(23, b.value(2));
1303 }
1304
1305 #[test]
1306 fn test_temporal_array_timestamp_micro_minute() {
1307 let a: TimestampMicrosecondArray =
1308 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1309
1310 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1311 assert_eq!(57, b.value(0));
1312 assert!(!b.is_valid(1));
1313 assert_eq!(44, b.value(2));
1314 }
1315
1316 #[test]
1317 fn test_temporal_array_date32_week() {
1318 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
1319
1320 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1321 assert_eq!(1, b.value(0));
1322 assert!(!b.is_valid(1));
1323 assert_eq!(2, b.value(2));
1324 }
1325
1326 #[test]
1327 fn test_temporal_array_date64_week() {
1328 let a: PrimitiveArray<Date64Type> = vec![
1331 Some(1646116175000),
1332 None,
1333 Some(1641171600000),
1334 Some(1640998800000),
1335 ]
1336 .into();
1337
1338 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1339 assert_eq!(9, b.value(0));
1340 assert!(!b.is_valid(1));
1341 assert_eq!(1, b.value(2));
1342 assert_eq!(52, b.value(3));
1343 }
1344
1345 #[test]
1346 fn test_temporal_array_timestamp_micro_week() {
1347 let a: TimestampMicrosecondArray =
1350 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1351
1352 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1353 assert_eq!(4, b.value(0));
1354 assert!(!b.is_valid(1));
1355 assert_eq!(30, b.value(2));
1356 }
1357
1358 #[test]
1359 fn test_temporal_array_date64_second() {
1360 let a: PrimitiveArray<Date64Type> =
1361 vec![Some(1514764800000), None, Some(1550636625000)].into();
1362
1363 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1364 assert_eq!(0, b.value(0));
1365 assert!(!b.is_valid(1));
1366 assert_eq!(45, b.value(2));
1367 }
1368
1369 #[test]
1370 fn test_temporal_array_timestamp_micro_second() {
1371 let a: TimestampMicrosecondArray =
1372 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1373
1374 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1375 assert_eq!(27, b.value(0));
1376 assert!(!b.is_valid(1));
1377 assert_eq!(7, b.value(2));
1378 }
1379
1380 #[test]
1381 fn test_temporal_array_timestamp_second_with_timezone() {
1382 let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1383 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1384 assert_eq!(10, b.value(0));
1385 assert_eq!(20, b.value(1));
1386 }
1387
1388 #[test]
1389 fn test_temporal_array_timestamp_minute_with_timezone() {
1390 let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1391 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1392 assert_eq!(50, b.value(0));
1393 assert_eq!(51, b.value(1));
1394 }
1395
1396 #[test]
1397 fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1398 let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1399 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1400 assert_eq!(5, b.value(0));
1401 }
1402
1403 #[test]
1404 fn test_temporal_array_timestamp_hour_with_timezone() {
1405 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1406 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1407 assert_eq!(11, b.value(0));
1408 }
1409
1410 #[test]
1411 fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1412 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1413 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1414 assert_eq!(11, b.value(0));
1415 }
1416
1417 #[test]
1418 fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1419 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1420 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1421 assert_eq!(11, b.value(0));
1422 }
1423
1424 #[test]
1425 fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1426 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1427 let err = date_part_primitive(&a, DatePart::Hour)
1428 .unwrap_err()
1429 .to_string();
1430 assert!(err.contains("Invalid timezone"), "{}", err);
1431 }
1432
1433 #[test]
1434 fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1435 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1436 let err = date_part_primitive(&a, DatePart::Hour)
1437 .unwrap_err()
1438 .to_string();
1439 assert!(err.contains("Invalid timezone"), "{}", err);
1440 }
1441
1442 #[test]
1443 fn test_temporal_array_timestamp_week_without_timezone() {
1444 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1448 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1449 assert_eq!(1, b.value(0));
1450 assert_eq!(2, b.value(1));
1451 assert_eq!(1, b.value(2));
1452 }
1453
1454 #[test]
1455 fn test_temporal_array_timestamp_week_with_timezone() {
1456 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1460 .with_timezone("+01:00".to_string());
1461 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1462 assert_eq!(1, b.value(0));
1463 assert_eq!(2, b.value(1));
1464 assert_eq!(2, b.value(2));
1465 }
1466
1467 #[test]
1468 fn test_hour_minute_second_dictionary_array() {
1469 let a = TimestampSecondArray::from(vec![
1470 60 * 60 * 10 + 61,
1471 60 * 60 * 20 + 122,
1472 60 * 60 * 30 + 183,
1473 ])
1474 .with_timezone("+01:00".to_string());
1475
1476 let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1477 let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1478
1479 let b = date_part(&dict, DatePart::Hour).unwrap();
1480
1481 let expected_dict =
1482 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1483 let expected = Arc::new(expected_dict) as ArrayRef;
1484 assert_eq!(&expected, &b);
1485
1486 let b = date_part(&dict, DatePart::Minute).unwrap();
1487
1488 let b_old = date_part(&dict, DatePart::Minute).unwrap();
1489
1490 let expected_dict =
1491 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1492 let expected = Arc::new(expected_dict) as ArrayRef;
1493 assert_eq!(&expected, &b);
1494 assert_eq!(&expected, &b_old);
1495
1496 let b = date_part(&dict, DatePart::Second).unwrap();
1497
1498 let b_old = date_part(&dict, DatePart::Second).unwrap();
1499
1500 let expected_dict =
1501 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1502 let expected = Arc::new(expected_dict) as ArrayRef;
1503 assert_eq!(&expected, &b);
1504 assert_eq!(&expected, &b_old);
1505
1506 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1507
1508 let expected_dict =
1509 DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1510 let expected = Arc::new(expected_dict) as ArrayRef;
1511 assert_eq!(&expected, &b);
1512 }
1513
1514 #[test]
1515 fn test_year_dictionary_array() {
1516 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1517
1518 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1519 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1520
1521 let b = date_part(&dict, DatePart::Year).unwrap();
1522
1523 let expected_dict = DictionaryArray::new(
1524 keys,
1525 Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1526 );
1527 let expected = Arc::new(expected_dict) as ArrayRef;
1528 assert_eq!(&expected, &b);
1529 }
1530
1531 #[test]
1532 fn test_quarter_month_dictionary_array() {
1533 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1536
1537 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1538 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1539
1540 let b = date_part(&dict, DatePart::Quarter).unwrap();
1541
1542 let expected =
1543 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1544 assert_eq!(b.as_ref(), &expected);
1545
1546 let b = date_part(&dict, DatePart::Month).unwrap();
1547
1548 let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1549 assert_eq!(b.as_ref(), &expected);
1550 }
1551
1552 #[test]
1553 fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1554 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1557
1558 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1559 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1560
1561 let b = date_part(&dict, DatePart::DayOfWeekMonday0).unwrap();
1562
1563 let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1564 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1565 assert_eq!(b.as_ref(), &expected);
1566
1567 let b = date_part(&dict, DatePart::DayOfWeekSunday0).unwrap();
1568
1569 let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), None]);
1570 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1571 assert_eq!(b.as_ref(), &expected);
1572
1573 let b = date_part(&dict, DatePart::Day).unwrap();
1574
1575 let a = Int32Array::from(vec![Some(1), Some(20), Some(20), Some(1), None]);
1576 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1577 assert_eq!(b.as_ref(), &expected);
1578
1579 let b = date_part(&dict, DatePart::DayOfYear).unwrap();
1580
1581 let a = Int32Array::from(vec![Some(1), Some(51), Some(51), Some(1), None]);
1582 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1583 assert_eq!(b.as_ref(), &expected);
1584
1585 let b = date_part(&dict, DatePart::Week).unwrap();
1586
1587 let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1588 let expected = DictionaryArray::new(keys, Arc::new(a));
1589 assert_eq!(b.as_ref(), &expected);
1590 }
1591
1592 #[test]
1593 fn test_temporal_array_date64_nanosecond() {
1594 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1601
1602 let b = date_part_primitive(&a, DatePart::Nanosecond).unwrap();
1603 assert!(!b.is_valid(0));
1604 assert_eq!(453_000_000, b.value(1));
1605
1606 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1607 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1608 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1609
1610 let a = Int32Array::from(vec![None, Some(453_000_000)]);
1611 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1612 let expected = Arc::new(expected_dict) as ArrayRef;
1613 assert_eq!(&expected, &b);
1614 }
1615
1616 #[test]
1617 fn test_temporal_array_date64_microsecond() {
1618 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1619
1620 let b = date_part_primitive(&a, DatePart::Microsecond).unwrap();
1621 assert!(!b.is_valid(0));
1622 assert_eq!(453_000, b.value(1));
1623
1624 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1625 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1626 let b = date_part(&dict, DatePart::Microsecond).unwrap();
1627
1628 let a = Int32Array::from(vec![None, Some(453_000)]);
1629 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1630 let expected = Arc::new(expected_dict) as ArrayRef;
1631 assert_eq!(&expected, &b);
1632 }
1633
1634 #[test]
1635 fn test_temporal_array_date64_millisecond() {
1636 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1637
1638 let b = date_part_primitive(&a, DatePart::Millisecond).unwrap();
1639 assert!(!b.is_valid(0));
1640 assert_eq!(453, b.value(1));
1641
1642 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1643 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1644 let b = date_part(&dict, DatePart::Millisecond).unwrap();
1645
1646 let a = Int32Array::from(vec![None, Some(453)]);
1647 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1648 let expected = Arc::new(expected_dict) as ArrayRef;
1649 assert_eq!(&expected, &b);
1650 }
1651
1652 #[test]
1653 fn test_temporal_array_time64_nanoseconds() {
1654 let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1656
1657 let actual = date_part(&input, DatePart::Hour).unwrap();
1658 let actual = actual.as_primitive::<Int32Type>();
1659 assert_eq!(23, actual.value(0));
1660
1661 let actual = date_part(&input, DatePart::Minute).unwrap();
1662 let actual = actual.as_primitive::<Int32Type>();
1663 assert_eq!(32, actual.value(0));
1664
1665 let actual = date_part(&input, DatePart::Second).unwrap();
1666 let actual = actual.as_primitive::<Int32Type>();
1667 assert_eq!(50, actual.value(0));
1668
1669 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1670 let actual = actual.as_primitive::<Int32Type>();
1671 assert_eq!(123, actual.value(0));
1672
1673 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1674 let actual = actual.as_primitive::<Int32Type>();
1675 assert_eq!(123_456, actual.value(0));
1676
1677 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1678 let actual = actual.as_primitive::<Int32Type>();
1679 assert_eq!(123_456_789, actual.value(0));
1680
1681 let input: Time64NanosecondArray = vec![
1683 Some(-1),
1684 Some(86_400_000_000_000),
1685 Some(86_401_000_000_000),
1686 None,
1687 ]
1688 .into();
1689 let actual = date_part(&input, DatePart::Hour).unwrap();
1690 let actual = actual.as_primitive::<Int32Type>();
1691 let expected: Int32Array = vec![None, None, None, None].into();
1692 assert_eq!(&expected, actual);
1693 }
1694
1695 #[test]
1696 fn test_temporal_array_time64_microseconds() {
1697 let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1699
1700 let actual = date_part(&input, DatePart::Hour).unwrap();
1701 let actual = actual.as_primitive::<Int32Type>();
1702 assert_eq!(23, actual.value(0));
1703
1704 let actual = date_part(&input, DatePart::Minute).unwrap();
1705 let actual = actual.as_primitive::<Int32Type>();
1706 assert_eq!(32, actual.value(0));
1707
1708 let actual = date_part(&input, DatePart::Second).unwrap();
1709 let actual = actual.as_primitive::<Int32Type>();
1710 assert_eq!(50, actual.value(0));
1711
1712 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1713 let actual = actual.as_primitive::<Int32Type>();
1714 assert_eq!(123, actual.value(0));
1715
1716 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1717 let actual = actual.as_primitive::<Int32Type>();
1718 assert_eq!(123_456, actual.value(0));
1719
1720 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1721 let actual = actual.as_primitive::<Int32Type>();
1722 assert_eq!(123_456_000, actual.value(0));
1723
1724 let input: Time64MicrosecondArray =
1726 vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1727 let actual = date_part(&input, DatePart::Hour).unwrap();
1728 let actual = actual.as_primitive::<Int32Type>();
1729 let expected: Int32Array = vec![None, None, None, None].into();
1730 assert_eq!(&expected, actual);
1731 }
1732
1733 #[test]
1734 fn test_temporal_array_time32_milliseconds() {
1735 let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1737
1738 let actual = date_part(&input, DatePart::Hour).unwrap();
1739 let actual = actual.as_primitive::<Int32Type>();
1740 assert_eq!(23, actual.value(0));
1741
1742 let actual = date_part(&input, DatePart::Minute).unwrap();
1743 let actual = actual.as_primitive::<Int32Type>();
1744 assert_eq!(32, actual.value(0));
1745
1746 let actual = date_part(&input, DatePart::Second).unwrap();
1747 let actual = actual.as_primitive::<Int32Type>();
1748 assert_eq!(50, actual.value(0));
1749
1750 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1751 let actual = actual.as_primitive::<Int32Type>();
1752 assert_eq!(123, actual.value(0));
1753
1754 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1755 let actual = actual.as_primitive::<Int32Type>();
1756 assert_eq!(123_000, actual.value(0));
1757
1758 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1759 let actual = actual.as_primitive::<Int32Type>();
1760 assert_eq!(123_000_000, actual.value(0));
1761
1762 let input: Time32MillisecondArray =
1764 vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1765 let actual = date_part(&input, DatePart::Hour).unwrap();
1766 let actual = actual.as_primitive::<Int32Type>();
1767 let expected: Int32Array = vec![None, None, None, None].into();
1768 assert_eq!(&expected, actual);
1769 }
1770
1771 #[test]
1772 fn test_temporal_array_time32_seconds() {
1773 let input: Time32SecondArray = vec![84_770].into();
1775
1776 let actual = date_part(&input, DatePart::Hour).unwrap();
1777 let actual = actual.as_primitive::<Int32Type>();
1778 assert_eq!(23, actual.value(0));
1779
1780 let actual = date_part(&input, DatePart::Minute).unwrap();
1781 let actual = actual.as_primitive::<Int32Type>();
1782 assert_eq!(32, actual.value(0));
1783
1784 let actual = date_part(&input, DatePart::Second).unwrap();
1785 let actual = actual.as_primitive::<Int32Type>();
1786 assert_eq!(50, actual.value(0));
1787
1788 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1789 let actual = actual.as_primitive::<Int32Type>();
1790 assert_eq!(0, actual.value(0));
1791
1792 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1793 let actual = actual.as_primitive::<Int32Type>();
1794 assert_eq!(0, actual.value(0));
1795
1796 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1797 let actual = actual.as_primitive::<Int32Type>();
1798 assert_eq!(0, actual.value(0));
1799
1800 let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1802 let actual = date_part(&input, DatePart::Hour).unwrap();
1803 let actual = actual.as_primitive::<Int32Type>();
1804 let expected: Int32Array = vec![None, None, None, None].into();
1805 assert_eq!(&expected, actual);
1806 }
1807
1808 #[test]
1809 fn test_temporal_array_time_invalid_parts() {
1810 fn ensure_returns_error(array: &dyn Array) {
1811 let invalid_parts = [
1812 DatePart::Quarter,
1813 DatePart::Year,
1814 DatePart::YearISO,
1815 DatePart::Month,
1816 DatePart::Week,
1817 DatePart::WeekISO,
1818 DatePart::Day,
1819 DatePart::DayOfWeekSunday0,
1820 DatePart::DayOfWeekMonday0,
1821 DatePart::DayOfWeekSunday1,
1822 DatePart::DayOfWeekMonday1,
1823 DatePart::DayOfYear,
1824 ];
1825
1826 for part in invalid_parts {
1827 let err = date_part(array, part).unwrap_err();
1828 let expected = format!(
1829 "Compute error: {part} does not support: {}",
1830 array.data_type()
1831 );
1832 assert_eq!(expected, err.to_string());
1833 }
1834 }
1835
1836 ensure_returns_error(&Time32SecondArray::from(vec![0]));
1837 ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1838 ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1839 ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1840 }
1841
1842 #[test]
1843 fn test_interval_year_month_array() {
1844 let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1845
1846 let actual = date_part(&input, DatePart::Year).unwrap();
1847 let actual = actual.as_primitive::<Int32Type>();
1848 assert_eq!(0, actual.value(0));
1849 assert_eq!(0, actual.value(1));
1850 assert_eq!(2, actual.value(2));
1851
1852 let actual = date_part(&input, DatePart::Month).unwrap();
1853 let actual = actual.as_primitive::<Int32Type>();
1854 assert_eq!(0, actual.value(0));
1855 assert_eq!(5, actual.value(1));
1856 assert_eq!(0, actual.value(2));
1857
1858 assert!(date_part(&input, DatePart::Day).is_err());
1859 assert!(date_part(&input, DatePart::Week).is_err());
1860 }
1861
1862 #[test]
1865 fn test_interval_day_time_array() {
1866 let input: IntervalDayTimeArray = vec![
1867 IntervalDayTime::ZERO,
1868 IntervalDayTime::new(10, 42), IntervalDayTime::new(10, 1042), IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1), IntervalDayTime::new(
1872 6,
1873 (MILLISECONDS * 60 * 60 * 4 + MILLISECONDS * 60 * 22 + MILLISECONDS * 11 + 3)
1874 as i32,
1875 ), ]
1877 .into();
1878
1879 let actual = date_part(&input, DatePart::Day).unwrap();
1881 let actual = actual.as_primitive::<Int32Type>();
1882 assert_eq!(0, actual.value(0));
1883 assert_eq!(10, actual.value(1));
1884 assert_eq!(10, actual.value(2));
1885 assert_eq!(10, actual.value(3));
1886 assert_eq!(6, actual.value(4));
1887
1888 let actual = date_part(&input, DatePart::Week).unwrap();
1889 let actual = actual.as_primitive::<Int32Type>();
1890 assert_eq!(0, actual.value(0));
1891 assert_eq!(1, actual.value(1));
1892 assert_eq!(1, actual.value(2));
1893 assert_eq!(1, actual.value(3));
1894 assert_eq!(0, actual.value(4));
1895
1896 let actual = date_part(&input, DatePart::Hour).unwrap();
1898 let actual = actual.as_primitive::<Int32Type>();
1899 assert_eq!(0, actual.value(0));
1900 assert_eq!(0, actual.value(1));
1901 assert_eq!(0, actual.value(2));
1902 assert_eq!(24, actual.value(3));
1903 assert_eq!(4, actual.value(4));
1904
1905 let actual = date_part(&input, DatePart::Minute).unwrap();
1906 let actual = actual.as_primitive::<Int32Type>();
1907 assert_eq!(0, actual.value(0));
1908 assert_eq!(0, actual.value(1));
1909 assert_eq!(0, actual.value(2));
1910 assert_eq!(0, actual.value(3));
1911 assert_eq!(22, actual.value(4));
1912
1913 let actual = date_part(&input, DatePart::Second).unwrap();
1914 let actual = actual.as_primitive::<Int32Type>();
1915 assert_eq!(0, actual.value(0));
1916 assert_eq!(0, actual.value(1));
1917 assert_eq!(1, actual.value(2));
1918 assert_eq!(0, actual.value(3));
1919 assert_eq!(11, actual.value(4));
1920
1921 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1922 let actual = actual.as_primitive::<Int32Type>();
1923 assert_eq!(0, actual.value(0));
1924 assert_eq!(42, actual.value(1));
1925 assert_eq!(1042, actual.value(2));
1926 assert_eq!(1, actual.value(3));
1927 assert_eq!(11003, actual.value(4));
1928
1929 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1930 let actual = actual.as_primitive::<Int32Type>();
1931 assert_eq!(0, actual.value(0));
1932 assert_eq!(42_000, actual.value(1));
1933 assert_eq!(1_042_000, actual.value(2));
1934 assert_eq!(1_000, actual.value(3));
1935 assert_eq!(11_003_000, actual.value(4));
1936
1937 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1938 let actual = actual.as_primitive::<Int32Type>();
1939 assert_eq!(0, actual.value(0));
1940 assert_eq!(42_000_000, actual.value(1));
1941 assert_eq!(1_042_000_000, actual.value(2));
1942 assert_eq!(1_000_000, actual.value(3));
1943 assert_eq!(0, actual.value(4));
1945
1946 assert!(date_part(&input, DatePart::Month).is_err());
1948 assert!(date_part(&input, DatePart::Year).is_err());
1949 }
1950
1951 #[test]
1954 fn test_interval_month_day_nano_array() {
1955 let input: IntervalMonthDayNanoArray = vec![
1956 IntervalMonthDayNano::ZERO,
1957 IntervalMonthDayNano::new(5, 10, 42), IntervalMonthDayNano::new(16, 35, NANOSECONDS_IN_DAY + 1), IntervalMonthDayNano::new(
1960 0,
1961 0,
1962 NANOSECONDS * 60 * 60 * 4
1963 + NANOSECONDS * 60 * 22
1964 + NANOSECONDS * 11
1965 + 1_000_000 * 33
1966 + 1_000 * 44
1967 + 5,
1968 ), ]
1970 .into();
1971
1972 let actual = date_part(&input, DatePart::Year).unwrap();
1974 let actual = actual.as_primitive::<Int32Type>();
1975 assert_eq!(0, actual.value(0));
1976 assert_eq!(0, actual.value(1));
1977 assert_eq!(1, actual.value(2));
1978 assert_eq!(0, actual.value(3));
1979
1980 let actual = date_part(&input, DatePart::Month).unwrap();
1981 let actual = actual.as_primitive::<Int32Type>();
1982 assert_eq!(0, actual.value(0));
1983 assert_eq!(5, actual.value(1));
1984 assert_eq!(4, actual.value(2));
1985 assert_eq!(0, actual.value(3));
1986
1987 let actual = date_part(&input, DatePart::Week).unwrap();
1989 let actual = actual.as_primitive::<Int32Type>();
1990 assert_eq!(0, actual.value(0));
1991 assert_eq!(1, actual.value(1));
1992 assert_eq!(5, actual.value(2));
1993 assert_eq!(0, actual.value(3));
1994
1995 let actual = date_part(&input, DatePart::Day).unwrap();
1996 let actual = actual.as_primitive::<Int32Type>();
1997 assert_eq!(0, actual.value(0));
1998 assert_eq!(10, actual.value(1));
1999 assert_eq!(35, actual.value(2));
2000 assert_eq!(0, actual.value(3));
2001
2002 let actual = date_part(&input, DatePart::Hour).unwrap();
2004 let actual = actual.as_primitive::<Int32Type>();
2005 assert_eq!(0, actual.value(0));
2006 assert_eq!(0, actual.value(1));
2007 assert_eq!(24, actual.value(2));
2008 assert_eq!(4, actual.value(3));
2009
2010 let actual = date_part(&input, DatePart::Minute).unwrap();
2011 let actual = actual.as_primitive::<Int32Type>();
2012 assert_eq!(0, actual.value(0));
2013 assert_eq!(0, actual.value(1));
2014 assert_eq!(0, actual.value(2));
2015 assert_eq!(22, actual.value(3));
2016
2017 let actual = date_part(&input, DatePart::Second).unwrap();
2018 let actual = actual.as_primitive::<Int32Type>();
2019 assert_eq!(0, actual.value(0));
2020 assert_eq!(0, actual.value(1));
2021 assert_eq!(0, actual.value(2));
2022 assert_eq!(11, actual.value(3));
2023
2024 let actual = date_part(&input, DatePart::Millisecond).unwrap();
2025 let actual = actual.as_primitive::<Int32Type>();
2026 assert_eq!(0, actual.value(0));
2027 assert_eq!(0, actual.value(1));
2028 assert_eq!(0, actual.value(2));
2029 assert_eq!(11_033, actual.value(3));
2030
2031 let actual = date_part(&input, DatePart::Microsecond).unwrap();
2032 let actual = actual.as_primitive::<Int32Type>();
2033 assert_eq!(0, actual.value(0));
2034 assert_eq!(0, actual.value(1));
2035 assert_eq!(0, actual.value(2));
2036 assert_eq!(11_033_044, actual.value(3));
2037
2038 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2039 let actual = actual.as_primitive::<Int32Type>();
2040 assert_eq!(0, actual.value(0));
2041 assert_eq!(42, actual.value(1));
2042 assert_eq!(1, actual.value(2));
2043 assert_eq!(0, actual.value(3));
2045 }
2046
2047 #[test]
2048 fn test_interval_array_invalid_parts() {
2049 fn ensure_returns_error(array: &dyn Array) {
2050 let invalid_parts = [
2051 DatePart::Quarter,
2052 DatePart::YearISO,
2053 DatePart::WeekISO,
2054 DatePart::DayOfWeekSunday0,
2055 DatePart::DayOfWeekMonday0,
2056 DatePart::DayOfWeekSunday1,
2057 DatePart::DayOfWeekMonday1,
2058 DatePart::DayOfYear,
2059 ];
2060
2061 for part in invalid_parts {
2062 let err = date_part(array, part).unwrap_err();
2063 let expected = format!(
2064 "Compute error: {part} does not support: {}",
2065 array.data_type()
2066 );
2067 assert_eq!(expected, err.to_string());
2068 }
2069 }
2070
2071 ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
2072 ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
2073 ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
2074 IntervalMonthDayNano::ZERO,
2075 ]));
2076 }
2077
2078 #[test]
2079 fn test_duration_second() {
2080 let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2081
2082 let actual = date_part(&input, DatePart::Second).unwrap();
2083 let actual = actual.as_primitive::<Int32Type>();
2084 assert_eq!(0, actual.value(0));
2085 assert_eq!(42, actual.value(1));
2086 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2087
2088 let actual = date_part(&input, DatePart::Millisecond).unwrap();
2089 let actual = actual.as_primitive::<Int32Type>();
2090 assert_eq!(0, actual.value(0));
2091 assert_eq!(42_000, actual.value(1));
2092 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
2093
2094 let actual = date_part(&input, DatePart::Microsecond).unwrap();
2095 let actual = actual.as_primitive::<Int32Type>();
2096 assert_eq!(0, actual.value(0));
2097 assert_eq!(42_000_000, actual.value(1));
2098 assert_eq!(0, actual.value(2));
2099
2100 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2101 let actual = actual.as_primitive::<Int32Type>();
2102 assert_eq!(0, actual.value(0));
2103 assert_eq!(0, actual.value(1));
2104 assert_eq!(0, actual.value(2));
2105 }
2106
2107 #[test]
2108 fn test_duration_millisecond() {
2109 let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2110
2111 let actual = date_part(&input, DatePart::Second).unwrap();
2112 let actual = actual.as_primitive::<Int32Type>();
2113 assert_eq!(0, actual.value(0));
2114 assert_eq!(0, actual.value(1));
2115 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2116
2117 let actual = date_part(&input, DatePart::Millisecond).unwrap();
2118 let actual = actual.as_primitive::<Int32Type>();
2119 assert_eq!(0, actual.value(0));
2120 assert_eq!(42, actual.value(1));
2121 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2122
2123 let actual = date_part(&input, DatePart::Microsecond).unwrap();
2124 let actual = actual.as_primitive::<Int32Type>();
2125 assert_eq!(0, actual.value(0));
2126 assert_eq!(42_000, actual.value(1));
2127 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
2128
2129 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2130 let actual = actual.as_primitive::<Int32Type>();
2131 assert_eq!(0, actual.value(0));
2132 assert_eq!(42_000_000, actual.value(1));
2133 assert_eq!(0, actual.value(2));
2134 }
2135
2136 #[test]
2137 fn test_duration_microsecond() {
2138 let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2139
2140 let actual = date_part(&input, DatePart::Second).unwrap();
2141 let actual = actual.as_primitive::<Int32Type>();
2142 assert_eq!(0, actual.value(0));
2143 assert_eq!(0, actual.value(1));
2144 assert_eq!(0, actual.value(2));
2145
2146 let actual = date_part(&input, DatePart::Millisecond).unwrap();
2147 let actual = actual.as_primitive::<Int32Type>();
2148 assert_eq!(0, actual.value(0));
2149 assert_eq!(0, actual.value(1));
2150 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2151
2152 let actual = date_part(&input, DatePart::Microsecond).unwrap();
2153 let actual = actual.as_primitive::<Int32Type>();
2154 assert_eq!(0, actual.value(0));
2155 assert_eq!(42, actual.value(1));
2156 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2157
2158 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2159 let actual = actual.as_primitive::<Int32Type>();
2160 assert_eq!(0, actual.value(0));
2161 assert_eq!(42_000, actual.value(1));
2162 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
2163 }
2164
2165 #[test]
2166 fn test_duration_nanosecond() {
2167 let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
2168
2169 let actual = date_part(&input, DatePart::Second).unwrap();
2170 let actual = actual.as_primitive::<Int32Type>();
2171 assert_eq!(0, actual.value(0));
2172 assert_eq!(0, actual.value(1));
2173 assert_eq!(0, actual.value(2));
2174
2175 let actual = date_part(&input, DatePart::Millisecond).unwrap();
2176 let actual = actual.as_primitive::<Int32Type>();
2177 assert_eq!(0, actual.value(0));
2178 assert_eq!(0, actual.value(1));
2179 assert_eq!(0, actual.value(2));
2180
2181 let actual = date_part(&input, DatePart::Microsecond).unwrap();
2182 let actual = actual.as_primitive::<Int32Type>();
2183 assert_eq!(0, actual.value(0));
2184 assert_eq!(0, actual.value(1));
2185 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2186
2187 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2188 let actual = actual.as_primitive::<Int32Type>();
2189 assert_eq!(0, actual.value(0));
2190 assert_eq!(42, actual.value(1));
2191 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2192 }
2193
2194 #[test]
2195 fn test_duration_invalid_parts() {
2196 fn ensure_returns_error(array: &dyn Array) {
2197 let invalid_parts = [
2198 DatePart::Year,
2199 DatePart::YearISO,
2200 DatePart::Quarter,
2201 DatePart::Month,
2202 DatePart::WeekISO,
2203 DatePart::DayOfWeekSunday0,
2204 DatePart::DayOfWeekMonday0,
2205 DatePart::DayOfWeekSunday1,
2206 DatePart::DayOfWeekMonday1,
2207 DatePart::DayOfYear,
2208 ];
2209
2210 for part in invalid_parts {
2211 let err = date_part(array, part).unwrap_err();
2212 let expected = format!(
2213 "Compute error: {part} does not support: {}",
2214 array.data_type()
2215 );
2216 assert_eq!(expected, err.to_string());
2217 }
2218 }
2219
2220 ensure_returns_error(&DurationSecondArray::from(vec![0]));
2221 ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
2222 ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
2223 ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
2224 }
2225
2226 const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
2227 const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
2228 const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
2229 const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
2230 #[test]
2232 fn test_temporal_array_date64_week_iso() {
2233 let a: PrimitiveArray<Date64Type> = vec![
2234 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2235 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2236 ]
2237 .into();
2238
2239 let b = date_part(&a, DatePart::WeekISO).unwrap();
2240 let actual = b.as_primitive::<Int32Type>();
2241 assert_eq!(1, actual.value(0));
2242 assert_eq!(8, actual.value(1));
2243 }
2244
2245 #[test]
2246 fn test_temporal_array_date64_year_iso() {
2247 let a: PrimitiveArray<Date64Type> = vec![
2248 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2249 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2250 ]
2251 .into();
2252
2253 let b = date_part(&a, DatePart::YearISO).unwrap();
2254 let actual = b.as_primitive::<Int32Type>();
2255 assert_eq!(2018, actual.value(0));
2256 assert_eq!(2019, actual.value(1));
2257 }
2258
2259 #[test]
2260 fn test_temporal_array_timestamp_week_iso() {
2261 let a = TimestampSecondArray::from(vec![
2262 TIMESTAMP_SECOND_1970_01_01, SECONDS_IN_DAY * 4, SECONDS_IN_DAY * 4 - 1, ]);
2266 let b = date_part(&a, DatePart::WeekISO).unwrap();
2267 let actual = b.as_primitive::<Int32Type>();
2268 assert_eq!(1, actual.value(0));
2269 assert_eq!(2, actual.value(1));
2270 assert_eq!(1, actual.value(2));
2271 }
2272
2273 #[test]
2274 fn test_temporal_array_timestamp_year_iso() {
2275 let a = TimestampSecondArray::from(vec![
2276 TIMESTAMP_SECOND_1970_01_01,
2277 SECONDS_IN_DAY * 4,
2278 SECONDS_IN_DAY * 4 - 1,
2279 ]);
2280 let b = date_part(&a, DatePart::YearISO).unwrap();
2281 let actual = b.as_primitive::<Int32Type>();
2282 assert_eq!(1970, actual.value(0));
2283 assert_eq!(1970, actual.value(1));
2284 assert_eq!(1970, actual.value(2));
2285 }
2286
2287 const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
2288 const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
2289 #[test]
2293 fn test_temporal_array_date64_week_iso_edge_cases() {
2294 let a: PrimitiveArray<Date64Type> = vec![
2295 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2296 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2297 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2298 ]
2299 .into();
2300
2301 let b = date_part(&a, DatePart::WeekISO).unwrap();
2302 let actual = b.as_primitive::<Int32Type>();
2303 assert_eq!(53, actual.value(0));
2304 assert_eq!(53, actual.value(1));
2305 assert_eq!(1, actual.value(2));
2306 }
2307
2308 #[test]
2309 fn test_temporal_array_date64_year_iso_edge_cases() {
2310 let a: PrimitiveArray<Date64Type> = vec![
2311 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2312 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2313 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2314 ]
2315 .into();
2316
2317 let b = date_part(&a, DatePart::YearISO).unwrap();
2318 let actual = b.as_primitive::<Int32Type>();
2319 assert_eq!(2015, actual.value(0));
2320 assert_eq!(2015, actual.value(1));
2321 assert_eq!(2016, actual.value(2));
2322 }
2323
2324 #[test]
2325 fn test_temporal_array_timestamp_week_iso_edge_cases() {
2326 let a = TimestampSecondArray::from(vec![
2327 TIMESTAMP_SECOND_2015_12_28,
2328 TIMESTAMP_SECOND_2016_01_03,
2329 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2330 ]);
2331 let b = date_part(&a, DatePart::WeekISO).unwrap();
2332 let actual = b.as_primitive::<Int32Type>();
2333 assert_eq!(53, actual.value(0));
2334 assert_eq!(53, actual.value(1));
2335 assert_eq!(1, actual.value(2));
2336 }
2337
2338 #[test]
2339 fn test_temporal_array_timestamp_year_iso_edge_cases() {
2340 let a = TimestampSecondArray::from(vec![
2341 TIMESTAMP_SECOND_2015_12_28,
2342 TIMESTAMP_SECOND_2016_01_03,
2343 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2344 ]);
2345 let b = date_part(&a, DatePart::YearISO).unwrap();
2346 let actual = b.as_primitive::<Int32Type>();
2347 assert_eq!(2015, actual.value(0));
2348 assert_eq!(2015, actual.value(1));
2349 assert_eq!(2016, actual.value(2));
2350 }
2351
2352 #[test]
2353 fn test_ree_timestamp_year() {
2354 let vals: TimestampSecondArray =
2355 vec![Some(1514764800), Some(1550636625), Some(1550636625)].into();
2356 let run_ends = Int32Array::from(vec![1, 2, 3]);
2357 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2358
2359 let b = date_part(&ree, DatePart::Year).unwrap();
2360 let ree_result = b.as_run_opt::<Int32Type>().unwrap();
2361 let values = ree_result.values().as_primitive::<Int32Type>();
2362 assert_eq!(2018, values.value(0));
2363 assert_eq!(2019, values.value(1));
2364 assert_eq!(2019, values.value(2));
2365 }
2366
2367 #[test]
2368 fn test_ree_date64_month() {
2369 let vals: PrimitiveArray<Date64Type> =
2370 vec![Some(1514764800000), Some(1550636625000)].into();
2371 let run_ends = Int64Array::from(vec![2, 4]);
2372 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2373
2374 let b = date_part(&ree, DatePart::Month).unwrap();
2375 let ree_result = b.as_run_opt::<Int64Type>().unwrap();
2376 let values = ree_result.values().as_primitive::<Int32Type>();
2377 assert_eq!(1, values.value(0));
2378 assert_eq!(2, values.value(1));
2379 }
2380
2381 #[test]
2382 fn test_date_part_from_str() {
2383 let cases = [
2384 ("y", DatePart::Year),
2385 ("yr", DatePart::Year),
2386 ("year", DatePart::Year),
2387 ("years", DatePart::Year),
2388 ("YEAR", DatePart::Year),
2389 ("isoyear", DatePart::YearISO),
2390 ("qtr", DatePart::Quarter),
2391 ("quarter", DatePart::Quarter),
2392 ("quarters", DatePart::Quarter),
2393 ("mon", DatePart::Month),
2394 ("mons", DatePart::Month),
2395 ("month", DatePart::Month),
2396 ("MONTHS", DatePart::Month),
2397 ("w", DatePart::Week),
2398 ("week", DatePart::Week),
2399 ("isoweek", DatePart::WeekISO),
2400 ("d", DatePart::Day),
2401 ("day", DatePart::Day),
2402 ("dow", DatePart::DayOfWeekSunday0),
2403 ("DayOfWeek", DatePart::DayOfWeekSunday0),
2404 ("dow1", DatePart::DayOfWeekSunday1),
2405 ("dayofweek1", DatePart::DayOfWeekSunday1),
2406 ("DAYOFWEEK1", DatePart::DayOfWeekSunday1),
2407 ("isodow", DatePart::DayOfWeekMonday1),
2408 ("ISODOW", DatePart::DayOfWeekMonday1),
2409 ("doy", DatePart::DayOfYear),
2410 ("DayOfYear", DatePart::DayOfYear),
2411 ("h", DatePart::Hour),
2412 ("hr", DatePart::Hour),
2413 ("hour", DatePart::Hour),
2414 ("m", DatePart::Minute),
2418 ("min", DatePart::Minute),
2419 ("mins", DatePart::Minute),
2420 ("minute", DatePart::Minute),
2421 ("s", DatePart::Second),
2422 ("sec", DatePart::Second),
2423 ("second", DatePart::Second),
2424 ("ms", DatePart::Millisecond),
2425 ("msec", DatePart::Millisecond),
2426 ("mseconds", DatePart::Millisecond),
2427 ("millisecond", DatePart::Millisecond),
2428 ("us", DatePart::Microsecond),
2429 ("usec", DatePart::Microsecond),
2430 ("useconds", DatePart::Microsecond),
2431 ("microsecond", DatePart::Microsecond),
2432 ("nanosecond", DatePart::Nanosecond),
2433 ("nanoseconds", DatePart::Nanosecond),
2434 ];
2435 for (input, expected) in cases {
2436 assert_eq!(
2437 DatePart::from_str(input).unwrap(),
2438 expected,
2439 "parsing {input}"
2440 );
2441 }
2442 }
2443
2444 #[test]
2445 fn test_date_part_from_str_unknown() {
2446 let unknown = [
2448 "epoch",
2449 "century",
2450 "decade",
2451 "millennium",
2452 "timezone",
2453 "timezone_hour",
2454 "timezone_minute",
2455 " year ",
2458 "year ",
2459 "",
2460 "nope",
2461 ];
2462 for s in unknown {
2463 let err = DatePart::from_str(s).unwrap_err();
2464 assert!(
2465 matches!(err, ArrowError::InvalidArgumentError(_)),
2466 "expected InvalidArgumentError for {s:?}, got: {err}"
2467 );
2468 }
2469 }
2470}