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 => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
603 DatePart::Microsecond => {
604 Ok(self.unary_opt(|d| d.checked_mul(1_000_000)?.try_into().ok()))
605 }
606 DatePart::Nanosecond => {
607 Ok(self.unary_opt(|d| d.checked_mul(1_000_000_000)?.try_into().ok()))
608 }
609
610 DatePart::Year
611 | DatePart::YearISO
612 | DatePart::WeekISO
613 | DatePart::Quarter
614 | DatePart::Month
615 | DatePart::DayOfWeekSunday0
616 | DatePart::DayOfWeekMonday0
617 | DatePart::DayOfWeekSunday1
618 | DatePart::DayOfWeekMonday1
619 | DatePart::DayOfYear => {
620 return_compute_error_with!(format!("{part} does not support"), self.data_type())
621 }
622 }
623 }
624}
625
626impl ExtractDatePartExt for PrimitiveArray<DurationMillisecondType> {
627 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
628 match part {
629 DatePart::Week => {
630 Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24 * 7)).try_into().ok()))
631 }
632 DatePart::Day => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24)).try_into().ok())),
633 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60)).try_into().ok())),
634 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000 * 60)).try_into().ok())),
635 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
636 DatePart::Millisecond => Ok(self.unary_opt(|d| d.try_into().ok())),
637 DatePart::Microsecond => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
638 DatePart::Nanosecond => {
639 Ok(self.unary_opt(|d| d.checked_mul(1_000_000)?.try_into().ok()))
640 }
641
642 DatePart::Year
643 | DatePart::YearISO
644 | DatePart::WeekISO
645 | DatePart::Quarter
646 | DatePart::Month
647 | DatePart::DayOfWeekSunday0
648 | DatePart::DayOfWeekMonday0
649 | DatePart::DayOfWeekSunday1
650 | DatePart::DayOfWeekMonday1
651 | DatePart::DayOfYear => {
652 return_compute_error_with!(format!("{part} does not support"), self.data_type())
653 }
654 }
655 }
656}
657
658impl ExtractDatePartExt for PrimitiveArray<DurationMicrosecondType> {
659 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
660 match part {
661 DatePart::Week => {
662 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
663 }
664 DatePart::Day => {
665 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24)).try_into().ok()))
666 }
667 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60)).try_into().ok())),
668 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000 * 60)).try_into().ok())),
669 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
670 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
671 DatePart::Microsecond => Ok(self.unary_opt(|d| d.try_into().ok())),
672 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.checked_mul(1_000)?.try_into().ok())),
673
674 DatePart::Year
675 | DatePart::YearISO
676 | DatePart::WeekISO
677 | DatePart::Quarter
678 | DatePart::Month
679 | DatePart::DayOfWeekSunday0
680 | DatePart::DayOfWeekMonday0
681 | DatePart::DayOfWeekSunday1
682 | DatePart::DayOfWeekMonday1
683 | DatePart::DayOfYear => {
684 return_compute_error_with!(format!("{part} does not support"), self.data_type())
685 }
686 }
687 }
688}
689
690impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
691 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
692 match part {
693 DatePart::Week => {
694 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
695 }
696 DatePart::Day => {
697 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24)).try_into().ok()))
698 }
699 DatePart::Hour => {
700 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60)).try_into().ok()))
701 }
702 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60)).try_into().ok())),
703 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000_000).try_into().ok())),
704 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
705 DatePart::Microsecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
706 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.try_into().ok())),
707
708 DatePart::Year
709 | DatePart::YearISO
710 | DatePart::WeekISO
711 | DatePart::Quarter
712 | DatePart::Month
713 | DatePart::DayOfWeekSunday0
714 | DatePart::DayOfWeekMonday0
715 | DatePart::DayOfWeekSunday1
716 | DatePart::DayOfWeekMonday1
717 | DatePart::DayOfYear => {
718 return_compute_error_with!(format!("{part} does not support"), self.data_type())
719 }
720 }
721 }
722}
723
724macro_rules! return_compute_error_with {
725 ($msg:expr, $param:expr) => {
726 return { Err(ArrowError::ComputeError(format!("{}: {}", $msg, $param))) }
727 };
728}
729
730pub(crate) use return_compute_error_with;
731
732trait ChronoDateExt {
734 fn num_days_from_monday(&self) -> i32;
736
737 fn num_days_from_sunday(&self) -> i32;
739}
740
741impl<T: Datelike> ChronoDateExt for T {
742 fn num_days_from_monday(&self) -> i32 {
743 self.weekday().num_days_from_monday() as i32
744 }
745
746 fn num_days_from_sunday(&self) -> i32 {
747 self.weekday().num_days_from_sunday() as i32
748 }
749}
750
751#[cfg(test)]
752mod tests {
753 use super::*;
754
755 fn date_part_primitive<T: ArrowTemporalType>(
758 array: &PrimitiveArray<T>,
759 part: DatePart,
760 ) -> Result<Int32Array, ArrowError> {
761 let array = date_part(array, part)?;
762 Ok(array.as_primitive::<Int32Type>().to_owned())
763 }
764
765 #[test]
766 fn test_temporal_array_date64_hour() {
767 let a: PrimitiveArray<Date64Type> =
768 vec![Some(1514764800000), None, Some(1550636625000)].into();
769
770 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
771 assert_eq!(0, b.value(0));
772 assert!(!b.is_valid(1));
773 assert_eq!(4, b.value(2));
774 }
775
776 #[test]
777 fn test_temporal_array_date32_hour() {
778 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
779
780 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
781 assert_eq!(0, b.value(0));
782 assert!(!b.is_valid(1));
783 assert_eq!(0, b.value(2));
784 }
785
786 #[test]
787 fn test_temporal_array_time32_second_hour() {
788 let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
789
790 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
791 assert_eq!(10, b.value(0));
792 assert_eq!(23, b.value(1));
793 }
794
795 #[test]
796 fn test_temporal_array_time64_micro_hour() {
797 let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
798
799 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
800 assert_eq!(10, b.value(0));
801 assert_eq!(23, b.value(1));
802 }
803
804 #[test]
805 fn test_temporal_array_timestamp_micro_hour() {
806 let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
807
808 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
809 assert_eq!(10, b.value(0));
810 assert_eq!(23, b.value(1));
811 }
812
813 #[test]
814 fn test_temporal_array_date64_year() {
815 let a: PrimitiveArray<Date64Type> =
816 vec![Some(1514764800000), None, Some(1550636625000)].into();
817
818 let b = date_part_primitive(&a, DatePart::Year).unwrap();
819 assert_eq!(2018, b.value(0));
820 assert!(!b.is_valid(1));
821 assert_eq!(2019, b.value(2));
822 }
823
824 #[test]
825 fn test_temporal_array_date32_year() {
826 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
827
828 let b = date_part_primitive(&a, DatePart::Year).unwrap();
829 assert_eq!(2011, b.value(0));
830 assert!(!b.is_valid(1));
831 assert_eq!(2012, b.value(2));
832 }
833
834 #[test]
835 fn test_temporal_array_date64_quarter() {
836 let a: PrimitiveArray<Date64Type> =
839 vec![Some(1514764800000), None, Some(1566275025000)].into();
840
841 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
842 assert_eq!(1, b.value(0));
843 assert!(!b.is_valid(1));
844 assert_eq!(3, b.value(2));
845 }
846
847 #[test]
848 fn test_temporal_array_date32_quarter() {
849 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
850
851 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
852 assert_eq!(1, b.value(0));
853 assert!(!b.is_valid(1));
854 assert_eq!(4, b.value(2));
855 }
856
857 #[test]
858 fn test_temporal_array_timestamp_quarter_with_timezone() {
859 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
861 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
862 assert_eq!(2, b.value(0));
863 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
864 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
865 assert_eq!(1, b.value(0));
866 }
867
868 #[test]
869 fn test_all_quarters_date64() {
870 let a: PrimitiveArray<Date64Type> = vec![
876 Some(1767225600000),
877 Some(1775001600000),
878 Some(1782864000000),
879 Some(1790812800000),
880 None,
881 ]
882 .into();
883
884 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
885 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));
890 }
891
892 #[test]
893 fn test_all_quarters_date32() {
894 let a: PrimitiveArray<Date32Type> =
900 vec![Some(20454), Some(20544), Some(20635), Some(20727), None].into();
901
902 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
903 assert_eq!(1, b.value(0));
904 assert_eq!(2, b.value(1));
905 assert_eq!(3, b.value(2));
906 assert_eq!(4, b.value(3));
907 assert!(!b.is_valid(4));
908 }
909
910 #[test]
911 fn test_quarter_timestamp_microsecond() {
912 let a: TimestampMicrosecondArray =
916 vec![Some(1767225600000000), None, Some(1782864000000000)].into();
917
918 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
919 assert_eq!(1, b.value(0));
920 assert!(!b.is_valid(1));
921 assert_eq!(3, b.value(2));
922 }
923
924 #[test]
925 fn test_quarter_timestamp_nanosecond() {
926 let a: TimestampNanosecondArray =
930 vec![Some(1775001600000000000), None, Some(1790812800000000000)].into();
931
932 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
933 assert_eq!(2, b.value(0));
934 assert!(!b.is_valid(1));
935 assert_eq!(4, b.value(2));
936 }
937
938 #[test]
939 fn test_temporal_array_date64_month() {
940 let a: PrimitiveArray<Date64Type> =
943 vec![Some(1514764800000), None, Some(1550636625000)].into();
944
945 let b = date_part_primitive(&a, DatePart::Month).unwrap();
946 assert_eq!(1, b.value(0));
947 assert!(!b.is_valid(1));
948 assert_eq!(2, b.value(2));
949 }
950
951 #[test]
952 fn test_temporal_array_date32_month() {
953 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
954
955 let b = date_part_primitive(&a, DatePart::Month).unwrap();
956 assert_eq!(1, b.value(0));
957 assert!(!b.is_valid(1));
958 assert_eq!(2, b.value(2));
959 }
960
961 #[test]
962 fn test_temporal_array_timestamp_month_with_timezone() {
963 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
965 let b = date_part_primitive(&a, DatePart::Month).unwrap();
966 assert_eq!(2, b.value(0));
967 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
968 let b = date_part_primitive(&a, DatePart::Month).unwrap();
969 assert_eq!(1, b.value(0));
970 }
971
972 #[test]
973 fn test_temporal_array_timestamp_day_with_timezone() {
974 let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
976 let b = date_part_primitive(&a, DatePart::Day).unwrap();
977 assert_eq!(2, b.value(0));
978 let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
979 let b = date_part_primitive(&a, DatePart::Day).unwrap();
980 assert_eq!(1, b.value(0));
981 }
982
983 #[test]
984 fn test_temporal_array_date64_weekday() {
985 let a: PrimitiveArray<Date64Type> =
988 vec![Some(1514764800000), None, Some(1550636625000)].into();
989
990 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday0).unwrap();
991 assert_eq!(0, b.value(0));
992 assert!(!b.is_valid(1));
993 assert_eq!(2, b.value(2));
994 }
995
996 #[test]
997 fn test_temporal_array_date64_dayofweek1() {
998 let a: PrimitiveArray<Date64Type> = vec![
1002 Some(1514764800000),
1003 None,
1004 Some(1550636625000),
1005 Some(1483228800000),
1006 ]
1007 .into();
1008
1009 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday1).unwrap();
1010 assert_eq!(2, b.value(0));
1011 assert!(!b.is_valid(1));
1012 assert_eq!(4, b.value(2));
1013 assert_eq!(1, b.value(3));
1014 }
1015
1016 #[test]
1017 fn test_temporal_array_date64_isodow() {
1018 let a: PrimitiveArray<Date64Type> = vec![
1022 Some(1514764800000),
1023 None,
1024 Some(1550636625000),
1025 Some(1483228800000),
1026 ]
1027 .into();
1028
1029 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday1).unwrap();
1030 assert_eq!(1, b.value(0));
1031 assert!(!b.is_valid(1));
1032 assert_eq!(3, b.value(2));
1033 assert_eq!(7, b.value(3));
1034 }
1035
1036 #[test]
1037 fn test_temporal_array_date64_weekday0() {
1038 let a: PrimitiveArray<Date64Type> = vec![
1042 Some(1483228800000),
1043 None,
1044 Some(1514764800000),
1045 Some(1550636625000),
1046 ]
1047 .into();
1048
1049 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday0).unwrap();
1050 assert_eq!(0, b.value(0));
1051 assert!(!b.is_valid(1));
1052 assert_eq!(1, b.value(2));
1053 assert_eq!(3, b.value(3));
1054 }
1055
1056 #[test]
1057 fn test_temporal_array_date64_day() {
1058 let a: PrimitiveArray<Date64Type> =
1061 vec![Some(1514764800000), None, Some(1550636625000)].into();
1062
1063 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1064 assert_eq!(1, b.value(0));
1065 assert!(!b.is_valid(1));
1066 assert_eq!(20, b.value(2));
1067 }
1068
1069 #[test]
1070 fn test_temporal_array_date32_day() {
1071 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
1072
1073 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1074 assert_eq!(1, b.value(0));
1075 assert!(!b.is_valid(1));
1076 assert_eq!(1, b.value(2));
1077 }
1078
1079 #[test]
1080 fn test_temporal_array_date64_doy() {
1081 let a: PrimitiveArray<Date64Type> = vec![
1085 Some(1483228800000),
1086 Some(1514764800000),
1087 None,
1088 Some(1550636625000),
1089 ]
1090 .into();
1091
1092 let b = date_part_primitive(&a, DatePart::DayOfYear).unwrap();
1093 assert_eq!(1, b.value(0));
1094 assert_eq!(1, b.value(1));
1095 assert!(!b.is_valid(2));
1096 assert_eq!(51, b.value(3));
1097 }
1098
1099 #[test]
1100 fn test_temporal_array_timestamp_micro_year() {
1101 let a: TimestampMicrosecondArray =
1102 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1103
1104 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1105 assert_eq!(2021, b.value(0));
1106 assert!(!b.is_valid(1));
1107 assert_eq!(2024, b.value(2));
1108 }
1109
1110 #[test]
1111 fn test_temporal_array_date64_minute() {
1112 let a: PrimitiveArray<Date64Type> =
1113 vec![Some(1514764800000), None, Some(1550636625000)].into();
1114
1115 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1116 assert_eq!(0, b.value(0));
1117 assert!(!b.is_valid(1));
1118 assert_eq!(23, b.value(2));
1119 }
1120
1121 #[test]
1122 fn test_temporal_array_timestamp_micro_minute() {
1123 let a: TimestampMicrosecondArray =
1124 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1125
1126 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1127 assert_eq!(57, b.value(0));
1128 assert!(!b.is_valid(1));
1129 assert_eq!(44, b.value(2));
1130 }
1131
1132 #[test]
1133 fn test_temporal_array_date32_week() {
1134 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
1135
1136 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1137 assert_eq!(1, b.value(0));
1138 assert!(!b.is_valid(1));
1139 assert_eq!(2, b.value(2));
1140 }
1141
1142 #[test]
1143 fn test_temporal_array_date64_week() {
1144 let a: PrimitiveArray<Date64Type> = vec![
1147 Some(1646116175000),
1148 None,
1149 Some(1641171600000),
1150 Some(1640998800000),
1151 ]
1152 .into();
1153
1154 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1155 assert_eq!(9, b.value(0));
1156 assert!(!b.is_valid(1));
1157 assert_eq!(1, b.value(2));
1158 assert_eq!(52, b.value(3));
1159 }
1160
1161 #[test]
1162 fn test_temporal_array_timestamp_micro_week() {
1163 let a: TimestampMicrosecondArray =
1166 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1167
1168 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1169 assert_eq!(4, b.value(0));
1170 assert!(!b.is_valid(1));
1171 assert_eq!(30, b.value(2));
1172 }
1173
1174 #[test]
1175 fn test_temporal_array_date64_second() {
1176 let a: PrimitiveArray<Date64Type> =
1177 vec![Some(1514764800000), None, Some(1550636625000)].into();
1178
1179 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1180 assert_eq!(0, b.value(0));
1181 assert!(!b.is_valid(1));
1182 assert_eq!(45, b.value(2));
1183 }
1184
1185 #[test]
1186 fn test_temporal_array_timestamp_micro_second() {
1187 let a: TimestampMicrosecondArray =
1188 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1189
1190 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1191 assert_eq!(27, b.value(0));
1192 assert!(!b.is_valid(1));
1193 assert_eq!(7, b.value(2));
1194 }
1195
1196 #[test]
1197 fn test_temporal_array_timestamp_second_with_timezone() {
1198 let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1199 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1200 assert_eq!(10, b.value(0));
1201 assert_eq!(20, b.value(1));
1202 }
1203
1204 #[test]
1205 fn test_temporal_array_timestamp_minute_with_timezone() {
1206 let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1207 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1208 assert_eq!(50, b.value(0));
1209 assert_eq!(51, b.value(1));
1210 }
1211
1212 #[test]
1213 fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1214 let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1215 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1216 assert_eq!(5, b.value(0));
1217 }
1218
1219 #[test]
1220 fn test_temporal_array_timestamp_hour_with_timezone() {
1221 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1222 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1223 assert_eq!(11, b.value(0));
1224 }
1225
1226 #[test]
1227 fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1228 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1229 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1230 assert_eq!(11, b.value(0));
1231 }
1232
1233 #[test]
1234 fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1235 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1236 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1237 assert_eq!(11, b.value(0));
1238 }
1239
1240 #[test]
1241 fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1242 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1243 let err = date_part_primitive(&a, DatePart::Hour)
1244 .unwrap_err()
1245 .to_string();
1246 assert!(err.contains("Invalid timezone"), "{}", err);
1247 }
1248
1249 #[test]
1250 fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1251 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1252 let err = date_part_primitive(&a, DatePart::Hour)
1253 .unwrap_err()
1254 .to_string();
1255 assert!(err.contains("Invalid timezone"), "{}", err);
1256 }
1257
1258 #[test]
1259 fn test_temporal_array_timestamp_week_without_timezone() {
1260 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1264 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1265 assert_eq!(1, b.value(0));
1266 assert_eq!(2, b.value(1));
1267 assert_eq!(1, b.value(2));
1268 }
1269
1270 #[test]
1271 fn test_temporal_array_timestamp_week_with_timezone() {
1272 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1276 .with_timezone("+01:00".to_string());
1277 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1278 assert_eq!(1, b.value(0));
1279 assert_eq!(2, b.value(1));
1280 assert_eq!(2, b.value(2));
1281 }
1282
1283 #[test]
1284 fn test_hour_minute_second_dictionary_array() {
1285 let a = TimestampSecondArray::from(vec![
1286 60 * 60 * 10 + 61,
1287 60 * 60 * 20 + 122,
1288 60 * 60 * 30 + 183,
1289 ])
1290 .with_timezone("+01:00".to_string());
1291
1292 let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1293 let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1294
1295 let b = date_part(&dict, DatePart::Hour).unwrap();
1296
1297 let expected_dict =
1298 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1299 let expected = Arc::new(expected_dict) as ArrayRef;
1300 assert_eq!(&expected, &b);
1301
1302 let b = date_part(&dict, DatePart::Minute).unwrap();
1303
1304 let b_old = date_part(&dict, DatePart::Minute).unwrap();
1305
1306 let expected_dict =
1307 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1308 let expected = Arc::new(expected_dict) as ArrayRef;
1309 assert_eq!(&expected, &b);
1310 assert_eq!(&expected, &b_old);
1311
1312 let b = date_part(&dict, DatePart::Second).unwrap();
1313
1314 let b_old = date_part(&dict, DatePart::Second).unwrap();
1315
1316 let expected_dict =
1317 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1318 let expected = Arc::new(expected_dict) as ArrayRef;
1319 assert_eq!(&expected, &b);
1320 assert_eq!(&expected, &b_old);
1321
1322 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1323
1324 let expected_dict =
1325 DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1326 let expected = Arc::new(expected_dict) as ArrayRef;
1327 assert_eq!(&expected, &b);
1328 }
1329
1330 #[test]
1331 fn test_year_dictionary_array() {
1332 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1333
1334 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1335 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1336
1337 let b = date_part(&dict, DatePart::Year).unwrap();
1338
1339 let expected_dict = DictionaryArray::new(
1340 keys,
1341 Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1342 );
1343 let expected = Arc::new(expected_dict) as ArrayRef;
1344 assert_eq!(&expected, &b);
1345 }
1346
1347 #[test]
1348 fn test_quarter_month_dictionary_array() {
1349 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1352
1353 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1354 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1355
1356 let b = date_part(&dict, DatePart::Quarter).unwrap();
1357
1358 let expected =
1359 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1360 assert_eq!(b.as_ref(), &expected);
1361
1362 let b = date_part(&dict, DatePart::Month).unwrap();
1363
1364 let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1365 assert_eq!(b.as_ref(), &expected);
1366 }
1367
1368 #[test]
1369 fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1370 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1373
1374 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1375 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1376
1377 let b = date_part(&dict, DatePart::DayOfWeekMonday0).unwrap();
1378
1379 let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1380 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1381 assert_eq!(b.as_ref(), &expected);
1382
1383 let b = date_part(&dict, DatePart::DayOfWeekSunday0).unwrap();
1384
1385 let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), 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::Day).unwrap();
1390
1391 let a = Int32Array::from(vec![Some(1), Some(20), Some(20), 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::DayOfYear).unwrap();
1396
1397 let a = Int32Array::from(vec![Some(1), Some(51), Some(51), 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::Week).unwrap();
1402
1403 let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1404 let expected = DictionaryArray::new(keys, Arc::new(a));
1405 assert_eq!(b.as_ref(), &expected);
1406 }
1407
1408 #[test]
1409 fn test_temporal_array_date64_nanosecond() {
1410 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1417
1418 let b = date_part_primitive(&a, DatePart::Nanosecond).unwrap();
1419 assert!(!b.is_valid(0));
1420 assert_eq!(453_000_000, b.value(1));
1421
1422 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1423 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1424 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1425
1426 let a = Int32Array::from(vec![None, Some(453_000_000)]);
1427 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1428 let expected = Arc::new(expected_dict) as ArrayRef;
1429 assert_eq!(&expected, &b);
1430 }
1431
1432 #[test]
1433 fn test_temporal_array_date64_microsecond() {
1434 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1435
1436 let b = date_part_primitive(&a, DatePart::Microsecond).unwrap();
1437 assert!(!b.is_valid(0));
1438 assert_eq!(453_000, b.value(1));
1439
1440 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1441 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1442 let b = date_part(&dict, DatePart::Microsecond).unwrap();
1443
1444 let a = Int32Array::from(vec![None, Some(453_000)]);
1445 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1446 let expected = Arc::new(expected_dict) as ArrayRef;
1447 assert_eq!(&expected, &b);
1448 }
1449
1450 #[test]
1451 fn test_temporal_array_date64_millisecond() {
1452 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1453
1454 let b = date_part_primitive(&a, DatePart::Millisecond).unwrap();
1455 assert!(!b.is_valid(0));
1456 assert_eq!(453, b.value(1));
1457
1458 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1459 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1460 let b = date_part(&dict, DatePart::Millisecond).unwrap();
1461
1462 let a = Int32Array::from(vec![None, Some(453)]);
1463 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1464 let expected = Arc::new(expected_dict) as ArrayRef;
1465 assert_eq!(&expected, &b);
1466 }
1467
1468 #[test]
1469 fn test_temporal_array_time64_nanoseconds() {
1470 let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1472
1473 let actual = date_part(&input, DatePart::Hour).unwrap();
1474 let actual = actual.as_primitive::<Int32Type>();
1475 assert_eq!(23, actual.value(0));
1476
1477 let actual = date_part(&input, DatePart::Minute).unwrap();
1478 let actual = actual.as_primitive::<Int32Type>();
1479 assert_eq!(32, actual.value(0));
1480
1481 let actual = date_part(&input, DatePart::Second).unwrap();
1482 let actual = actual.as_primitive::<Int32Type>();
1483 assert_eq!(50, actual.value(0));
1484
1485 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1486 let actual = actual.as_primitive::<Int32Type>();
1487 assert_eq!(123, actual.value(0));
1488
1489 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1490 let actual = actual.as_primitive::<Int32Type>();
1491 assert_eq!(123_456, actual.value(0));
1492
1493 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1494 let actual = actual.as_primitive::<Int32Type>();
1495 assert_eq!(123_456_789, actual.value(0));
1496
1497 let input: Time64NanosecondArray = vec![
1499 Some(-1),
1500 Some(86_400_000_000_000),
1501 Some(86_401_000_000_000),
1502 None,
1503 ]
1504 .into();
1505 let actual = date_part(&input, DatePart::Hour).unwrap();
1506 let actual = actual.as_primitive::<Int32Type>();
1507 let expected: Int32Array = vec![None, None, None, None].into();
1508 assert_eq!(&expected, actual);
1509 }
1510
1511 #[test]
1512 fn test_temporal_array_time64_microseconds() {
1513 let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1515
1516 let actual = date_part(&input, DatePart::Hour).unwrap();
1517 let actual = actual.as_primitive::<Int32Type>();
1518 assert_eq!(23, actual.value(0));
1519
1520 let actual = date_part(&input, DatePart::Minute).unwrap();
1521 let actual = actual.as_primitive::<Int32Type>();
1522 assert_eq!(32, actual.value(0));
1523
1524 let actual = date_part(&input, DatePart::Second).unwrap();
1525 let actual = actual.as_primitive::<Int32Type>();
1526 assert_eq!(50, actual.value(0));
1527
1528 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1529 let actual = actual.as_primitive::<Int32Type>();
1530 assert_eq!(123, actual.value(0));
1531
1532 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1533 let actual = actual.as_primitive::<Int32Type>();
1534 assert_eq!(123_456, actual.value(0));
1535
1536 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1537 let actual = actual.as_primitive::<Int32Type>();
1538 assert_eq!(123_456_000, actual.value(0));
1539
1540 let input: Time64MicrosecondArray =
1542 vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1543 let actual = date_part(&input, DatePart::Hour).unwrap();
1544 let actual = actual.as_primitive::<Int32Type>();
1545 let expected: Int32Array = vec![None, None, None, None].into();
1546 assert_eq!(&expected, actual);
1547 }
1548
1549 #[test]
1550 fn test_temporal_array_time32_milliseconds() {
1551 let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1553
1554 let actual = date_part(&input, DatePart::Hour).unwrap();
1555 let actual = actual.as_primitive::<Int32Type>();
1556 assert_eq!(23, actual.value(0));
1557
1558 let actual = date_part(&input, DatePart::Minute).unwrap();
1559 let actual = actual.as_primitive::<Int32Type>();
1560 assert_eq!(32, actual.value(0));
1561
1562 let actual = date_part(&input, DatePart::Second).unwrap();
1563 let actual = actual.as_primitive::<Int32Type>();
1564 assert_eq!(50, actual.value(0));
1565
1566 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1567 let actual = actual.as_primitive::<Int32Type>();
1568 assert_eq!(123, actual.value(0));
1569
1570 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1571 let actual = actual.as_primitive::<Int32Type>();
1572 assert_eq!(123_000, actual.value(0));
1573
1574 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1575 let actual = actual.as_primitive::<Int32Type>();
1576 assert_eq!(123_000_000, actual.value(0));
1577
1578 let input: Time32MillisecondArray =
1580 vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1581 let actual = date_part(&input, DatePart::Hour).unwrap();
1582 let actual = actual.as_primitive::<Int32Type>();
1583 let expected: Int32Array = vec![None, None, None, None].into();
1584 assert_eq!(&expected, actual);
1585 }
1586
1587 #[test]
1588 fn test_temporal_array_time32_seconds() {
1589 let input: Time32SecondArray = vec![84_770].into();
1591
1592 let actual = date_part(&input, DatePart::Hour).unwrap();
1593 let actual = actual.as_primitive::<Int32Type>();
1594 assert_eq!(23, actual.value(0));
1595
1596 let actual = date_part(&input, DatePart::Minute).unwrap();
1597 let actual = actual.as_primitive::<Int32Type>();
1598 assert_eq!(32, actual.value(0));
1599
1600 let actual = date_part(&input, DatePart::Second).unwrap();
1601 let actual = actual.as_primitive::<Int32Type>();
1602 assert_eq!(50, actual.value(0));
1603
1604 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1605 let actual = actual.as_primitive::<Int32Type>();
1606 assert_eq!(0, actual.value(0));
1607
1608 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1609 let actual = actual.as_primitive::<Int32Type>();
1610 assert_eq!(0, actual.value(0));
1611
1612 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1613 let actual = actual.as_primitive::<Int32Type>();
1614 assert_eq!(0, actual.value(0));
1615
1616 let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1618 let actual = date_part(&input, DatePart::Hour).unwrap();
1619 let actual = actual.as_primitive::<Int32Type>();
1620 let expected: Int32Array = vec![None, None, None, None].into();
1621 assert_eq!(&expected, actual);
1622 }
1623
1624 #[test]
1625 fn test_temporal_array_time_invalid_parts() {
1626 fn ensure_returns_error(array: &dyn Array) {
1627 let invalid_parts = [
1628 DatePart::Quarter,
1629 DatePart::Year,
1630 DatePart::YearISO,
1631 DatePart::Month,
1632 DatePart::Week,
1633 DatePart::WeekISO,
1634 DatePart::Day,
1635 DatePart::DayOfWeekSunday0,
1636 DatePart::DayOfWeekMonday0,
1637 DatePart::DayOfWeekSunday1,
1638 DatePart::DayOfWeekMonday1,
1639 DatePart::DayOfYear,
1640 ];
1641
1642 for part in invalid_parts {
1643 let err = date_part(array, part).unwrap_err();
1644 let expected = format!(
1645 "Compute error: {part} does not support: {}",
1646 array.data_type()
1647 );
1648 assert_eq!(expected, err.to_string());
1649 }
1650 }
1651
1652 ensure_returns_error(&Time32SecondArray::from(vec![0]));
1653 ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1654 ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1655 ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1656 }
1657
1658 #[test]
1659 fn test_interval_year_month_array() {
1660 let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1661
1662 let actual = date_part(&input, DatePart::Year).unwrap();
1663 let actual = actual.as_primitive::<Int32Type>();
1664 assert_eq!(0, actual.value(0));
1665 assert_eq!(0, actual.value(1));
1666 assert_eq!(2, actual.value(2));
1667
1668 let actual = date_part(&input, DatePart::Month).unwrap();
1669 let actual = actual.as_primitive::<Int32Type>();
1670 assert_eq!(0, actual.value(0));
1671 assert_eq!(5, actual.value(1));
1672 assert_eq!(0, actual.value(2));
1673
1674 assert!(date_part(&input, DatePart::Day).is_err());
1675 assert!(date_part(&input, DatePart::Week).is_err());
1676 }
1677
1678 #[test]
1681 fn test_interval_day_time_array() {
1682 let input: IntervalDayTimeArray = vec![
1683 IntervalDayTime::ZERO,
1684 IntervalDayTime::new(10, 42), IntervalDayTime::new(10, 1042), IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1), IntervalDayTime::new(
1688 6,
1689 (MILLISECONDS * 60 * 60 * 4 + MILLISECONDS * 60 * 22 + MILLISECONDS * 11 + 3)
1690 as i32,
1691 ), ]
1693 .into();
1694
1695 let actual = date_part(&input, DatePart::Day).unwrap();
1697 let actual = actual.as_primitive::<Int32Type>();
1698 assert_eq!(0, actual.value(0));
1699 assert_eq!(10, actual.value(1));
1700 assert_eq!(10, actual.value(2));
1701 assert_eq!(10, actual.value(3));
1702 assert_eq!(6, actual.value(4));
1703
1704 let actual = date_part(&input, DatePart::Week).unwrap();
1705 let actual = actual.as_primitive::<Int32Type>();
1706 assert_eq!(0, actual.value(0));
1707 assert_eq!(1, actual.value(1));
1708 assert_eq!(1, actual.value(2));
1709 assert_eq!(1, actual.value(3));
1710 assert_eq!(0, actual.value(4));
1711
1712 let actual = date_part(&input, DatePart::Hour).unwrap();
1714 let actual = actual.as_primitive::<Int32Type>();
1715 assert_eq!(0, actual.value(0));
1716 assert_eq!(0, actual.value(1));
1717 assert_eq!(0, actual.value(2));
1718 assert_eq!(24, actual.value(3));
1719 assert_eq!(4, actual.value(4));
1720
1721 let actual = date_part(&input, DatePart::Minute).unwrap();
1722 let actual = actual.as_primitive::<Int32Type>();
1723 assert_eq!(0, actual.value(0));
1724 assert_eq!(0, actual.value(1));
1725 assert_eq!(0, actual.value(2));
1726 assert_eq!(0, actual.value(3));
1727 assert_eq!(22, actual.value(4));
1728
1729 let actual = date_part(&input, DatePart::Second).unwrap();
1730 let actual = actual.as_primitive::<Int32Type>();
1731 assert_eq!(0, actual.value(0));
1732 assert_eq!(0, actual.value(1));
1733 assert_eq!(1, actual.value(2));
1734 assert_eq!(0, actual.value(3));
1735 assert_eq!(11, actual.value(4));
1736
1737 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1738 let actual = actual.as_primitive::<Int32Type>();
1739 assert_eq!(0, actual.value(0));
1740 assert_eq!(42, actual.value(1));
1741 assert_eq!(1042, actual.value(2));
1742 assert_eq!(1, actual.value(3));
1743 assert_eq!(11003, actual.value(4));
1744
1745 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1746 let actual = actual.as_primitive::<Int32Type>();
1747 assert_eq!(0, actual.value(0));
1748 assert_eq!(42_000, actual.value(1));
1749 assert_eq!(1_042_000, actual.value(2));
1750 assert_eq!(1_000, actual.value(3));
1751 assert_eq!(11_003_000, actual.value(4));
1752
1753 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1754 let actual = actual.as_primitive::<Int32Type>();
1755 assert_eq!(0, actual.value(0));
1756 assert_eq!(42_000_000, actual.value(1));
1757 assert_eq!(1_042_000_000, actual.value(2));
1758 assert_eq!(1_000_000, actual.value(3));
1759 assert_eq!(0, actual.value(4));
1761
1762 assert!(date_part(&input, DatePart::Month).is_err());
1764 assert!(date_part(&input, DatePart::Year).is_err());
1765 }
1766
1767 #[test]
1770 fn test_interval_month_day_nano_array() {
1771 let input: IntervalMonthDayNanoArray = vec![
1772 IntervalMonthDayNano::ZERO,
1773 IntervalMonthDayNano::new(5, 10, 42), IntervalMonthDayNano::new(16, 35, NANOSECONDS_IN_DAY + 1), IntervalMonthDayNano::new(
1776 0,
1777 0,
1778 NANOSECONDS * 60 * 60 * 4
1779 + NANOSECONDS * 60 * 22
1780 + NANOSECONDS * 11
1781 + 1_000_000 * 33
1782 + 1_000 * 44
1783 + 5,
1784 ), ]
1786 .into();
1787
1788 let actual = date_part(&input, DatePart::Year).unwrap();
1790 let actual = actual.as_primitive::<Int32Type>();
1791 assert_eq!(0, actual.value(0));
1792 assert_eq!(0, actual.value(1));
1793 assert_eq!(1, actual.value(2));
1794 assert_eq!(0, actual.value(3));
1795
1796 let actual = date_part(&input, DatePart::Month).unwrap();
1797 let actual = actual.as_primitive::<Int32Type>();
1798 assert_eq!(0, actual.value(0));
1799 assert_eq!(5, actual.value(1));
1800 assert_eq!(4, actual.value(2));
1801 assert_eq!(0, actual.value(3));
1802
1803 let actual = date_part(&input, DatePart::Week).unwrap();
1805 let actual = actual.as_primitive::<Int32Type>();
1806 assert_eq!(0, actual.value(0));
1807 assert_eq!(1, actual.value(1));
1808 assert_eq!(5, actual.value(2));
1809 assert_eq!(0, actual.value(3));
1810
1811 let actual = date_part(&input, DatePart::Day).unwrap();
1812 let actual = actual.as_primitive::<Int32Type>();
1813 assert_eq!(0, actual.value(0));
1814 assert_eq!(10, actual.value(1));
1815 assert_eq!(35, actual.value(2));
1816 assert_eq!(0, actual.value(3));
1817
1818 let actual = date_part(&input, DatePart::Hour).unwrap();
1820 let actual = actual.as_primitive::<Int32Type>();
1821 assert_eq!(0, actual.value(0));
1822 assert_eq!(0, actual.value(1));
1823 assert_eq!(24, actual.value(2));
1824 assert_eq!(4, actual.value(3));
1825
1826 let actual = date_part(&input, DatePart::Minute).unwrap();
1827 let actual = actual.as_primitive::<Int32Type>();
1828 assert_eq!(0, actual.value(0));
1829 assert_eq!(0, actual.value(1));
1830 assert_eq!(0, actual.value(2));
1831 assert_eq!(22, actual.value(3));
1832
1833 let actual = date_part(&input, DatePart::Second).unwrap();
1834 let actual = actual.as_primitive::<Int32Type>();
1835 assert_eq!(0, actual.value(0));
1836 assert_eq!(0, actual.value(1));
1837 assert_eq!(0, actual.value(2));
1838 assert_eq!(11, actual.value(3));
1839
1840 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1841 let actual = actual.as_primitive::<Int32Type>();
1842 assert_eq!(0, actual.value(0));
1843 assert_eq!(0, actual.value(1));
1844 assert_eq!(0, actual.value(2));
1845 assert_eq!(11_033, actual.value(3));
1846
1847 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1848 let actual = actual.as_primitive::<Int32Type>();
1849 assert_eq!(0, actual.value(0));
1850 assert_eq!(0, actual.value(1));
1851 assert_eq!(0, actual.value(2));
1852 assert_eq!(11_033_044, actual.value(3));
1853
1854 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1855 let actual = actual.as_primitive::<Int32Type>();
1856 assert_eq!(0, actual.value(0));
1857 assert_eq!(42, actual.value(1));
1858 assert_eq!(1, actual.value(2));
1859 assert_eq!(0, actual.value(3));
1861 }
1862
1863 #[test]
1864 fn test_interval_array_invalid_parts() {
1865 fn ensure_returns_error(array: &dyn Array) {
1866 let invalid_parts = [
1867 DatePart::Quarter,
1868 DatePart::YearISO,
1869 DatePart::WeekISO,
1870 DatePart::DayOfWeekSunday0,
1871 DatePart::DayOfWeekMonday0,
1872 DatePart::DayOfWeekSunday1,
1873 DatePart::DayOfWeekMonday1,
1874 DatePart::DayOfYear,
1875 ];
1876
1877 for part in invalid_parts {
1878 let err = date_part(array, part).unwrap_err();
1879 let expected = format!(
1880 "Compute error: {part} does not support: {}",
1881 array.data_type()
1882 );
1883 assert_eq!(expected, err.to_string());
1884 }
1885 }
1886
1887 ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
1888 ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
1889 ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
1890 IntervalMonthDayNano::ZERO,
1891 ]));
1892 }
1893
1894 #[test]
1895 fn test_duration_second() {
1896 let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1897
1898 let actual = date_part(&input, DatePart::Second).unwrap();
1899 let actual = actual.as_primitive::<Int32Type>();
1900 assert_eq!(0, actual.value(0));
1901 assert_eq!(42, actual.value(1));
1902 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1903
1904 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1905 let actual = actual.as_primitive::<Int32Type>();
1906 assert_eq!(0, actual.value(0));
1907 assert_eq!(42_000, actual.value(1));
1908 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1909
1910 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1911 let actual = actual.as_primitive::<Int32Type>();
1912 assert_eq!(0, actual.value(0));
1913 assert_eq!(42_000_000, actual.value(1));
1914 assert_eq!(0, actual.value(2));
1915
1916 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1917 let actual = actual.as_primitive::<Int32Type>();
1918 assert_eq!(0, actual.value(0));
1919 assert_eq!(0, actual.value(1));
1920 assert_eq!(0, actual.value(2));
1921 }
1922
1923 #[test]
1924 fn test_duration_millisecond() {
1925 let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1926
1927 let actual = date_part(&input, DatePart::Second).unwrap();
1928 let actual = actual.as_primitive::<Int32Type>();
1929 assert_eq!(0, actual.value(0));
1930 assert_eq!(0, actual.value(1));
1931 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1932
1933 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1934 let actual = actual.as_primitive::<Int32Type>();
1935 assert_eq!(0, actual.value(0));
1936 assert_eq!(42, actual.value(1));
1937 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1938
1939 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1940 let actual = actual.as_primitive::<Int32Type>();
1941 assert_eq!(0, actual.value(0));
1942 assert_eq!(42_000, actual.value(1));
1943 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1944
1945 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1946 let actual = actual.as_primitive::<Int32Type>();
1947 assert_eq!(0, actual.value(0));
1948 assert_eq!(42_000_000, actual.value(1));
1949 assert_eq!(0, actual.value(2));
1950 }
1951
1952 #[test]
1953 fn test_duration_microsecond() {
1954 let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1955
1956 let actual = date_part(&input, DatePart::Second).unwrap();
1957 let actual = actual.as_primitive::<Int32Type>();
1958 assert_eq!(0, actual.value(0));
1959 assert_eq!(0, actual.value(1));
1960 assert_eq!(0, actual.value(2));
1961
1962 let actual = date_part(&input, DatePart::Millisecond).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!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1967
1968 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1969 let actual = actual.as_primitive::<Int32Type>();
1970 assert_eq!(0, actual.value(0));
1971 assert_eq!(42, actual.value(1));
1972 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1973
1974 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1975 let actual = actual.as_primitive::<Int32Type>();
1976 assert_eq!(0, actual.value(0));
1977 assert_eq!(42_000, actual.value(1));
1978 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1979 }
1980
1981 #[test]
1982 fn test_duration_nanosecond() {
1983 let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1984
1985 let actual = date_part(&input, DatePart::Second).unwrap();
1986 let actual = actual.as_primitive::<Int32Type>();
1987 assert_eq!(0, actual.value(0));
1988 assert_eq!(0, actual.value(1));
1989 assert_eq!(0, actual.value(2));
1990
1991 let actual = date_part(&input, DatePart::Millisecond).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::Microsecond).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!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
2002
2003 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
2004 let actual = actual.as_primitive::<Int32Type>();
2005 assert_eq!(0, actual.value(0));
2006 assert_eq!(42, actual.value(1));
2007 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
2008 }
2009
2010 #[test]
2011 fn test_duration_invalid_parts() {
2012 fn ensure_returns_error(array: &dyn Array) {
2013 let invalid_parts = [
2014 DatePart::Year,
2015 DatePart::YearISO,
2016 DatePart::Quarter,
2017 DatePart::Month,
2018 DatePart::WeekISO,
2019 DatePart::DayOfWeekSunday0,
2020 DatePart::DayOfWeekMonday0,
2021 DatePart::DayOfWeekSunday1,
2022 DatePart::DayOfWeekMonday1,
2023 DatePart::DayOfYear,
2024 ];
2025
2026 for part in invalid_parts {
2027 let err = date_part(array, part).unwrap_err();
2028 let expected = format!(
2029 "Compute error: {part} does not support: {}",
2030 array.data_type()
2031 );
2032 assert_eq!(expected, err.to_string());
2033 }
2034 }
2035
2036 ensure_returns_error(&DurationSecondArray::from(vec![0]));
2037 ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
2038 ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
2039 ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
2040 }
2041
2042 const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
2043 const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
2044 const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
2045 const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
2046 #[test]
2048 fn test_temporal_array_date64_week_iso() {
2049 let a: PrimitiveArray<Date64Type> = vec![
2050 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2051 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2052 ]
2053 .into();
2054
2055 let b = date_part(&a, DatePart::WeekISO).unwrap();
2056 let actual = b.as_primitive::<Int32Type>();
2057 assert_eq!(1, actual.value(0));
2058 assert_eq!(8, actual.value(1));
2059 }
2060
2061 #[test]
2062 fn test_temporal_array_date64_year_iso() {
2063 let a: PrimitiveArray<Date64Type> = vec![
2064 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2065 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2066 ]
2067 .into();
2068
2069 let b = date_part(&a, DatePart::YearISO).unwrap();
2070 let actual = b.as_primitive::<Int32Type>();
2071 assert_eq!(2018, actual.value(0));
2072 assert_eq!(2019, actual.value(1));
2073 }
2074
2075 #[test]
2076 fn test_temporal_array_timestamp_week_iso() {
2077 let a = TimestampSecondArray::from(vec![
2078 TIMESTAMP_SECOND_1970_01_01, SECONDS_IN_DAY * 4, SECONDS_IN_DAY * 4 - 1, ]);
2082 let b = date_part(&a, DatePart::WeekISO).unwrap();
2083 let actual = b.as_primitive::<Int32Type>();
2084 assert_eq!(1, actual.value(0));
2085 assert_eq!(2, actual.value(1));
2086 assert_eq!(1, actual.value(2));
2087 }
2088
2089 #[test]
2090 fn test_temporal_array_timestamp_year_iso() {
2091 let a = TimestampSecondArray::from(vec![
2092 TIMESTAMP_SECOND_1970_01_01,
2093 SECONDS_IN_DAY * 4,
2094 SECONDS_IN_DAY * 4 - 1,
2095 ]);
2096 let b = date_part(&a, DatePart::YearISO).unwrap();
2097 let actual = b.as_primitive::<Int32Type>();
2098 assert_eq!(1970, actual.value(0));
2099 assert_eq!(1970, actual.value(1));
2100 assert_eq!(1970, actual.value(2));
2101 }
2102
2103 const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
2104 const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
2105 #[test]
2109 fn test_temporal_array_date64_week_iso_edge_cases() {
2110 let a: PrimitiveArray<Date64Type> = vec![
2111 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2112 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2113 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2114 ]
2115 .into();
2116
2117 let b = date_part(&a, DatePart::WeekISO).unwrap();
2118 let actual = b.as_primitive::<Int32Type>();
2119 assert_eq!(53, actual.value(0));
2120 assert_eq!(53, actual.value(1));
2121 assert_eq!(1, actual.value(2));
2122 }
2123
2124 #[test]
2125 fn test_temporal_array_date64_year_iso_edge_cases() {
2126 let a: PrimitiveArray<Date64Type> = vec![
2127 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2128 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2129 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2130 ]
2131 .into();
2132
2133 let b = date_part(&a, DatePart::YearISO).unwrap();
2134 let actual = b.as_primitive::<Int32Type>();
2135 assert_eq!(2015, actual.value(0));
2136 assert_eq!(2015, actual.value(1));
2137 assert_eq!(2016, actual.value(2));
2138 }
2139
2140 #[test]
2141 fn test_temporal_array_timestamp_week_iso_edge_cases() {
2142 let a = TimestampSecondArray::from(vec![
2143 TIMESTAMP_SECOND_2015_12_28,
2144 TIMESTAMP_SECOND_2016_01_03,
2145 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2146 ]);
2147 let b = date_part(&a, DatePart::WeekISO).unwrap();
2148 let actual = b.as_primitive::<Int32Type>();
2149 assert_eq!(53, actual.value(0));
2150 assert_eq!(53, actual.value(1));
2151 assert_eq!(1, actual.value(2));
2152 }
2153
2154 #[test]
2155 fn test_temporal_array_timestamp_year_iso_edge_cases() {
2156 let a = TimestampSecondArray::from(vec![
2157 TIMESTAMP_SECOND_2015_12_28,
2158 TIMESTAMP_SECOND_2016_01_03,
2159 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2160 ]);
2161 let b = date_part(&a, DatePart::YearISO).unwrap();
2162 let actual = b.as_primitive::<Int32Type>();
2163 assert_eq!(2015, actual.value(0));
2164 assert_eq!(2015, actual.value(1));
2165 assert_eq!(2016, actual.value(2));
2166 }
2167
2168 #[test]
2169 fn test_ree_timestamp_year() {
2170 let vals: TimestampSecondArray =
2171 vec![Some(1514764800), Some(1550636625), Some(1550636625)].into();
2172 let run_ends = Int32Array::from(vec![1, 2, 3]);
2173 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2174
2175 let b = date_part(&ree, DatePart::Year).unwrap();
2176 let ree_result = b.as_run_opt::<Int32Type>().unwrap();
2177 let values = ree_result.values().as_primitive::<Int32Type>();
2178 assert_eq!(2018, values.value(0));
2179 assert_eq!(2019, values.value(1));
2180 assert_eq!(2019, values.value(2));
2181 }
2182
2183 #[test]
2184 fn test_ree_date64_month() {
2185 let vals: PrimitiveArray<Date64Type> =
2186 vec![Some(1514764800000), Some(1550636625000)].into();
2187 let run_ends = Int64Array::from(vec![2, 4]);
2188 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2189
2190 let b = date_part(&ree, DatePart::Month).unwrap();
2191 let ree_result = b.as_run_opt::<Int64Type>().unwrap();
2192 let values = ree_result.values().as_primitive::<Int32Type>();
2193 assert_eq!(1, values.value(0));
2194 assert_eq!(2, values.value(1));
2195 }
2196
2197 #[test]
2198 fn test_date_part_from_str() {
2199 let cases = [
2200 ("y", DatePart::Year),
2201 ("yr", DatePart::Year),
2202 ("year", DatePart::Year),
2203 ("years", DatePart::Year),
2204 ("YEAR", DatePart::Year),
2205 ("isoyear", DatePart::YearISO),
2206 ("qtr", DatePart::Quarter),
2207 ("quarter", DatePart::Quarter),
2208 ("quarters", DatePart::Quarter),
2209 ("mon", DatePart::Month),
2210 ("mons", DatePart::Month),
2211 ("month", DatePart::Month),
2212 ("MONTHS", DatePart::Month),
2213 ("w", DatePart::Week),
2214 ("week", DatePart::Week),
2215 ("isoweek", DatePart::WeekISO),
2216 ("d", DatePart::Day),
2217 ("day", DatePart::Day),
2218 ("dow", DatePart::DayOfWeekSunday0),
2219 ("DayOfWeek", DatePart::DayOfWeekSunday0),
2220 ("dow1", DatePart::DayOfWeekSunday1),
2221 ("dayofweek1", DatePart::DayOfWeekSunday1),
2222 ("DAYOFWEEK1", DatePart::DayOfWeekSunday1),
2223 ("isodow", DatePart::DayOfWeekMonday1),
2224 ("ISODOW", DatePart::DayOfWeekMonday1),
2225 ("doy", DatePart::DayOfYear),
2226 ("DayOfYear", DatePart::DayOfYear),
2227 ("h", DatePart::Hour),
2228 ("hr", DatePart::Hour),
2229 ("hour", DatePart::Hour),
2230 ("m", DatePart::Minute),
2234 ("min", DatePart::Minute),
2235 ("mins", DatePart::Minute),
2236 ("minute", DatePart::Minute),
2237 ("s", DatePart::Second),
2238 ("sec", DatePart::Second),
2239 ("second", DatePart::Second),
2240 ("ms", DatePart::Millisecond),
2241 ("msec", DatePart::Millisecond),
2242 ("mseconds", DatePart::Millisecond),
2243 ("millisecond", DatePart::Millisecond),
2244 ("us", DatePart::Microsecond),
2245 ("usec", DatePart::Microsecond),
2246 ("useconds", DatePart::Microsecond),
2247 ("microsecond", DatePart::Microsecond),
2248 ("nanosecond", DatePart::Nanosecond),
2249 ("nanoseconds", DatePart::Nanosecond),
2250 ];
2251 for (input, expected) in cases {
2252 assert_eq!(
2253 DatePart::from_str(input).unwrap(),
2254 expected,
2255 "parsing {input}"
2256 );
2257 }
2258 }
2259
2260 #[test]
2261 fn test_date_part_from_str_unknown() {
2262 let unknown = [
2264 "epoch",
2265 "century",
2266 "decade",
2267 "millennium",
2268 "timezone",
2269 "timezone_hour",
2270 "timezone_minute",
2271 " year ",
2274 "year ",
2275 "",
2276 "nope",
2277 ];
2278 for s in unknown {
2279 let err = DatePart::from_str(s).unwrap_err();
2280 assert!(
2281 matches!(err, ArrowError::InvalidArgumentError(_)),
2282 "expected InvalidArgumentError for {s:?}, got: {err}"
2283 );
2284 }
2285 }
2286}