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> {
208 downcast_temporal_array!(
209 array => {
210 let array = array.date_part(part)?;
211 let array = Arc::new(array) as ArrayRef;
212 Ok(array)
213 }
214 DataType::Interval(IntervalUnit::YearMonth) => {
215 let array = as_primitive_array::<IntervalYearMonthType>(array).date_part(part)?;
216 let array = Arc::new(array) as ArrayRef;
217 Ok(array)
218 }
219 DataType::Interval(IntervalUnit::DayTime) => {
220 let array = as_primitive_array::<IntervalDayTimeType>(array).date_part(part)?;
221 let array = Arc::new(array) as ArrayRef;
222 Ok(array)
223 }
224 DataType::Interval(IntervalUnit::MonthDayNano) => {
225 let array = as_primitive_array::<IntervalMonthDayNanoType>(array).date_part(part)?;
226 let array = Arc::new(array) as ArrayRef;
227 Ok(array)
228 }
229 DataType::Duration(TimeUnit::Second) => {
230 let array = as_primitive_array::<DurationSecondType>(array).date_part(part)?;
231 let array = Arc::new(array) as ArrayRef;
232 Ok(array)
233 }
234 DataType::Duration(TimeUnit::Millisecond) => {
235 let array = as_primitive_array::<DurationMillisecondType>(array).date_part(part)?;
236 let array = Arc::new(array) as ArrayRef;
237 Ok(array)
238 }
239 DataType::Duration(TimeUnit::Microsecond) => {
240 let array = as_primitive_array::<DurationMicrosecondType>(array).date_part(part)?;
241 let array = Arc::new(array) as ArrayRef;
242 Ok(array)
243 }
244 DataType::Duration(TimeUnit::Nanosecond) => {
245 let array = as_primitive_array::<DurationNanosecondType>(array).date_part(part)?;
246 let array = Arc::new(array) as ArrayRef;
247 Ok(array)
248 }
249 DataType::Dictionary(_, _) => {
250 let array = array.as_any_dictionary();
251 let values = date_part(array.values(), part)?;
252 let new_array = array.with_values(values);
253 Ok(new_array)
254 }
255 DataType::RunEndEncoded(_, _) => {
256 let array = array.as_any_ree();
257 let values = date_part(array.values(), part)?;
258 let new_array = array.with_values(values);
259 Ok(new_array)
260 }
261 t => return_compute_error_with!(format!("{part} does not support"), t),
262 )
263}
264
265fn get_tz(dt: &DataType) -> Result<Option<Tz>, ArrowError> {
268 match dt {
269 DataType::Timestamp(_, Some(tz)) => Ok(Some(tz.parse::<Tz>()?)),
270 DataType::Timestamp(_, None) => Ok(None),
271 _ => Err(ArrowError::CastError(format!("Not a timestamp type: {dt}"))),
272 }
273}
274
275trait ExtractDatePartExt {
277 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError>;
278}
279
280impl ExtractDatePartExt for PrimitiveArray<Time32SecondType> {
281 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
282 #[inline]
283 fn range_check(s: i32) -> bool {
284 (0..SECONDS_IN_DAY as i32).contains(&s)
285 }
286 match part {
287 DatePart::Hour => Ok(self.unary_opt(|s| range_check(s).then_some(s / 3_600))),
288 DatePart::Minute => Ok(self.unary_opt(|s| range_check(s).then_some((s / 60) % 60))),
289 DatePart::Second => Ok(self.unary_opt(|s| range_check(s).then_some(s % 60))),
290 DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond => {
292 Ok(self.unary_opt(|s| range_check(s).then_some(0)))
293 }
294 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
295 }
296 }
297}
298
299impl ExtractDatePartExt for PrimitiveArray<Time32MillisecondType> {
300 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
301 #[inline]
302 fn range_check(ms: i32) -> bool {
303 (0..MILLISECONDS_IN_DAY as i32).contains(&ms)
304 }
305 let milliseconds = MILLISECONDS as i32;
306 match part {
307 DatePart::Hour => {
308 Ok(self.unary_opt(|ms| range_check(ms).then_some(ms / 3_600 / milliseconds)))
309 }
310 DatePart::Minute => {
311 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / 60 / milliseconds) % 60)))
312 }
313 DatePart::Second => {
314 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms / milliseconds) % 60)))
315 }
316 DatePart::Millisecond => {
317 Ok(self.unary_opt(|ms| range_check(ms).then_some(ms % milliseconds)))
318 }
319 DatePart::Microsecond => {
320 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000)))
321 }
322 DatePart::Nanosecond => {
323 Ok(self.unary_opt(|ms| range_check(ms).then_some((ms % milliseconds) * 1_000_000)))
324 }
325 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
326 }
327 }
328}
329
330impl ExtractDatePartExt for PrimitiveArray<Time64MicrosecondType> {
331 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
332 #[inline]
333 fn range_check(us: i64) -> bool {
334 (0..MICROSECONDS_IN_DAY).contains(&us)
335 }
336 match part {
337 DatePart::Hour => {
338 Ok(self
339 .unary_opt(|us| range_check(us).then_some((us / 3_600 / MICROSECONDS) as i32)))
340 }
341 DatePart::Minute => Ok(self
342 .unary_opt(|us| range_check(us).then_some(((us / 60 / MICROSECONDS) % 60) as i32))),
343 DatePart::Second => {
344 Ok(self
345 .unary_opt(|us| range_check(us).then_some(((us / MICROSECONDS) % 60) as i32)))
346 }
347 DatePart::Millisecond => Ok(self
348 .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) / 1_000) as i32))),
349 DatePart::Microsecond => {
350 Ok(self.unary_opt(|us| range_check(us).then_some((us % MICROSECONDS) as i32)))
351 }
352 DatePart::Nanosecond => Ok(self
353 .unary_opt(|us| range_check(us).then_some(((us % MICROSECONDS) * 1_000) as i32))),
354 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
355 }
356 }
357}
358
359impl ExtractDatePartExt for PrimitiveArray<Time64NanosecondType> {
360 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
361 #[inline]
362 fn range_check(ns: i64) -> bool {
363 (0..NANOSECONDS_IN_DAY).contains(&ns)
364 }
365 match part {
366 DatePart::Hour => {
367 Ok(self
368 .unary_opt(|ns| range_check(ns).then_some((ns / 3_600 / NANOSECONDS) as i32)))
369 }
370 DatePart::Minute => Ok(self
371 .unary_opt(|ns| range_check(ns).then_some(((ns / 60 / NANOSECONDS) % 60) as i32))),
372 DatePart::Second => Ok(
373 self.unary_opt(|ns| range_check(ns).then_some(((ns / NANOSECONDS) % 60) as i32))
374 ),
375 DatePart::Millisecond => Ok(self.unary_opt(|ns| {
376 range_check(ns).then_some(((ns % NANOSECONDS) / 1_000_000) as i32)
377 })),
378 DatePart::Microsecond => {
379 Ok(self
380 .unary_opt(|ns| range_check(ns).then_some(((ns % NANOSECONDS) / 1_000) as i32)))
381 }
382 DatePart::Nanosecond => {
383 Ok(self.unary_opt(|ns| range_check(ns).then_some((ns % NANOSECONDS) as i32)))
384 }
385 _ => return_compute_error_with!(format!("{part} does not support"), self.data_type()),
386 }
387 }
388}
389
390impl ExtractDatePartExt for PrimitiveArray<Date32Type> {
391 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
392 if let DatePart::Hour
394 | DatePart::Minute
395 | DatePart::Second
396 | DatePart::Millisecond
397 | DatePart::Microsecond
398 | DatePart::Nanosecond = part
399 {
400 Ok(Int32Array::new(
401 vec![0; self.len()].into(),
402 self.nulls().cloned(),
403 ))
404 } else {
405 let map_func = get_date_time_part_extract_fn(part);
406 Ok(self.unary_opt(|d| date32_to_datetime(d).map(map_func)))
407 }
408 }
409}
410
411impl ExtractDatePartExt for PrimitiveArray<Date64Type> {
412 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
413 let map_func = get_date_time_part_extract_fn(part);
414 Ok(self.unary_opt(|d| date64_to_datetime(d).map(map_func)))
415 }
416}
417
418impl ExtractDatePartExt for PrimitiveArray<TimestampSecondType> {
419 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
420 let array =
422 if let DatePart::Millisecond | DatePart::Microsecond | DatePart::Nanosecond = part {
423 Int32Array::new(vec![0; self.len()].into(), self.nulls().cloned())
424 } else if let Some(tz) = get_tz(self.data_type())? {
425 let map_func = get_date_time_part_extract_fn(part);
426 self.unary_opt(|d| {
427 timestamp_s_to_datetime(d)
428 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
429 .map(map_func)
430 })
431 } else {
432 let map_func = get_date_time_part_extract_fn(part);
433 self.unary_opt(|d| timestamp_s_to_datetime(d).map(map_func))
434 };
435 Ok(array)
436 }
437}
438
439impl ExtractDatePartExt for PrimitiveArray<TimestampMillisecondType> {
440 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
441 let array = if let Some(tz) = get_tz(self.data_type())? {
442 let map_func = get_date_time_part_extract_fn(part);
443 self.unary_opt(|d| {
444 timestamp_ms_to_datetime(d)
445 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
446 .map(map_func)
447 })
448 } else {
449 let map_func = get_date_time_part_extract_fn(part);
450 self.unary_opt(|d| timestamp_ms_to_datetime(d).map(map_func))
451 };
452 Ok(array)
453 }
454}
455
456impl ExtractDatePartExt for PrimitiveArray<TimestampMicrosecondType> {
457 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
458 let array = if let Some(tz) = get_tz(self.data_type())? {
459 let map_func = get_date_time_part_extract_fn(part);
460 self.unary_opt(|d| {
461 timestamp_us_to_datetime(d)
462 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
463 .map(map_func)
464 })
465 } else {
466 let map_func = get_date_time_part_extract_fn(part);
467 self.unary_opt(|d| timestamp_us_to_datetime(d).map(map_func))
468 };
469 Ok(array)
470 }
471}
472
473impl ExtractDatePartExt for PrimitiveArray<TimestampNanosecondType> {
474 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
475 let array = if let Some(tz) = get_tz(self.data_type())? {
476 let map_func = get_date_time_part_extract_fn(part);
477 self.unary_opt(|d| {
478 timestamp_ns_to_datetime(d)
479 .map(|c| Utc.from_utc_datetime(&c).with_timezone(&tz))
480 .map(map_func)
481 })
482 } else {
483 let map_func = get_date_time_part_extract_fn(part);
484 self.unary_opt(|d| timestamp_ns_to_datetime(d).map(map_func))
485 };
486 Ok(array)
487 }
488}
489
490impl ExtractDatePartExt for PrimitiveArray<IntervalYearMonthType> {
491 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
492 match part {
493 DatePart::Year => Ok(self.unary_opt(|d| Some(d / 12))),
494 DatePart::Month => Ok(self.unary_opt(|d| Some(d % 12))),
495
496 DatePart::Quarter
497 | DatePart::Week
498 | DatePart::WeekISO
499 | DatePart::YearISO
500 | DatePart::Day
501 | DatePart::DayOfWeekSunday0
502 | DatePart::DayOfWeekMonday0
503 | DatePart::DayOfWeekSunday1
504 | DatePart::DayOfWeekMonday1
505 | DatePart::DayOfYear
506 | DatePart::Hour
507 | DatePart::Minute
508 | DatePart::Second
509 | DatePart::Millisecond
510 | DatePart::Microsecond
511 | DatePart::Nanosecond => {
512 return_compute_error_with!(format!("{part} does not support"), self.data_type())
513 }
514 }
515 }
516}
517
518impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> {
519 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
520 match part {
521 DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))),
522 DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))),
523 DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))),
524 DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))),
525 DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))),
526 DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))),
527 DatePart::Microsecond => {
528 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000)))
529 }
530 DatePart::Nanosecond => {
531 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000)))
532 }
533
534 DatePart::Quarter
535 | DatePart::Year
536 | DatePart::YearISO
537 | DatePart::WeekISO
538 | DatePart::Month
539 | DatePart::DayOfWeekSunday0
540 | DatePart::DayOfWeekMonday0
541 | DatePart::DayOfWeekSunday1
542 | DatePart::DayOfWeekMonday1
543 | DatePart::DayOfYear => {
544 return_compute_error_with!(format!("{part} does not support"), self.data_type())
545 }
546 }
547 }
548}
549
550impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> {
551 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
552 match part {
553 DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))),
554 DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months % 12))),
555 DatePart::Week => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days / 7))),
556 DatePart::Day => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days))),
557 DatePart::Hour => {
558 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 60 * 1_000_000_000)).try_into().ok()))
559 }
560 DatePart::Minute => {
561 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 1_000_000_000) % 60).try_into().ok()))
562 }
563 DatePart::Second => {
564 Ok(self.unary_opt(|d| ((d.nanoseconds / 1_000_000_000) % 60).try_into().ok()))
565 }
566 DatePart::Millisecond => Ok(self.unary_opt(|d| {
567 (d.nanoseconds % (60 * 1_000_000_000) / 1_000_000)
568 .try_into()
569 .ok()
570 })),
571 DatePart::Microsecond => Ok(self.unary_opt(|d| {
572 (d.nanoseconds % (60 * 1_000_000_000) / 1_000)
573 .try_into()
574 .ok()
575 })),
576 DatePart::Nanosecond => {
577 Ok(self.unary_opt(|d| (d.nanoseconds % (60 * 1_000_000_000)).try_into().ok()))
578 }
579
580 DatePart::Quarter
581 | DatePart::WeekISO
582 | DatePart::YearISO
583 | DatePart::DayOfWeekSunday0
584 | DatePart::DayOfWeekMonday0
585 | DatePart::DayOfWeekSunday1
586 | DatePart::DayOfWeekMonday1
587 | DatePart::DayOfYear => {
588 return_compute_error_with!(format!("{part} does not support"), self.data_type())
589 }
590 }
591 }
592}
593
594impl ExtractDatePartExt for PrimitiveArray<DurationSecondType> {
595 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
596 match part {
597 DatePart::Week => Ok(self.unary_opt(|d| (d / (60 * 60 * 24 * 7)).try_into().ok())),
598 DatePart::Day => Ok(self.unary_opt(|d| (d / (60 * 60 * 24)).try_into().ok())),
599 DatePart::Hour => Ok(self.unary_opt(|d| (d / (60 * 60)).try_into().ok())),
600 DatePart::Minute => Ok(self.unary_opt(|d| (d / 60).try_into().ok())),
601 DatePart::Second => Ok(self.unary_opt(|d| d.try_into().ok())),
602 DatePart::Millisecond => {
603 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
604 }
605 DatePart::Microsecond => {
606 Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
607 }
608 DatePart::Nanosecond => Ok(
609 self.unary_opt(|d| d.checked_mul(1_000_000_000).and_then(|d| d.try_into().ok()))
610 ),
611
612 DatePart::Year
613 | DatePart::YearISO
614 | DatePart::WeekISO
615 | DatePart::Quarter
616 | DatePart::Month
617 | DatePart::DayOfWeekSunday0
618 | DatePart::DayOfWeekMonday0
619 | DatePart::DayOfWeekSunday1
620 | DatePart::DayOfWeekMonday1
621 | DatePart::DayOfYear => {
622 return_compute_error_with!(format!("{part} does not support"), self.data_type())
623 }
624 }
625 }
626}
627
628impl ExtractDatePartExt for PrimitiveArray<DurationMillisecondType> {
629 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
630 match part {
631 DatePart::Week => {
632 Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24 * 7)).try_into().ok()))
633 }
634 DatePart::Day => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24)).try_into().ok())),
635 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60)).try_into().ok())),
636 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000 * 60)).try_into().ok())),
637 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
638 DatePart::Millisecond => Ok(self.unary_opt(|d| d.try_into().ok())),
639 DatePart::Microsecond => {
640 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
641 }
642 DatePart::Nanosecond => {
643 Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
644 }
645
646 DatePart::Year
647 | DatePart::YearISO
648 | DatePart::WeekISO
649 | DatePart::Quarter
650 | DatePart::Month
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<DurationMicrosecondType> {
663 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
664 match part {
665 DatePart::Week => {
666 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
667 }
668 DatePart::Day => {
669 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24)).try_into().ok()))
670 }
671 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60)).try_into().ok())),
672 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000 * 60)).try_into().ok())),
673 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
674 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
675 DatePart::Microsecond => Ok(self.unary_opt(|d| d.try_into().ok())),
676 DatePart::Nanosecond => {
677 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
678 }
679
680 DatePart::Year
681 | DatePart::YearISO
682 | DatePart::WeekISO
683 | DatePart::Quarter
684 | DatePart::Month
685 | DatePart::DayOfWeekSunday0
686 | DatePart::DayOfWeekMonday0
687 | DatePart::DayOfWeekSunday1
688 | DatePart::DayOfWeekMonday1
689 | DatePart::DayOfYear => {
690 return_compute_error_with!(format!("{part} does not support"), self.data_type())
691 }
692 }
693 }
694}
695
696impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
697 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
698 match part {
699 DatePart::Week => {
700 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
701 }
702 DatePart::Day => {
703 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24)).try_into().ok()))
704 }
705 DatePart::Hour => {
706 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60)).try_into().ok()))
707 }
708 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60)).try_into().ok())),
709 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000_000).try_into().ok())),
710 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
711 DatePart::Microsecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
712 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.try_into().ok())),
713
714 DatePart::Year
715 | DatePart::YearISO
716 | DatePart::WeekISO
717 | DatePart::Quarter
718 | DatePart::Month
719 | DatePart::DayOfWeekSunday0
720 | DatePart::DayOfWeekMonday0
721 | DatePart::DayOfWeekSunday1
722 | DatePart::DayOfWeekMonday1
723 | DatePart::DayOfYear => {
724 return_compute_error_with!(format!("{part} does not support"), self.data_type())
725 }
726 }
727 }
728}
729
730macro_rules! return_compute_error_with {
731 ($msg:expr, $param:expr) => {
732 return { Err(ArrowError::ComputeError(format!("{}: {}", $msg, $param))) }
733 };
734}
735
736pub(crate) use return_compute_error_with;
737
738trait ChronoDateExt {
740 fn num_days_from_monday(&self) -> i32;
742
743 fn num_days_from_sunday(&self) -> i32;
745}
746
747impl<T: Datelike> ChronoDateExt for T {
748 fn num_days_from_monday(&self) -> i32 {
749 self.weekday().num_days_from_monday() as i32
750 }
751
752 fn num_days_from_sunday(&self) -> i32 {
753 self.weekday().num_days_from_sunday() as i32
754 }
755}
756
757#[cfg(test)]
758mod tests {
759 use super::*;
760
761 fn date_part_primitive<T: ArrowTemporalType>(
764 array: &PrimitiveArray<T>,
765 part: DatePart,
766 ) -> Result<Int32Array, ArrowError> {
767 let array = date_part(array, part)?;
768 Ok(array.as_primitive::<Int32Type>().to_owned())
769 }
770
771 #[test]
772 fn test_temporal_array_date64_hour() {
773 let a: PrimitiveArray<Date64Type> =
774 vec![Some(1514764800000), None, Some(1550636625000)].into();
775
776 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
777 assert_eq!(0, b.value(0));
778 assert!(!b.is_valid(1));
779 assert_eq!(4, b.value(2));
780 }
781
782 #[test]
783 fn test_temporal_array_date32_hour() {
784 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
785
786 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
787 assert_eq!(0, b.value(0));
788 assert!(!b.is_valid(1));
789 assert_eq!(0, b.value(2));
790 }
791
792 #[test]
793 fn test_temporal_array_time32_second_hour() {
794 let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
795
796 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
797 assert_eq!(10, b.value(0));
798 assert_eq!(23, b.value(1));
799 }
800
801 #[test]
802 fn test_temporal_array_time64_micro_hour() {
803 let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
804
805 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
806 assert_eq!(10, b.value(0));
807 assert_eq!(23, b.value(1));
808 }
809
810 #[test]
811 fn test_temporal_array_timestamp_micro_hour() {
812 let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
813
814 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
815 assert_eq!(10, b.value(0));
816 assert_eq!(23, b.value(1));
817 }
818
819 #[test]
820 fn test_temporal_array_date64_year() {
821 let a: PrimitiveArray<Date64Type> =
822 vec![Some(1514764800000), None, Some(1550636625000)].into();
823
824 let b = date_part_primitive(&a, DatePart::Year).unwrap();
825 assert_eq!(2018, b.value(0));
826 assert!(!b.is_valid(1));
827 assert_eq!(2019, b.value(2));
828 }
829
830 #[test]
831 fn test_temporal_array_date32_year() {
832 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
833
834 let b = date_part_primitive(&a, DatePart::Year).unwrap();
835 assert_eq!(2011, b.value(0));
836 assert!(!b.is_valid(1));
837 assert_eq!(2012, b.value(2));
838 }
839
840 #[test]
841 fn test_temporal_array_date64_quarter() {
842 let a: PrimitiveArray<Date64Type> =
845 vec![Some(1514764800000), None, Some(1566275025000)].into();
846
847 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
848 assert_eq!(1, b.value(0));
849 assert!(!b.is_valid(1));
850 assert_eq!(3, b.value(2));
851 }
852
853 #[test]
854 fn test_temporal_array_date32_quarter() {
855 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
856
857 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
858 assert_eq!(1, b.value(0));
859 assert!(!b.is_valid(1));
860 assert_eq!(4, b.value(2));
861 }
862
863 #[test]
864 fn test_temporal_array_timestamp_quarter_with_timezone() {
865 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
867 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
868 assert_eq!(2, b.value(0));
869 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
870 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
871 assert_eq!(1, b.value(0));
872 }
873
874 #[test]
875 fn test_all_quarters_date64() {
876 let a: PrimitiveArray<Date64Type> = vec![
882 Some(1767225600000),
883 Some(1775001600000),
884 Some(1782864000000),
885 Some(1790812800000),
886 None,
887 ]
888 .into();
889
890 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
891 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));
896 }
897
898 #[test]
899 fn test_all_quarters_date32() {
900 let a: PrimitiveArray<Date32Type> =
906 vec![Some(20454), Some(20544), Some(20635), Some(20727), None].into();
907
908 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
909 assert_eq!(1, b.value(0));
910 assert_eq!(2, b.value(1));
911 assert_eq!(3, b.value(2));
912 assert_eq!(4, b.value(3));
913 assert!(!b.is_valid(4));
914 }
915
916 #[test]
917 fn test_quarter_timestamp_microsecond() {
918 let a: TimestampMicrosecondArray =
922 vec![Some(1767225600000000), None, Some(1782864000000000)].into();
923
924 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
925 assert_eq!(1, b.value(0));
926 assert!(!b.is_valid(1));
927 assert_eq!(3, b.value(2));
928 }
929
930 #[test]
931 fn test_quarter_timestamp_nanosecond() {
932 let a: TimestampNanosecondArray =
936 vec![Some(1775001600000000000), None, Some(1790812800000000000)].into();
937
938 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
939 assert_eq!(2, b.value(0));
940 assert!(!b.is_valid(1));
941 assert_eq!(4, b.value(2));
942 }
943
944 #[test]
945 fn test_temporal_array_date64_month() {
946 let a: PrimitiveArray<Date64Type> =
949 vec![Some(1514764800000), None, Some(1550636625000)].into();
950
951 let b = date_part_primitive(&a, DatePart::Month).unwrap();
952 assert_eq!(1, b.value(0));
953 assert!(!b.is_valid(1));
954 assert_eq!(2, b.value(2));
955 }
956
957 #[test]
958 fn test_temporal_array_date32_month() {
959 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
960
961 let b = date_part_primitive(&a, DatePart::Month).unwrap();
962 assert_eq!(1, b.value(0));
963 assert!(!b.is_valid(1));
964 assert_eq!(2, b.value(2));
965 }
966
967 #[test]
968 fn test_temporal_array_timestamp_month_with_timezone() {
969 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
971 let b = date_part_primitive(&a, DatePart::Month).unwrap();
972 assert_eq!(2, b.value(0));
973 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
974 let b = date_part_primitive(&a, DatePart::Month).unwrap();
975 assert_eq!(1, b.value(0));
976 }
977
978 #[test]
979 fn test_temporal_array_timestamp_day_with_timezone() {
980 let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
982 let b = date_part_primitive(&a, DatePart::Day).unwrap();
983 assert_eq!(2, b.value(0));
984 let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
985 let b = date_part_primitive(&a, DatePart::Day).unwrap();
986 assert_eq!(1, b.value(0));
987 }
988
989 #[test]
990 fn test_temporal_array_date64_weekday() {
991 let a: PrimitiveArray<Date64Type> =
994 vec![Some(1514764800000), None, Some(1550636625000)].into();
995
996 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday0).unwrap();
997 assert_eq!(0, b.value(0));
998 assert!(!b.is_valid(1));
999 assert_eq!(2, b.value(2));
1000 }
1001
1002 #[test]
1003 fn test_temporal_array_date64_dayofweek1() {
1004 let a: PrimitiveArray<Date64Type> = vec![
1008 Some(1514764800000),
1009 None,
1010 Some(1550636625000),
1011 Some(1483228800000),
1012 ]
1013 .into();
1014
1015 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday1).unwrap();
1016 assert_eq!(2, b.value(0));
1017 assert!(!b.is_valid(1));
1018 assert_eq!(4, b.value(2));
1019 assert_eq!(1, b.value(3));
1020 }
1021
1022 #[test]
1023 fn test_temporal_array_date64_isodow() {
1024 let a: PrimitiveArray<Date64Type> = vec![
1028 Some(1514764800000),
1029 None,
1030 Some(1550636625000),
1031 Some(1483228800000),
1032 ]
1033 .into();
1034
1035 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday1).unwrap();
1036 assert_eq!(1, b.value(0));
1037 assert!(!b.is_valid(1));
1038 assert_eq!(3, b.value(2));
1039 assert_eq!(7, b.value(3));
1040 }
1041
1042 #[test]
1043 fn test_temporal_array_date64_weekday0() {
1044 let a: PrimitiveArray<Date64Type> = vec![
1048 Some(1483228800000),
1049 None,
1050 Some(1514764800000),
1051 Some(1550636625000),
1052 ]
1053 .into();
1054
1055 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday0).unwrap();
1056 assert_eq!(0, b.value(0));
1057 assert!(!b.is_valid(1));
1058 assert_eq!(1, b.value(2));
1059 assert_eq!(3, b.value(3));
1060 }
1061
1062 #[test]
1063 fn test_temporal_array_date64_day() {
1064 let a: PrimitiveArray<Date64Type> =
1067 vec![Some(1514764800000), None, Some(1550636625000)].into();
1068
1069 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1070 assert_eq!(1, b.value(0));
1071 assert!(!b.is_valid(1));
1072 assert_eq!(20, b.value(2));
1073 }
1074
1075 #[test]
1076 fn test_temporal_array_date32_day() {
1077 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
1078
1079 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1080 assert_eq!(1, b.value(0));
1081 assert!(!b.is_valid(1));
1082 assert_eq!(1, b.value(2));
1083 }
1084
1085 #[test]
1086 fn test_temporal_array_date64_doy() {
1087 let a: PrimitiveArray<Date64Type> = vec![
1091 Some(1483228800000),
1092 Some(1514764800000),
1093 None,
1094 Some(1550636625000),
1095 ]
1096 .into();
1097
1098 let b = date_part_primitive(&a, DatePart::DayOfYear).unwrap();
1099 assert_eq!(1, b.value(0));
1100 assert_eq!(1, b.value(1));
1101 assert!(!b.is_valid(2));
1102 assert_eq!(51, b.value(3));
1103 }
1104
1105 #[test]
1106 fn test_temporal_array_timestamp_micro_year() {
1107 let a: TimestampMicrosecondArray =
1108 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1109
1110 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1111 assert_eq!(2021, b.value(0));
1112 assert!(!b.is_valid(1));
1113 assert_eq!(2024, b.value(2));
1114 }
1115
1116 #[test]
1117 fn test_temporal_array_date64_minute() {
1118 let a: PrimitiveArray<Date64Type> =
1119 vec![Some(1514764800000), None, Some(1550636625000)].into();
1120
1121 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1122 assert_eq!(0, b.value(0));
1123 assert!(!b.is_valid(1));
1124 assert_eq!(23, b.value(2));
1125 }
1126
1127 #[test]
1128 fn test_temporal_array_timestamp_micro_minute() {
1129 let a: TimestampMicrosecondArray =
1130 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1131
1132 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1133 assert_eq!(57, b.value(0));
1134 assert!(!b.is_valid(1));
1135 assert_eq!(44, b.value(2));
1136 }
1137
1138 #[test]
1139 fn test_temporal_array_date32_week() {
1140 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
1141
1142 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1143 assert_eq!(1, b.value(0));
1144 assert!(!b.is_valid(1));
1145 assert_eq!(2, b.value(2));
1146 }
1147
1148 #[test]
1149 fn test_temporal_array_date64_week() {
1150 let a: PrimitiveArray<Date64Type> = vec![
1153 Some(1646116175000),
1154 None,
1155 Some(1641171600000),
1156 Some(1640998800000),
1157 ]
1158 .into();
1159
1160 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1161 assert_eq!(9, b.value(0));
1162 assert!(!b.is_valid(1));
1163 assert_eq!(1, b.value(2));
1164 assert_eq!(52, b.value(3));
1165 }
1166
1167 #[test]
1168 fn test_temporal_array_timestamp_micro_week() {
1169 let a: TimestampMicrosecondArray =
1172 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1173
1174 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1175 assert_eq!(4, b.value(0));
1176 assert!(!b.is_valid(1));
1177 assert_eq!(30, b.value(2));
1178 }
1179
1180 #[test]
1181 fn test_temporal_array_date64_second() {
1182 let a: PrimitiveArray<Date64Type> =
1183 vec![Some(1514764800000), None, Some(1550636625000)].into();
1184
1185 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1186 assert_eq!(0, b.value(0));
1187 assert!(!b.is_valid(1));
1188 assert_eq!(45, b.value(2));
1189 }
1190
1191 #[test]
1192 fn test_temporal_array_timestamp_micro_second() {
1193 let a: TimestampMicrosecondArray =
1194 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1195
1196 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1197 assert_eq!(27, b.value(0));
1198 assert!(!b.is_valid(1));
1199 assert_eq!(7, b.value(2));
1200 }
1201
1202 #[test]
1203 fn test_temporal_array_timestamp_second_with_timezone() {
1204 let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1205 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1206 assert_eq!(10, b.value(0));
1207 assert_eq!(20, b.value(1));
1208 }
1209
1210 #[test]
1211 fn test_temporal_array_timestamp_minute_with_timezone() {
1212 let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1213 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1214 assert_eq!(50, b.value(0));
1215 assert_eq!(51, b.value(1));
1216 }
1217
1218 #[test]
1219 fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1220 let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1221 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1222 assert_eq!(5, b.value(0));
1223 }
1224
1225 #[test]
1226 fn test_temporal_array_timestamp_hour_with_timezone() {
1227 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1228 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1229 assert_eq!(11, b.value(0));
1230 }
1231
1232 #[test]
1233 fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1234 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1235 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1236 assert_eq!(11, b.value(0));
1237 }
1238
1239 #[test]
1240 fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1241 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1242 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1243 assert_eq!(11, b.value(0));
1244 }
1245
1246 #[test]
1247 fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1248 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1249 let err = date_part_primitive(&a, DatePart::Hour)
1250 .unwrap_err()
1251 .to_string();
1252 assert!(err.contains("Invalid timezone"), "{}", err);
1253 }
1254
1255 #[test]
1256 fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1257 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1258 let err = date_part_primitive(&a, DatePart::Hour)
1259 .unwrap_err()
1260 .to_string();
1261 assert!(err.contains("Invalid timezone"), "{}", err);
1262 }
1263
1264 #[test]
1265 fn test_temporal_array_timestamp_week_without_timezone() {
1266 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1270 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1271 assert_eq!(1, b.value(0));
1272 assert_eq!(2, b.value(1));
1273 assert_eq!(1, b.value(2));
1274 }
1275
1276 #[test]
1277 fn test_temporal_array_timestamp_week_with_timezone() {
1278 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1282 .with_timezone("+01:00".to_string());
1283 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1284 assert_eq!(1, b.value(0));
1285 assert_eq!(2, b.value(1));
1286 assert_eq!(2, b.value(2));
1287 }
1288
1289 #[test]
1290 fn test_hour_minute_second_dictionary_array() {
1291 let a = TimestampSecondArray::from(vec![
1292 60 * 60 * 10 + 61,
1293 60 * 60 * 20 + 122,
1294 60 * 60 * 30 + 183,
1295 ])
1296 .with_timezone("+01:00".to_string());
1297
1298 let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1299 let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1300
1301 let b = date_part(&dict, DatePart::Hour).unwrap();
1302
1303 let expected_dict =
1304 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1305 let expected = Arc::new(expected_dict) as ArrayRef;
1306 assert_eq!(&expected, &b);
1307
1308 let b = date_part(&dict, DatePart::Minute).unwrap();
1309
1310 let b_old = date_part(&dict, DatePart::Minute).unwrap();
1311
1312 let expected_dict =
1313 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1314 let expected = Arc::new(expected_dict) as ArrayRef;
1315 assert_eq!(&expected, &b);
1316 assert_eq!(&expected, &b_old);
1317
1318 let b = date_part(&dict, DatePart::Second).unwrap();
1319
1320 let b_old = date_part(&dict, DatePart::Second).unwrap();
1321
1322 let expected_dict =
1323 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1324 let expected = Arc::new(expected_dict) as ArrayRef;
1325 assert_eq!(&expected, &b);
1326 assert_eq!(&expected, &b_old);
1327
1328 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1329
1330 let expected_dict =
1331 DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1332 let expected = Arc::new(expected_dict) as ArrayRef;
1333 assert_eq!(&expected, &b);
1334 }
1335
1336 #[test]
1337 fn test_year_dictionary_array() {
1338 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1339
1340 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1341 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1342
1343 let b = date_part(&dict, DatePart::Year).unwrap();
1344
1345 let expected_dict = DictionaryArray::new(
1346 keys,
1347 Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1348 );
1349 let expected = Arc::new(expected_dict) as ArrayRef;
1350 assert_eq!(&expected, &b);
1351 }
1352
1353 #[test]
1354 fn test_quarter_month_dictionary_array() {
1355 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1358
1359 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1360 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1361
1362 let b = date_part(&dict, DatePart::Quarter).unwrap();
1363
1364 let expected =
1365 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1366 assert_eq!(b.as_ref(), &expected);
1367
1368 let b = date_part(&dict, DatePart::Month).unwrap();
1369
1370 let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1371 assert_eq!(b.as_ref(), &expected);
1372 }
1373
1374 #[test]
1375 fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1376 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1379
1380 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1381 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1382
1383 let b = date_part(&dict, DatePart::DayOfWeekMonday0).unwrap();
1384
1385 let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1386 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1387 assert_eq!(b.as_ref(), &expected);
1388
1389 let b = date_part(&dict, DatePart::DayOfWeekSunday0).unwrap();
1390
1391 let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), None]);
1392 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1393 assert_eq!(b.as_ref(), &expected);
1394
1395 let b = date_part(&dict, DatePart::Day).unwrap();
1396
1397 let a = Int32Array::from(vec![Some(1), Some(20), Some(20), Some(1), None]);
1398 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1399 assert_eq!(b.as_ref(), &expected);
1400
1401 let b = date_part(&dict, DatePart::DayOfYear).unwrap();
1402
1403 let a = Int32Array::from(vec![Some(1), Some(51), Some(51), Some(1), None]);
1404 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1405 assert_eq!(b.as_ref(), &expected);
1406
1407 let b = date_part(&dict, DatePart::Week).unwrap();
1408
1409 let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1410 let expected = DictionaryArray::new(keys, Arc::new(a));
1411 assert_eq!(b.as_ref(), &expected);
1412 }
1413
1414 #[test]
1415 fn test_temporal_array_date64_nanosecond() {
1416 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1423
1424 let b = date_part_primitive(&a, DatePart::Nanosecond).unwrap();
1425 assert!(!b.is_valid(0));
1426 assert_eq!(453_000_000, b.value(1));
1427
1428 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1429 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1430 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1431
1432 let a = Int32Array::from(vec![None, Some(453_000_000)]);
1433 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1434 let expected = Arc::new(expected_dict) as ArrayRef;
1435 assert_eq!(&expected, &b);
1436 }
1437
1438 #[test]
1439 fn test_temporal_array_date64_microsecond() {
1440 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1441
1442 let b = date_part_primitive(&a, DatePart::Microsecond).unwrap();
1443 assert!(!b.is_valid(0));
1444 assert_eq!(453_000, b.value(1));
1445
1446 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1447 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1448 let b = date_part(&dict, DatePart::Microsecond).unwrap();
1449
1450 let a = Int32Array::from(vec![None, Some(453_000)]);
1451 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1452 let expected = Arc::new(expected_dict) as ArrayRef;
1453 assert_eq!(&expected, &b);
1454 }
1455
1456 #[test]
1457 fn test_temporal_array_date64_millisecond() {
1458 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1459
1460 let b = date_part_primitive(&a, DatePart::Millisecond).unwrap();
1461 assert!(!b.is_valid(0));
1462 assert_eq!(453, b.value(1));
1463
1464 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1465 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1466 let b = date_part(&dict, DatePart::Millisecond).unwrap();
1467
1468 let a = Int32Array::from(vec![None, Some(453)]);
1469 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1470 let expected = Arc::new(expected_dict) as ArrayRef;
1471 assert_eq!(&expected, &b);
1472 }
1473
1474 #[test]
1475 fn test_temporal_array_time64_nanoseconds() {
1476 let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1478
1479 let actual = date_part(&input, DatePart::Hour).unwrap();
1480 let actual = actual.as_primitive::<Int32Type>();
1481 assert_eq!(23, actual.value(0));
1482
1483 let actual = date_part(&input, DatePart::Minute).unwrap();
1484 let actual = actual.as_primitive::<Int32Type>();
1485 assert_eq!(32, actual.value(0));
1486
1487 let actual = date_part(&input, DatePart::Second).unwrap();
1488 let actual = actual.as_primitive::<Int32Type>();
1489 assert_eq!(50, actual.value(0));
1490
1491 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1492 let actual = actual.as_primitive::<Int32Type>();
1493 assert_eq!(123, actual.value(0));
1494
1495 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1496 let actual = actual.as_primitive::<Int32Type>();
1497 assert_eq!(123_456, actual.value(0));
1498
1499 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1500 let actual = actual.as_primitive::<Int32Type>();
1501 assert_eq!(123_456_789, actual.value(0));
1502
1503 let input: Time64NanosecondArray = vec![
1505 Some(-1),
1506 Some(86_400_000_000_000),
1507 Some(86_401_000_000_000),
1508 None,
1509 ]
1510 .into();
1511 let actual = date_part(&input, DatePart::Hour).unwrap();
1512 let actual = actual.as_primitive::<Int32Type>();
1513 let expected: Int32Array = vec![None, None, None, None].into();
1514 assert_eq!(&expected, actual);
1515 }
1516
1517 #[test]
1518 fn test_temporal_array_time64_microseconds() {
1519 let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1521
1522 let actual = date_part(&input, DatePart::Hour).unwrap();
1523 let actual = actual.as_primitive::<Int32Type>();
1524 assert_eq!(23, actual.value(0));
1525
1526 let actual = date_part(&input, DatePart::Minute).unwrap();
1527 let actual = actual.as_primitive::<Int32Type>();
1528 assert_eq!(32, actual.value(0));
1529
1530 let actual = date_part(&input, DatePart::Second).unwrap();
1531 let actual = actual.as_primitive::<Int32Type>();
1532 assert_eq!(50, actual.value(0));
1533
1534 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1535 let actual = actual.as_primitive::<Int32Type>();
1536 assert_eq!(123, actual.value(0));
1537
1538 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1539 let actual = actual.as_primitive::<Int32Type>();
1540 assert_eq!(123_456, actual.value(0));
1541
1542 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1543 let actual = actual.as_primitive::<Int32Type>();
1544 assert_eq!(123_456_000, actual.value(0));
1545
1546 let input: Time64MicrosecondArray =
1548 vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1549 let actual = date_part(&input, DatePart::Hour).unwrap();
1550 let actual = actual.as_primitive::<Int32Type>();
1551 let expected: Int32Array = vec![None, None, None, None].into();
1552 assert_eq!(&expected, actual);
1553 }
1554
1555 #[test]
1556 fn test_temporal_array_time32_milliseconds() {
1557 let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1559
1560 let actual = date_part(&input, DatePart::Hour).unwrap();
1561 let actual = actual.as_primitive::<Int32Type>();
1562 assert_eq!(23, actual.value(0));
1563
1564 let actual = date_part(&input, DatePart::Minute).unwrap();
1565 let actual = actual.as_primitive::<Int32Type>();
1566 assert_eq!(32, actual.value(0));
1567
1568 let actual = date_part(&input, DatePart::Second).unwrap();
1569 let actual = actual.as_primitive::<Int32Type>();
1570 assert_eq!(50, actual.value(0));
1571
1572 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1573 let actual = actual.as_primitive::<Int32Type>();
1574 assert_eq!(123, actual.value(0));
1575
1576 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1577 let actual = actual.as_primitive::<Int32Type>();
1578 assert_eq!(123_000, actual.value(0));
1579
1580 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1581 let actual = actual.as_primitive::<Int32Type>();
1582 assert_eq!(123_000_000, actual.value(0));
1583
1584 let input: Time32MillisecondArray =
1586 vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1587 let actual = date_part(&input, DatePart::Hour).unwrap();
1588 let actual = actual.as_primitive::<Int32Type>();
1589 let expected: Int32Array = vec![None, None, None, None].into();
1590 assert_eq!(&expected, actual);
1591 }
1592
1593 #[test]
1594 fn test_temporal_array_time32_seconds() {
1595 let input: Time32SecondArray = vec![84_770].into();
1597
1598 let actual = date_part(&input, DatePart::Hour).unwrap();
1599 let actual = actual.as_primitive::<Int32Type>();
1600 assert_eq!(23, actual.value(0));
1601
1602 let actual = date_part(&input, DatePart::Minute).unwrap();
1603 let actual = actual.as_primitive::<Int32Type>();
1604 assert_eq!(32, actual.value(0));
1605
1606 let actual = date_part(&input, DatePart::Second).unwrap();
1607 let actual = actual.as_primitive::<Int32Type>();
1608 assert_eq!(50, actual.value(0));
1609
1610 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1611 let actual = actual.as_primitive::<Int32Type>();
1612 assert_eq!(0, actual.value(0));
1613
1614 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1615 let actual = actual.as_primitive::<Int32Type>();
1616 assert_eq!(0, actual.value(0));
1617
1618 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1619 let actual = actual.as_primitive::<Int32Type>();
1620 assert_eq!(0, actual.value(0));
1621
1622 let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1624 let actual = date_part(&input, DatePart::Hour).unwrap();
1625 let actual = actual.as_primitive::<Int32Type>();
1626 let expected: Int32Array = vec![None, None, None, None].into();
1627 assert_eq!(&expected, actual);
1628 }
1629
1630 #[test]
1631 fn test_temporal_array_time_invalid_parts() {
1632 fn ensure_returns_error(array: &dyn Array) {
1633 let invalid_parts = [
1634 DatePart::Quarter,
1635 DatePart::Year,
1636 DatePart::YearISO,
1637 DatePart::Month,
1638 DatePart::Week,
1639 DatePart::WeekISO,
1640 DatePart::Day,
1641 DatePart::DayOfWeekSunday0,
1642 DatePart::DayOfWeekMonday0,
1643 DatePart::DayOfWeekSunday1,
1644 DatePart::DayOfWeekMonday1,
1645 DatePart::DayOfYear,
1646 ];
1647
1648 for part in invalid_parts {
1649 let err = date_part(array, part).unwrap_err();
1650 let expected = format!(
1651 "Compute error: {part} does not support: {}",
1652 array.data_type()
1653 );
1654 assert_eq!(expected, err.to_string());
1655 }
1656 }
1657
1658 ensure_returns_error(&Time32SecondArray::from(vec![0]));
1659 ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1660 ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1661 ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1662 }
1663
1664 #[test]
1665 fn test_interval_year_month_array() {
1666 let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1667
1668 let actual = date_part(&input, DatePart::Year).unwrap();
1669 let actual = actual.as_primitive::<Int32Type>();
1670 assert_eq!(0, actual.value(0));
1671 assert_eq!(0, actual.value(1));
1672 assert_eq!(2, actual.value(2));
1673
1674 let actual = date_part(&input, DatePart::Month).unwrap();
1675 let actual = actual.as_primitive::<Int32Type>();
1676 assert_eq!(0, actual.value(0));
1677 assert_eq!(5, actual.value(1));
1678 assert_eq!(0, actual.value(2));
1679
1680 assert!(date_part(&input, DatePart::Day).is_err());
1681 assert!(date_part(&input, DatePart::Week).is_err());
1682 }
1683
1684 #[test]
1687 fn test_interval_day_time_array() {
1688 let input: IntervalDayTimeArray = vec![
1689 IntervalDayTime::ZERO,
1690 IntervalDayTime::new(10, 42), IntervalDayTime::new(10, 1042), IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1), IntervalDayTime::new(
1694 6,
1695 (MILLISECONDS * 60 * 60 * 4 + MILLISECONDS * 60 * 22 + MILLISECONDS * 11 + 3)
1696 as i32,
1697 ), ]
1699 .into();
1700
1701 let actual = date_part(&input, DatePart::Day).unwrap();
1703 let actual = actual.as_primitive::<Int32Type>();
1704 assert_eq!(0, actual.value(0));
1705 assert_eq!(10, actual.value(1));
1706 assert_eq!(10, actual.value(2));
1707 assert_eq!(10, actual.value(3));
1708 assert_eq!(6, actual.value(4));
1709
1710 let actual = date_part(&input, DatePart::Week).unwrap();
1711 let actual = actual.as_primitive::<Int32Type>();
1712 assert_eq!(0, actual.value(0));
1713 assert_eq!(1, actual.value(1));
1714 assert_eq!(1, actual.value(2));
1715 assert_eq!(1, actual.value(3));
1716 assert_eq!(0, actual.value(4));
1717
1718 let actual = date_part(&input, DatePart::Hour).unwrap();
1720 let actual = actual.as_primitive::<Int32Type>();
1721 assert_eq!(0, actual.value(0));
1722 assert_eq!(0, actual.value(1));
1723 assert_eq!(0, actual.value(2));
1724 assert_eq!(24, actual.value(3));
1725 assert_eq!(4, actual.value(4));
1726
1727 let actual = date_part(&input, DatePart::Minute).unwrap();
1728 let actual = actual.as_primitive::<Int32Type>();
1729 assert_eq!(0, actual.value(0));
1730 assert_eq!(0, actual.value(1));
1731 assert_eq!(0, actual.value(2));
1732 assert_eq!(0, actual.value(3));
1733 assert_eq!(22, actual.value(4));
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!(1, actual.value(2));
1740 assert_eq!(0, actual.value(3));
1741 assert_eq!(11, actual.value(4));
1742
1743 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1744 let actual = actual.as_primitive::<Int32Type>();
1745 assert_eq!(0, actual.value(0));
1746 assert_eq!(42, actual.value(1));
1747 assert_eq!(1042, actual.value(2));
1748 assert_eq!(1, actual.value(3));
1749 assert_eq!(11003, actual.value(4));
1750
1751 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1752 let actual = actual.as_primitive::<Int32Type>();
1753 assert_eq!(0, actual.value(0));
1754 assert_eq!(42_000, actual.value(1));
1755 assert_eq!(1_042_000, actual.value(2));
1756 assert_eq!(1_000, actual.value(3));
1757 assert_eq!(11_003_000, actual.value(4));
1758
1759 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1760 let actual = actual.as_primitive::<Int32Type>();
1761 assert_eq!(0, actual.value(0));
1762 assert_eq!(42_000_000, actual.value(1));
1763 assert_eq!(1_042_000_000, actual.value(2));
1764 assert_eq!(1_000_000, actual.value(3));
1765 assert_eq!(0, actual.value(4));
1767
1768 assert!(date_part(&input, DatePart::Month).is_err());
1770 assert!(date_part(&input, DatePart::Year).is_err());
1771 }
1772
1773 #[test]
1776 fn test_interval_month_day_nano_array() {
1777 let input: IntervalMonthDayNanoArray = vec![
1778 IntervalMonthDayNano::ZERO,
1779 IntervalMonthDayNano::new(5, 10, 42), IntervalMonthDayNano::new(16, 35, NANOSECONDS_IN_DAY + 1), IntervalMonthDayNano::new(
1782 0,
1783 0,
1784 NANOSECONDS * 60 * 60 * 4
1785 + NANOSECONDS * 60 * 22
1786 + NANOSECONDS * 11
1787 + 1_000_000 * 33
1788 + 1_000 * 44
1789 + 5,
1790 ), ]
1792 .into();
1793
1794 let actual = date_part(&input, DatePart::Year).unwrap();
1796 let actual = actual.as_primitive::<Int32Type>();
1797 assert_eq!(0, actual.value(0));
1798 assert_eq!(0, actual.value(1));
1799 assert_eq!(1, actual.value(2));
1800 assert_eq!(0, actual.value(3));
1801
1802 let actual = date_part(&input, DatePart::Month).unwrap();
1803 let actual = actual.as_primitive::<Int32Type>();
1804 assert_eq!(0, actual.value(0));
1805 assert_eq!(5, actual.value(1));
1806 assert_eq!(4, actual.value(2));
1807 assert_eq!(0, actual.value(3));
1808
1809 let actual = date_part(&input, DatePart::Week).unwrap();
1811 let actual = actual.as_primitive::<Int32Type>();
1812 assert_eq!(0, actual.value(0));
1813 assert_eq!(1, actual.value(1));
1814 assert_eq!(5, actual.value(2));
1815 assert_eq!(0, actual.value(3));
1816
1817 let actual = date_part(&input, DatePart::Day).unwrap();
1818 let actual = actual.as_primitive::<Int32Type>();
1819 assert_eq!(0, actual.value(0));
1820 assert_eq!(10, actual.value(1));
1821 assert_eq!(35, actual.value(2));
1822 assert_eq!(0, actual.value(3));
1823
1824 let actual = date_part(&input, DatePart::Hour).unwrap();
1826 let actual = actual.as_primitive::<Int32Type>();
1827 assert_eq!(0, actual.value(0));
1828 assert_eq!(0, actual.value(1));
1829 assert_eq!(24, actual.value(2));
1830 assert_eq!(4, actual.value(3));
1831
1832 let actual = date_part(&input, DatePart::Minute).unwrap();
1833 let actual = actual.as_primitive::<Int32Type>();
1834 assert_eq!(0, actual.value(0));
1835 assert_eq!(0, actual.value(1));
1836 assert_eq!(0, actual.value(2));
1837 assert_eq!(22, actual.value(3));
1838
1839 let actual = date_part(&input, DatePart::Second).unwrap();
1840 let actual = actual.as_primitive::<Int32Type>();
1841 assert_eq!(0, actual.value(0));
1842 assert_eq!(0, actual.value(1));
1843 assert_eq!(0, actual.value(2));
1844 assert_eq!(11, actual.value(3));
1845
1846 let actual = date_part(&input, DatePart::Millisecond).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!(0, actual.value(2));
1851 assert_eq!(11_033, actual.value(3));
1852
1853 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1854 let actual = actual.as_primitive::<Int32Type>();
1855 assert_eq!(0, actual.value(0));
1856 assert_eq!(0, actual.value(1));
1857 assert_eq!(0, actual.value(2));
1858 assert_eq!(11_033_044, actual.value(3));
1859
1860 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1861 let actual = actual.as_primitive::<Int32Type>();
1862 assert_eq!(0, actual.value(0));
1863 assert_eq!(42, actual.value(1));
1864 assert_eq!(1, actual.value(2));
1865 assert_eq!(0, actual.value(3));
1867 }
1868
1869 #[test]
1870 fn test_interval_array_invalid_parts() {
1871 fn ensure_returns_error(array: &dyn Array) {
1872 let invalid_parts = [
1873 DatePart::Quarter,
1874 DatePart::YearISO,
1875 DatePart::WeekISO,
1876 DatePart::DayOfWeekSunday0,
1877 DatePart::DayOfWeekMonday0,
1878 DatePart::DayOfWeekSunday1,
1879 DatePart::DayOfWeekMonday1,
1880 DatePart::DayOfYear,
1881 ];
1882
1883 for part in invalid_parts {
1884 let err = date_part(array, part).unwrap_err();
1885 let expected = format!(
1886 "Compute error: {part} does not support: {}",
1887 array.data_type()
1888 );
1889 assert_eq!(expected, err.to_string());
1890 }
1891 }
1892
1893 ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
1894 ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
1895 ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
1896 IntervalMonthDayNano::ZERO,
1897 ]));
1898 }
1899
1900 #[test]
1901 fn test_duration_second() {
1902 let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1903
1904 let actual = date_part(&input, DatePart::Second).unwrap();
1905 let actual = actual.as_primitive::<Int32Type>();
1906 assert_eq!(0, actual.value(0));
1907 assert_eq!(42, actual.value(1));
1908 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1909
1910 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1911 let actual = actual.as_primitive::<Int32Type>();
1912 assert_eq!(0, actual.value(0));
1913 assert_eq!(42_000, actual.value(1));
1914 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1915
1916 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1917 let actual = actual.as_primitive::<Int32Type>();
1918 assert_eq!(0, actual.value(0));
1919 assert_eq!(42_000_000, actual.value(1));
1920 assert_eq!(0, actual.value(2));
1921
1922 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1923 let actual = actual.as_primitive::<Int32Type>();
1924 assert_eq!(0, actual.value(0));
1925 assert_eq!(0, actual.value(1));
1926 assert_eq!(0, actual.value(2));
1927 }
1928
1929 #[test]
1930 fn test_duration_millisecond() {
1931 let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1932
1933 let actual = date_part(&input, DatePart::Second).unwrap();
1934 let actual = actual.as_primitive::<Int32Type>();
1935 assert_eq!(0, actual.value(0));
1936 assert_eq!(0, actual.value(1));
1937 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1938
1939 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1940 let actual = actual.as_primitive::<Int32Type>();
1941 assert_eq!(0, actual.value(0));
1942 assert_eq!(42, actual.value(1));
1943 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1944
1945 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1946 let actual = actual.as_primitive::<Int32Type>();
1947 assert_eq!(0, actual.value(0));
1948 assert_eq!(42_000, actual.value(1));
1949 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1950
1951 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1952 let actual = actual.as_primitive::<Int32Type>();
1953 assert_eq!(0, actual.value(0));
1954 assert_eq!(42_000_000, actual.value(1));
1955 assert_eq!(0, actual.value(2));
1956 }
1957
1958 #[test]
1959 fn test_duration_microsecond() {
1960 let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1961
1962 let actual = date_part(&input, DatePart::Second).unwrap();
1963 let actual = actual.as_primitive::<Int32Type>();
1964 assert_eq!(0, actual.value(0));
1965 assert_eq!(0, actual.value(1));
1966 assert_eq!(0, actual.value(2));
1967
1968 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1969 let actual = actual.as_primitive::<Int32Type>();
1970 assert_eq!(0, actual.value(0));
1971 assert_eq!(0, actual.value(1));
1972 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1973
1974 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1975 let actual = actual.as_primitive::<Int32Type>();
1976 assert_eq!(0, actual.value(0));
1977 assert_eq!(42, actual.value(1));
1978 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1979
1980 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1981 let actual = actual.as_primitive::<Int32Type>();
1982 assert_eq!(0, actual.value(0));
1983 assert_eq!(42_000, actual.value(1));
1984 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1985 }
1986
1987 #[test]
1988 fn test_duration_nanosecond() {
1989 let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1990
1991 let actual = date_part(&input, DatePart::Second).unwrap();
1992 let actual = actual.as_primitive::<Int32Type>();
1993 assert_eq!(0, actual.value(0));
1994 assert_eq!(0, actual.value(1));
1995 assert_eq!(0, actual.value(2));
1996
1997 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1998 let actual = actual.as_primitive::<Int32Type>();
1999 assert_eq!(0, actual.value(0));
2000 assert_eq!(0, actual.value(1));
2001 assert_eq!(0, actual.value(2));
2002
2003 let actual = date_part(&input, DatePart::Microsecond).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!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2008
2009 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2010 let actual = actual.as_primitive::<Int32Type>();
2011 assert_eq!(0, actual.value(0));
2012 assert_eq!(42, actual.value(1));
2013 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2014 }
2015
2016 #[test]
2017 fn test_duration_invalid_parts() {
2018 fn ensure_returns_error(array: &dyn Array) {
2019 let invalid_parts = [
2020 DatePart::Year,
2021 DatePart::YearISO,
2022 DatePart::Quarter,
2023 DatePart::Month,
2024 DatePart::WeekISO,
2025 DatePart::DayOfWeekSunday0,
2026 DatePart::DayOfWeekMonday0,
2027 DatePart::DayOfWeekSunday1,
2028 DatePart::DayOfWeekMonday1,
2029 DatePart::DayOfYear,
2030 ];
2031
2032 for part in invalid_parts {
2033 let err = date_part(array, part).unwrap_err();
2034 let expected = format!(
2035 "Compute error: {part} does not support: {}",
2036 array.data_type()
2037 );
2038 assert_eq!(expected, err.to_string());
2039 }
2040 }
2041
2042 ensure_returns_error(&DurationSecondArray::from(vec![0]));
2043 ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
2044 ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
2045 ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
2046 }
2047
2048 const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
2049 const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
2050 const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
2051 const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
2052 #[test]
2054 fn test_temporal_array_date64_week_iso() {
2055 let a: PrimitiveArray<Date64Type> = vec![
2056 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2057 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2058 ]
2059 .into();
2060
2061 let b = date_part(&a, DatePart::WeekISO).unwrap();
2062 let actual = b.as_primitive::<Int32Type>();
2063 assert_eq!(1, actual.value(0));
2064 assert_eq!(8, actual.value(1));
2065 }
2066
2067 #[test]
2068 fn test_temporal_array_date64_year_iso() {
2069 let a: PrimitiveArray<Date64Type> = vec![
2070 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2071 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2072 ]
2073 .into();
2074
2075 let b = date_part(&a, DatePart::YearISO).unwrap();
2076 let actual = b.as_primitive::<Int32Type>();
2077 assert_eq!(2018, actual.value(0));
2078 assert_eq!(2019, actual.value(1));
2079 }
2080
2081 #[test]
2082 fn test_temporal_array_timestamp_week_iso() {
2083 let a = TimestampSecondArray::from(vec![
2084 TIMESTAMP_SECOND_1970_01_01, SECONDS_IN_DAY * 4, SECONDS_IN_DAY * 4 - 1, ]);
2088 let b = date_part(&a, DatePart::WeekISO).unwrap();
2089 let actual = b.as_primitive::<Int32Type>();
2090 assert_eq!(1, actual.value(0));
2091 assert_eq!(2, actual.value(1));
2092 assert_eq!(1, actual.value(2));
2093 }
2094
2095 #[test]
2096 fn test_temporal_array_timestamp_year_iso() {
2097 let a = TimestampSecondArray::from(vec![
2098 TIMESTAMP_SECOND_1970_01_01,
2099 SECONDS_IN_DAY * 4,
2100 SECONDS_IN_DAY * 4 - 1,
2101 ]);
2102 let b = date_part(&a, DatePart::YearISO).unwrap();
2103 let actual = b.as_primitive::<Int32Type>();
2104 assert_eq!(1970, actual.value(0));
2105 assert_eq!(1970, actual.value(1));
2106 assert_eq!(1970, actual.value(2));
2107 }
2108
2109 const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
2110 const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
2111 #[test]
2115 fn test_temporal_array_date64_week_iso_edge_cases() {
2116 let a: PrimitiveArray<Date64Type> = vec![
2117 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2118 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2119 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2120 ]
2121 .into();
2122
2123 let b = date_part(&a, DatePart::WeekISO).unwrap();
2124 let actual = b.as_primitive::<Int32Type>();
2125 assert_eq!(53, actual.value(0));
2126 assert_eq!(53, actual.value(1));
2127 assert_eq!(1, actual.value(2));
2128 }
2129
2130 #[test]
2131 fn test_temporal_array_date64_year_iso_edge_cases() {
2132 let a: PrimitiveArray<Date64Type> = vec![
2133 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2134 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2135 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2136 ]
2137 .into();
2138
2139 let b = date_part(&a, DatePart::YearISO).unwrap();
2140 let actual = b.as_primitive::<Int32Type>();
2141 assert_eq!(2015, actual.value(0));
2142 assert_eq!(2015, actual.value(1));
2143 assert_eq!(2016, actual.value(2));
2144 }
2145
2146 #[test]
2147 fn test_temporal_array_timestamp_week_iso_edge_cases() {
2148 let a = TimestampSecondArray::from(vec![
2149 TIMESTAMP_SECOND_2015_12_28,
2150 TIMESTAMP_SECOND_2016_01_03,
2151 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2152 ]);
2153 let b = date_part(&a, DatePart::WeekISO).unwrap();
2154 let actual = b.as_primitive::<Int32Type>();
2155 assert_eq!(53, actual.value(0));
2156 assert_eq!(53, actual.value(1));
2157 assert_eq!(1, actual.value(2));
2158 }
2159
2160 #[test]
2161 fn test_temporal_array_timestamp_year_iso_edge_cases() {
2162 let a = TimestampSecondArray::from(vec![
2163 TIMESTAMP_SECOND_2015_12_28,
2164 TIMESTAMP_SECOND_2016_01_03,
2165 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2166 ]);
2167 let b = date_part(&a, DatePart::YearISO).unwrap();
2168 let actual = b.as_primitive::<Int32Type>();
2169 assert_eq!(2015, actual.value(0));
2170 assert_eq!(2015, actual.value(1));
2171 assert_eq!(2016, actual.value(2));
2172 }
2173
2174 #[test]
2175 fn test_ree_timestamp_year() {
2176 let vals: TimestampSecondArray =
2177 vec![Some(1514764800), Some(1550636625), Some(1550636625)].into();
2178 let run_ends = Int32Array::from(vec![1, 2, 3]);
2179 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2180
2181 let b = date_part(&ree, DatePart::Year).unwrap();
2182 let ree_result = b.as_run_opt::<Int32Type>().unwrap();
2183 let values = ree_result.values().as_primitive::<Int32Type>();
2184 assert_eq!(2018, values.value(0));
2185 assert_eq!(2019, values.value(1));
2186 assert_eq!(2019, values.value(2));
2187 }
2188
2189 #[test]
2190 fn test_ree_date64_month() {
2191 let vals: PrimitiveArray<Date64Type> =
2192 vec![Some(1514764800000), Some(1550636625000)].into();
2193 let run_ends = Int64Array::from(vec![2, 4]);
2194 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2195
2196 let b = date_part(&ree, DatePart::Month).unwrap();
2197 let ree_result = b.as_run_opt::<Int64Type>().unwrap();
2198 let values = ree_result.values().as_primitive::<Int32Type>();
2199 assert_eq!(1, values.value(0));
2200 assert_eq!(2, values.value(1));
2201 }
2202
2203 #[test]
2204 fn test_date_part_from_str() {
2205 let cases = [
2206 ("y", DatePart::Year),
2207 ("yr", DatePart::Year),
2208 ("year", DatePart::Year),
2209 ("years", DatePart::Year),
2210 ("YEAR", DatePart::Year),
2211 ("isoyear", DatePart::YearISO),
2212 ("qtr", DatePart::Quarter),
2213 ("quarter", DatePart::Quarter),
2214 ("quarters", DatePart::Quarter),
2215 ("mon", DatePart::Month),
2216 ("mons", DatePart::Month),
2217 ("month", DatePart::Month),
2218 ("MONTHS", DatePart::Month),
2219 ("w", DatePart::Week),
2220 ("week", DatePart::Week),
2221 ("isoweek", DatePart::WeekISO),
2222 ("d", DatePart::Day),
2223 ("day", DatePart::Day),
2224 ("dow", DatePart::DayOfWeekSunday0),
2225 ("DayOfWeek", DatePart::DayOfWeekSunday0),
2226 ("dow1", DatePart::DayOfWeekSunday1),
2227 ("dayofweek1", DatePart::DayOfWeekSunday1),
2228 ("DAYOFWEEK1", DatePart::DayOfWeekSunday1),
2229 ("isodow", DatePart::DayOfWeekMonday1),
2230 ("ISODOW", DatePart::DayOfWeekMonday1),
2231 ("doy", DatePart::DayOfYear),
2232 ("DayOfYear", DatePart::DayOfYear),
2233 ("h", DatePart::Hour),
2234 ("hr", DatePart::Hour),
2235 ("hour", DatePart::Hour),
2236 ("m", DatePart::Minute),
2240 ("min", DatePart::Minute),
2241 ("mins", DatePart::Minute),
2242 ("minute", DatePart::Minute),
2243 ("s", DatePart::Second),
2244 ("sec", DatePart::Second),
2245 ("second", DatePart::Second),
2246 ("ms", DatePart::Millisecond),
2247 ("msec", DatePart::Millisecond),
2248 ("mseconds", DatePart::Millisecond),
2249 ("millisecond", DatePart::Millisecond),
2250 ("us", DatePart::Microsecond),
2251 ("usec", DatePart::Microsecond),
2252 ("useconds", DatePart::Microsecond),
2253 ("microsecond", DatePart::Microsecond),
2254 ("nanosecond", DatePart::Nanosecond),
2255 ("nanoseconds", DatePart::Nanosecond),
2256 ];
2257 for (input, expected) in cases {
2258 assert_eq!(
2259 DatePart::from_str(input).unwrap(),
2260 expected,
2261 "parsing {input}"
2262 );
2263 }
2264 }
2265
2266 #[test]
2267 fn test_date_part_from_str_unknown() {
2268 let unknown = [
2270 "epoch",
2271 "century",
2272 "decade",
2273 "millennium",
2274 "timezone",
2275 "timezone_hour",
2276 "timezone_minute",
2277 " year ",
2280 "year ",
2281 "",
2282 "nope",
2283 ];
2284 for s in unknown {
2285 let err = DatePart::from_str(s).unwrap_err();
2286 assert!(
2287 matches!(err, ArrowError::InvalidArgumentError(_)),
2288 "expected InvalidArgumentError for {s:?}, got: {err}"
2289 );
2290 }
2291 }
2292}