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::ree_map;
28use arrow_array::temporal_conversions::{
29 MICROSECONDS, MICROSECONDS_IN_DAY, MILLISECONDS, MILLISECONDS_IN_DAY, NANOSECONDS,
30 NANOSECONDS_IN_DAY, SECONDS_IN_DAY, date32_to_datetime, date64_to_datetime,
31 timestamp_ms_to_datetime, timestamp_ns_to_datetime, timestamp_s_to_datetime,
32 timestamp_us_to_datetime,
33};
34use arrow_array::timezone::Tz;
35use arrow_array::types::*;
36use arrow_array::*;
37use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46#[non_exhaustive]
47pub enum DatePart {
48 Quarter,
50 Year,
52 YearISO,
54 Month,
56 Week,
58 WeekISO,
60 Day,
62 DayOfWeekSunday0,
64 DayOfWeekMonday0,
66 DayOfYear,
68 Hour,
70 Minute,
72 Second,
74 Millisecond,
76 Microsecond,
78 Nanosecond,
80}
81
82impl std::fmt::Display for DatePart {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 write!(f, "{self:?}")
85 }
86}
87
88impl FromStr for DatePart {
109 type Err = ArrowError;
110
111 fn from_str(s: &str) -> Result<Self, ArrowError> {
112 Ok(match s.to_lowercase().as_str() {
113 "y" | "yr" | "yrs" | "year" | "years" => Self::Year,
114 "isoyear" => Self::YearISO,
115 "qtr" | "quarter" | "quarters" => Self::Quarter,
116 "mon" | "mons" | "month" | "months" => Self::Month,
117 "w" | "week" | "weeks" => Self::Week,
118 "isoweek" => Self::WeekISO,
119 "d" | "day" | "days" => Self::Day,
120 "dow" | "dayofweek" => Self::DayOfWeekSunday0,
121 "doy" | "dayofyear" => Self::DayOfYear,
122 "h" | "hr" | "hrs" | "hour" | "hours" => Self::Hour,
123 "m" | "min" | "mins" | "minute" | "minutes" => Self::Minute,
124 "s" | "sec" | "secs" | "second" | "seconds" => Self::Second,
125 "ms" | "msec" | "msecs" | "msecond" | "mseconds" | "millisecond" | "milliseconds" => {
126 Self::Millisecond
127 }
128 "us" | "usec" | "usecs" | "usecond" | "useconds" | "microsecond" | "microseconds" => {
129 Self::Microsecond
130 }
131 "nanosecond" | "nanoseconds" => Self::Nanosecond,
132 _ => {
133 return Err(ArrowError::InvalidArgumentError(format!(
134 "Unknown date part: {s}"
135 )));
136 }
137 })
138 }
139}
140
141fn get_date_time_part_extract_fn<T>(part: DatePart) -> fn(T) -> i32
147where
148 T: ChronoDateExt + Datelike + Timelike,
149{
150 match part {
151 DatePart::Year => |d| d.year(),
152 DatePart::Quarter => |d| Datelike::quarter(&d) as i32,
155 DatePart::YearISO => |d| d.iso_week().year(),
156 DatePart::Month => |d| d.month() as i32,
157 DatePart::Week | DatePart::WeekISO => |d| d.iso_week().week() as i32,
158 DatePart::Day => |d| d.day() as i32,
159 DatePart::DayOfWeekSunday0 => |d| d.num_days_from_sunday(),
160 DatePart::DayOfWeekMonday0 => |d| d.num_days_from_monday(),
161 DatePart::DayOfYear => |d| d.ordinal() as i32,
162 DatePart::Hour => |d| d.hour() as i32,
163 DatePart::Minute => |d| d.minute() as i32,
164 DatePart::Second => |d| d.second() as i32,
165 DatePart::Millisecond => |d| (d.nanosecond() / 1_000_000) as i32,
166 DatePart::Microsecond => |d| (d.nanosecond() / 1_000) as i32,
167 DatePart::Nanosecond => |d| d.nanosecond() as i32,
168 }
169}
170
171pub fn date_part(array: &dyn Array, part: DatePart) -> Result<ArrayRef, ArrowError> {
205 downcast_temporal_array!(
206 array => {
207 let array = array.date_part(part)?;
208 let array = Arc::new(array) as ArrayRef;
209 Ok(array)
210 }
211 DataType::Interval(IntervalUnit::YearMonth) => {
212 let array = as_primitive_array::<IntervalYearMonthType>(array).date_part(part)?;
213 let array = Arc::new(array) as ArrayRef;
214 Ok(array)
215 }
216 DataType::Interval(IntervalUnit::DayTime) => {
217 let array = as_primitive_array::<IntervalDayTimeType>(array).date_part(part)?;
218 let array = Arc::new(array) as ArrayRef;
219 Ok(array)
220 }
221 DataType::Interval(IntervalUnit::MonthDayNano) => {
222 let array = as_primitive_array::<IntervalMonthDayNanoType>(array).date_part(part)?;
223 let array = Arc::new(array) as ArrayRef;
224 Ok(array)
225 }
226 DataType::Duration(TimeUnit::Second) => {
227 let array = as_primitive_array::<DurationSecondType>(array).date_part(part)?;
228 let array = Arc::new(array) as ArrayRef;
229 Ok(array)
230 }
231 DataType::Duration(TimeUnit::Millisecond) => {
232 let array = as_primitive_array::<DurationMillisecondType>(array).date_part(part)?;
233 let array = Arc::new(array) as ArrayRef;
234 Ok(array)
235 }
236 DataType::Duration(TimeUnit::Microsecond) => {
237 let array = as_primitive_array::<DurationMicrosecondType>(array).date_part(part)?;
238 let array = Arc::new(array) as ArrayRef;
239 Ok(array)
240 }
241 DataType::Duration(TimeUnit::Nanosecond) => {
242 let array = as_primitive_array::<DurationNanosecondType>(array).date_part(part)?;
243 let array = Arc::new(array) as ArrayRef;
244 Ok(array)
245 }
246 DataType::Dictionary(_, _) => {
247 let array = array.as_any_dictionary();
248 let values = date_part(array.values(), part)?;
249 let new_array = array.with_values(values);
250 Ok(new_array)
251 }
252 DataType::RunEndEncoded(k, _) => match k.data_type() {
253 DataType::Int16 => ree_map!(array, Int16Type, |a| date_part(a, part)),
254 DataType::Int32 => ree_map!(array, Int32Type, |a| date_part(a, part)),
255 DataType::Int64 => ree_map!(array, Int64Type, |a| date_part(a, part)),
256 _ => Err(ArrowError::InvalidArgumentError(format!(
257 "Invalid run-end type: {:?}",
258 k.data_type()
259 ))),
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::DayOfYear
504 | DatePart::Hour
505 | DatePart::Minute
506 | DatePart::Second
507 | DatePart::Millisecond
508 | DatePart::Microsecond
509 | DatePart::Nanosecond => {
510 return_compute_error_with!(format!("{part} does not support"), self.data_type())
511 }
512 }
513 }
514}
515
516impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> {
517 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
518 match part {
519 DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))),
520 DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))),
521 DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))),
522 DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))),
523 DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))),
524 DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))),
525 DatePart::Microsecond => {
526 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000)))
527 }
528 DatePart::Nanosecond => {
529 Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000)))
530 }
531
532 DatePart::Quarter
533 | DatePart::Year
534 | DatePart::YearISO
535 | DatePart::WeekISO
536 | DatePart::Month
537 | DatePart::DayOfWeekSunday0
538 | DatePart::DayOfWeekMonday0
539 | DatePart::DayOfYear => {
540 return_compute_error_with!(format!("{part} does not support"), self.data_type())
541 }
542 }
543 }
544}
545
546impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> {
547 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
548 match part {
549 DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))),
550 DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months % 12))),
551 DatePart::Week => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days / 7))),
552 DatePart::Day => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.days))),
553 DatePart::Hour => {
554 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 60 * 1_000_000_000)).try_into().ok()))
555 }
556 DatePart::Minute => {
557 Ok(self.unary_opt(|d| (d.nanoseconds / (60 * 1_000_000_000) % 60).try_into().ok()))
558 }
559 DatePart::Second => {
560 Ok(self.unary_opt(|d| ((d.nanoseconds / 1_000_000_000) % 60).try_into().ok()))
561 }
562 DatePart::Millisecond => Ok(self.unary_opt(|d| {
563 (d.nanoseconds % (60 * 1_000_000_000) / 1_000_000)
564 .try_into()
565 .ok()
566 })),
567 DatePart::Microsecond => Ok(self.unary_opt(|d| {
568 (d.nanoseconds % (60 * 1_000_000_000) / 1_000)
569 .try_into()
570 .ok()
571 })),
572 DatePart::Nanosecond => {
573 Ok(self.unary_opt(|d| (d.nanoseconds % (60 * 1_000_000_000)).try_into().ok()))
574 }
575
576 DatePart::Quarter
577 | DatePart::WeekISO
578 | DatePart::YearISO
579 | DatePart::DayOfWeekSunday0
580 | DatePart::DayOfWeekMonday0
581 | DatePart::DayOfYear => {
582 return_compute_error_with!(format!("{part} does not support"), self.data_type())
583 }
584 }
585 }
586}
587
588impl ExtractDatePartExt for PrimitiveArray<DurationSecondType> {
589 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
590 match part {
591 DatePart::Week => Ok(self.unary_opt(|d| (d / (60 * 60 * 24 * 7)).try_into().ok())),
592 DatePart::Day => Ok(self.unary_opt(|d| (d / (60 * 60 * 24)).try_into().ok())),
593 DatePart::Hour => Ok(self.unary_opt(|d| (d / (60 * 60)).try_into().ok())),
594 DatePart::Minute => Ok(self.unary_opt(|d| (d / 60).try_into().ok())),
595 DatePart::Second => Ok(self.unary_opt(|d| d.try_into().ok())),
596 DatePart::Millisecond => {
597 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
598 }
599 DatePart::Microsecond => {
600 Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
601 }
602 DatePart::Nanosecond => Ok(
603 self.unary_opt(|d| d.checked_mul(1_000_000_000).and_then(|d| d.try_into().ok()))
604 ),
605
606 DatePart::Year
607 | DatePart::YearISO
608 | DatePart::WeekISO
609 | DatePart::Quarter
610 | DatePart::Month
611 | DatePart::DayOfWeekSunday0
612 | DatePart::DayOfWeekMonday0
613 | DatePart::DayOfYear => {
614 return_compute_error_with!(format!("{part} does not support"), self.data_type())
615 }
616 }
617 }
618}
619
620impl ExtractDatePartExt for PrimitiveArray<DurationMillisecondType> {
621 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
622 match part {
623 DatePart::Week => {
624 Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24 * 7)).try_into().ok()))
625 }
626 DatePart::Day => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60 * 24)).try_into().ok())),
627 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000 * 60 * 60)).try_into().ok())),
628 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000 * 60)).try_into().ok())),
629 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
630 DatePart::Millisecond => Ok(self.unary_opt(|d| d.try_into().ok())),
631 DatePart::Microsecond => {
632 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
633 }
634 DatePart::Nanosecond => {
635 Ok(self.unary_opt(|d| d.checked_mul(1_000_000).and_then(|d| d.try_into().ok())))
636 }
637
638 DatePart::Year
639 | DatePart::YearISO
640 | DatePart::WeekISO
641 | DatePart::Quarter
642 | DatePart::Month
643 | DatePart::DayOfWeekSunday0
644 | DatePart::DayOfWeekMonday0
645 | DatePart::DayOfYear => {
646 return_compute_error_with!(format!("{part} does not support"), self.data_type())
647 }
648 }
649 }
650}
651
652impl ExtractDatePartExt for PrimitiveArray<DurationMicrosecondType> {
653 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
654 match part {
655 DatePart::Week => {
656 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
657 }
658 DatePart::Day => {
659 Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60 * 24)).try_into().ok()))
660 }
661 DatePart::Hour => Ok(self.unary_opt(|d| (d / (1_000_000 * 60 * 60)).try_into().ok())),
662 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000 * 60)).try_into().ok())),
663 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
664 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
665 DatePart::Microsecond => Ok(self.unary_opt(|d| d.try_into().ok())),
666 DatePart::Nanosecond => {
667 Ok(self.unary_opt(|d| d.checked_mul(1_000).and_then(|d| d.try_into().ok())))
668 }
669
670 DatePart::Year
671 | DatePart::YearISO
672 | DatePart::WeekISO
673 | DatePart::Quarter
674 | DatePart::Month
675 | DatePart::DayOfWeekSunday0
676 | DatePart::DayOfWeekMonday0
677 | DatePart::DayOfYear => {
678 return_compute_error_with!(format!("{part} does not support"), self.data_type())
679 }
680 }
681 }
682}
683
684impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
685 fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> {
686 match part {
687 DatePart::Week => {
688 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24 * 7)).try_into().ok()))
689 }
690 DatePart::Day => {
691 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60 * 24)).try_into().ok()))
692 }
693 DatePart::Hour => {
694 Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60 * 60)).try_into().ok()))
695 }
696 DatePart::Minute => Ok(self.unary_opt(|d| (d / (1_000_000_000 * 60)).try_into().ok())),
697 DatePart::Second => Ok(self.unary_opt(|d| (d / 1_000_000_000).try_into().ok())),
698 DatePart::Millisecond => Ok(self.unary_opt(|d| (d / 1_000_000).try_into().ok())),
699 DatePart::Microsecond => Ok(self.unary_opt(|d| (d / 1_000).try_into().ok())),
700 DatePart::Nanosecond => Ok(self.unary_opt(|d| d.try_into().ok())),
701
702 DatePart::Year
703 | DatePart::YearISO
704 | DatePart::WeekISO
705 | DatePart::Quarter
706 | DatePart::Month
707 | DatePart::DayOfWeekSunday0
708 | DatePart::DayOfWeekMonday0
709 | DatePart::DayOfYear => {
710 return_compute_error_with!(format!("{part} does not support"), self.data_type())
711 }
712 }
713 }
714}
715
716macro_rules! return_compute_error_with {
717 ($msg:expr, $param:expr) => {
718 return { Err(ArrowError::ComputeError(format!("{}: {}", $msg, $param))) }
719 };
720}
721
722pub(crate) use return_compute_error_with;
723
724trait ChronoDateExt {
726 fn num_days_from_monday(&self) -> i32;
728
729 fn num_days_from_sunday(&self) -> i32;
731}
732
733impl<T: Datelike> ChronoDateExt for T {
734 fn num_days_from_monday(&self) -> i32 {
735 self.weekday().num_days_from_monday() as i32
736 }
737
738 fn num_days_from_sunday(&self) -> i32 {
739 self.weekday().num_days_from_sunday() as i32
740 }
741}
742
743#[cfg(test)]
744mod tests {
745 use super::*;
746
747 fn date_part_primitive<T: ArrowTemporalType>(
750 array: &PrimitiveArray<T>,
751 part: DatePart,
752 ) -> Result<Int32Array, ArrowError> {
753 let array = date_part(array, part)?;
754 Ok(array.as_primitive::<Int32Type>().to_owned())
755 }
756
757 #[test]
758 fn test_temporal_array_date64_hour() {
759 let a: PrimitiveArray<Date64Type> =
760 vec![Some(1514764800000), None, Some(1550636625000)].into();
761
762 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
763 assert_eq!(0, b.value(0));
764 assert!(!b.is_valid(1));
765 assert_eq!(4, b.value(2));
766 }
767
768 #[test]
769 fn test_temporal_array_date32_hour() {
770 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15148)].into();
771
772 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
773 assert_eq!(0, b.value(0));
774 assert!(!b.is_valid(1));
775 assert_eq!(0, b.value(2));
776 }
777
778 #[test]
779 fn test_temporal_array_time32_second_hour() {
780 let a: PrimitiveArray<Time32SecondType> = vec![37800, 86339].into();
781
782 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
783 assert_eq!(10, b.value(0));
784 assert_eq!(23, b.value(1));
785 }
786
787 #[test]
788 fn test_temporal_array_time64_micro_hour() {
789 let a: PrimitiveArray<Time64MicrosecondType> = vec![37800000000, 86339000000].into();
790
791 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
792 assert_eq!(10, b.value(0));
793 assert_eq!(23, b.value(1));
794 }
795
796 #[test]
797 fn test_temporal_array_timestamp_micro_hour() {
798 let a: TimestampMicrosecondArray = vec![37800000000, 86339000000].into();
799
800 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
801 assert_eq!(10, b.value(0));
802 assert_eq!(23, b.value(1));
803 }
804
805 #[test]
806 fn test_temporal_array_date64_year() {
807 let a: PrimitiveArray<Date64Type> =
808 vec![Some(1514764800000), None, Some(1550636625000)].into();
809
810 let b = date_part_primitive(&a, DatePart::Year).unwrap();
811 assert_eq!(2018, b.value(0));
812 assert!(!b.is_valid(1));
813 assert_eq!(2019, b.value(2));
814 }
815
816 #[test]
817 fn test_temporal_array_date32_year() {
818 let a: PrimitiveArray<Date32Type> = vec![Some(15147), None, Some(15448)].into();
819
820 let b = date_part_primitive(&a, DatePart::Year).unwrap();
821 assert_eq!(2011, b.value(0));
822 assert!(!b.is_valid(1));
823 assert_eq!(2012, b.value(2));
824 }
825
826 #[test]
827 fn test_temporal_array_date64_quarter() {
828 let a: PrimitiveArray<Date64Type> =
831 vec![Some(1514764800000), None, Some(1566275025000)].into();
832
833 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
834 assert_eq!(1, b.value(0));
835 assert!(!b.is_valid(1));
836 assert_eq!(3, b.value(2));
837 }
838
839 #[test]
840 fn test_temporal_array_date32_quarter() {
841 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(300)].into();
842
843 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
844 assert_eq!(1, b.value(0));
845 assert!(!b.is_valid(1));
846 assert_eq!(4, b.value(2));
847 }
848
849 #[test]
850 fn test_temporal_array_timestamp_quarter_with_timezone() {
851 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("+00:00".to_string());
853 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
854 assert_eq!(2, b.value(0));
855 let a = TimestampSecondArray::from(vec![86400 * 90]).with_timezone("-10:00".to_string());
856 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
857 assert_eq!(1, b.value(0));
858 }
859
860 #[test]
861 fn test_all_quarters_date64() {
862 let a: PrimitiveArray<Date64Type> = vec![
868 Some(1767225600000),
869 Some(1775001600000),
870 Some(1782864000000),
871 Some(1790812800000),
872 None,
873 ]
874 .into();
875
876 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
877 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));
882 }
883
884 #[test]
885 fn test_all_quarters_date32() {
886 let a: PrimitiveArray<Date32Type> =
892 vec![Some(20454), Some(20544), Some(20635), Some(20727), None].into();
893
894 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
895 assert_eq!(1, b.value(0));
896 assert_eq!(2, b.value(1));
897 assert_eq!(3, b.value(2));
898 assert_eq!(4, b.value(3));
899 assert!(!b.is_valid(4));
900 }
901
902 #[test]
903 fn test_quarter_timestamp_microsecond() {
904 let a: TimestampMicrosecondArray =
908 vec![Some(1767225600000000), None, Some(1782864000000000)].into();
909
910 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
911 assert_eq!(1, b.value(0));
912 assert!(!b.is_valid(1));
913 assert_eq!(3, b.value(2));
914 }
915
916 #[test]
917 fn test_quarter_timestamp_nanosecond() {
918 let a: TimestampNanosecondArray =
922 vec![Some(1775001600000000000), None, Some(1790812800000000000)].into();
923
924 let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
925 assert_eq!(2, b.value(0));
926 assert!(!b.is_valid(1));
927 assert_eq!(4, b.value(2));
928 }
929
930 #[test]
931 fn test_temporal_array_date64_month() {
932 let a: PrimitiveArray<Date64Type> =
935 vec![Some(1514764800000), None, Some(1550636625000)].into();
936
937 let b = date_part_primitive(&a, DatePart::Month).unwrap();
938 assert_eq!(1, b.value(0));
939 assert!(!b.is_valid(1));
940 assert_eq!(2, b.value(2));
941 }
942
943 #[test]
944 fn test_temporal_array_date32_month() {
945 let a: PrimitiveArray<Date32Type> = vec![Some(1), None, Some(31)].into();
946
947 let b = date_part_primitive(&a, DatePart::Month).unwrap();
948 assert_eq!(1, b.value(0));
949 assert!(!b.is_valid(1));
950 assert_eq!(2, b.value(2));
951 }
952
953 #[test]
954 fn test_temporal_array_timestamp_month_with_timezone() {
955 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("+00:00".to_string());
957 let b = date_part_primitive(&a, DatePart::Month).unwrap();
958 assert_eq!(2, b.value(0));
959 let a = TimestampSecondArray::from(vec![86400 * 31]).with_timezone("-10:00".to_string());
960 let b = date_part_primitive(&a, DatePart::Month).unwrap();
961 assert_eq!(1, b.value(0));
962 }
963
964 #[test]
965 fn test_temporal_array_timestamp_day_with_timezone() {
966 let a = TimestampSecondArray::from(vec![86400]).with_timezone("+00:00".to_string());
968 let b = date_part_primitive(&a, DatePart::Day).unwrap();
969 assert_eq!(2, b.value(0));
970 let a = TimestampSecondArray::from(vec![86400]).with_timezone("-10:00".to_string());
971 let b = date_part_primitive(&a, DatePart::Day).unwrap();
972 assert_eq!(1, b.value(0));
973 }
974
975 #[test]
976 fn test_temporal_array_date64_weekday() {
977 let a: PrimitiveArray<Date64Type> =
980 vec![Some(1514764800000), None, Some(1550636625000)].into();
981
982 let b = date_part_primitive(&a, DatePart::DayOfWeekMonday0).unwrap();
983 assert_eq!(0, b.value(0));
984 assert!(!b.is_valid(1));
985 assert_eq!(2, b.value(2));
986 }
987
988 #[test]
989 fn test_temporal_array_date64_weekday0() {
990 let a: PrimitiveArray<Date64Type> = vec![
994 Some(1483228800000),
995 None,
996 Some(1514764800000),
997 Some(1550636625000),
998 ]
999 .into();
1000
1001 let b = date_part_primitive(&a, DatePart::DayOfWeekSunday0).unwrap();
1002 assert_eq!(0, b.value(0));
1003 assert!(!b.is_valid(1));
1004 assert_eq!(1, b.value(2));
1005 assert_eq!(3, b.value(3));
1006 }
1007
1008 #[test]
1009 fn test_temporal_array_date64_day() {
1010 let a: PrimitiveArray<Date64Type> =
1013 vec![Some(1514764800000), None, Some(1550636625000)].into();
1014
1015 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1016 assert_eq!(1, b.value(0));
1017 assert!(!b.is_valid(1));
1018 assert_eq!(20, b.value(2));
1019 }
1020
1021 #[test]
1022 fn test_temporal_array_date32_day() {
1023 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(31)].into();
1024
1025 let b = date_part_primitive(&a, DatePart::Day).unwrap();
1026 assert_eq!(1, b.value(0));
1027 assert!(!b.is_valid(1));
1028 assert_eq!(1, b.value(2));
1029 }
1030
1031 #[test]
1032 fn test_temporal_array_date64_doy() {
1033 let a: PrimitiveArray<Date64Type> = vec![
1037 Some(1483228800000),
1038 Some(1514764800000),
1039 None,
1040 Some(1550636625000),
1041 ]
1042 .into();
1043
1044 let b = date_part_primitive(&a, DatePart::DayOfYear).unwrap();
1045 assert_eq!(1, b.value(0));
1046 assert_eq!(1, b.value(1));
1047 assert!(!b.is_valid(2));
1048 assert_eq!(51, b.value(3));
1049 }
1050
1051 #[test]
1052 fn test_temporal_array_timestamp_micro_year() {
1053 let a: TimestampMicrosecondArray =
1054 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1055
1056 let b = date_part_primitive(&a, DatePart::Year).unwrap();
1057 assert_eq!(2021, b.value(0));
1058 assert!(!b.is_valid(1));
1059 assert_eq!(2024, b.value(2));
1060 }
1061
1062 #[test]
1063 fn test_temporal_array_date64_minute() {
1064 let a: PrimitiveArray<Date64Type> =
1065 vec![Some(1514764800000), None, Some(1550636625000)].into();
1066
1067 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1068 assert_eq!(0, b.value(0));
1069 assert!(!b.is_valid(1));
1070 assert_eq!(23, b.value(2));
1071 }
1072
1073 #[test]
1074 fn test_temporal_array_timestamp_micro_minute() {
1075 let a: TimestampMicrosecondArray =
1076 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1077
1078 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1079 assert_eq!(57, b.value(0));
1080 assert!(!b.is_valid(1));
1081 assert_eq!(44, b.value(2));
1082 }
1083
1084 #[test]
1085 fn test_temporal_array_date32_week() {
1086 let a: PrimitiveArray<Date32Type> = vec![Some(0), None, Some(7)].into();
1087
1088 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1089 assert_eq!(1, b.value(0));
1090 assert!(!b.is_valid(1));
1091 assert_eq!(2, b.value(2));
1092 }
1093
1094 #[test]
1095 fn test_temporal_array_date64_week() {
1096 let a: PrimitiveArray<Date64Type> = vec![
1099 Some(1646116175000),
1100 None,
1101 Some(1641171600000),
1102 Some(1640998800000),
1103 ]
1104 .into();
1105
1106 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1107 assert_eq!(9, b.value(0));
1108 assert!(!b.is_valid(1));
1109 assert_eq!(1, b.value(2));
1110 assert_eq!(52, b.value(3));
1111 }
1112
1113 #[test]
1114 fn test_temporal_array_timestamp_micro_week() {
1115 let a: TimestampMicrosecondArray =
1118 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1119
1120 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1121 assert_eq!(4, b.value(0));
1122 assert!(!b.is_valid(1));
1123 assert_eq!(30, b.value(2));
1124 }
1125
1126 #[test]
1127 fn test_temporal_array_date64_second() {
1128 let a: PrimitiveArray<Date64Type> =
1129 vec![Some(1514764800000), None, Some(1550636625000)].into();
1130
1131 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1132 assert_eq!(0, b.value(0));
1133 assert!(!b.is_valid(1));
1134 assert_eq!(45, b.value(2));
1135 }
1136
1137 #[test]
1138 fn test_temporal_array_timestamp_micro_second() {
1139 let a: TimestampMicrosecondArray =
1140 vec![Some(1612025847000000), None, Some(1722015847000000)].into();
1141
1142 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1143 assert_eq!(27, b.value(0));
1144 assert!(!b.is_valid(1));
1145 assert_eq!(7, b.value(2));
1146 }
1147
1148 #[test]
1149 fn test_temporal_array_timestamp_second_with_timezone() {
1150 let a = TimestampSecondArray::from(vec![10, 20]).with_timezone("+00:00".to_string());
1151 let b = date_part_primitive(&a, DatePart::Second).unwrap();
1152 assert_eq!(10, b.value(0));
1153 assert_eq!(20, b.value(1));
1154 }
1155
1156 #[test]
1157 fn test_temporal_array_timestamp_minute_with_timezone() {
1158 let a = TimestampSecondArray::from(vec![0, 60]).with_timezone("+00:50".to_string());
1159 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1160 assert_eq!(50, b.value(0));
1161 assert_eq!(51, b.value(1));
1162 }
1163
1164 #[test]
1165 fn test_temporal_array_timestamp_minute_with_negative_timezone() {
1166 let a = TimestampSecondArray::from(vec![60 * 55]).with_timezone("-00:50".to_string());
1167 let b = date_part_primitive(&a, DatePart::Minute).unwrap();
1168 assert_eq!(5, b.value(0));
1169 }
1170
1171 #[test]
1172 fn test_temporal_array_timestamp_hour_with_timezone() {
1173 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01:00".to_string());
1174 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1175 assert_eq!(11, b.value(0));
1176 }
1177
1178 #[test]
1179 fn test_temporal_array_timestamp_hour_with_timezone_without_colon() {
1180 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+0100".to_string());
1181 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1182 assert_eq!(11, b.value(0));
1183 }
1184
1185 #[test]
1186 fn test_temporal_array_timestamp_hour_with_timezone_without_minutes() {
1187 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("+01".to_string());
1188 let b = date_part_primitive(&a, DatePart::Hour).unwrap();
1189 assert_eq!(11, b.value(0));
1190 }
1191
1192 #[test]
1193 fn test_temporal_array_timestamp_hour_with_timezone_without_initial_sign() {
1194 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("0100".to_string());
1195 let err = date_part_primitive(&a, DatePart::Hour)
1196 .unwrap_err()
1197 .to_string();
1198 assert!(err.contains("Invalid timezone"), "{}", err);
1199 }
1200
1201 #[test]
1202 fn test_temporal_array_timestamp_hour_with_timezone_with_only_colon() {
1203 let a = TimestampSecondArray::from(vec![60 * 60 * 10]).with_timezone("01:00".to_string());
1204 let err = date_part_primitive(&a, DatePart::Hour)
1205 .unwrap_err()
1206 .to_string();
1207 assert!(err.contains("Invalid timezone"), "{}", err);
1208 }
1209
1210 #[test]
1211 fn test_temporal_array_timestamp_week_without_timezone() {
1212 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1]);
1216 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1217 assert_eq!(1, b.value(0));
1218 assert_eq!(2, b.value(1));
1219 assert_eq!(1, b.value(2));
1220 }
1221
1222 #[test]
1223 fn test_temporal_array_timestamp_week_with_timezone() {
1224 let a = TimestampSecondArray::from(vec![0, 86400 * 4, 86400 * 4 - 1])
1228 .with_timezone("+01:00".to_string());
1229 let b = date_part_primitive(&a, DatePart::Week).unwrap();
1230 assert_eq!(1, b.value(0));
1231 assert_eq!(2, b.value(1));
1232 assert_eq!(2, b.value(2));
1233 }
1234
1235 #[test]
1236 fn test_hour_minute_second_dictionary_array() {
1237 let a = TimestampSecondArray::from(vec![
1238 60 * 60 * 10 + 61,
1239 60 * 60 * 20 + 122,
1240 60 * 60 * 30 + 183,
1241 ])
1242 .with_timezone("+01:00".to_string());
1243
1244 let keys = Int8Array::from_iter_values([0_i8, 0, 1, 2, 1]);
1245 let dict = DictionaryArray::try_new(keys.clone(), Arc::new(a)).unwrap();
1246
1247 let b = date_part(&dict, DatePart::Hour).unwrap();
1248
1249 let expected_dict =
1250 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![11, 21, 7])));
1251 let expected = Arc::new(expected_dict) as ArrayRef;
1252 assert_eq!(&expected, &b);
1253
1254 let b = date_part(&dict, DatePart::Minute).unwrap();
1255
1256 let b_old = date_part(&dict, DatePart::Minute).unwrap();
1257
1258 let expected_dict =
1259 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1260 let expected = Arc::new(expected_dict) as ArrayRef;
1261 assert_eq!(&expected, &b);
1262 assert_eq!(&expected, &b_old);
1263
1264 let b = date_part(&dict, DatePart::Second).unwrap();
1265
1266 let b_old = date_part(&dict, DatePart::Second).unwrap();
1267
1268 let expected_dict =
1269 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 2, 3])));
1270 let expected = Arc::new(expected_dict) as ArrayRef;
1271 assert_eq!(&expected, &b);
1272 assert_eq!(&expected, &b_old);
1273
1274 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1275
1276 let expected_dict =
1277 DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![0, 0, 0, 0, 0])));
1278 let expected = Arc::new(expected_dict) as ArrayRef;
1279 assert_eq!(&expected, &b);
1280 }
1281
1282 #[test]
1283 fn test_year_dictionary_array() {
1284 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1285
1286 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1287 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1288
1289 let b = date_part(&dict, DatePart::Year).unwrap();
1290
1291 let expected_dict = DictionaryArray::new(
1292 keys,
1293 Arc::new(Int32Array::from(vec![2018, 2019, 2019, 2018])),
1294 );
1295 let expected = Arc::new(expected_dict) as ArrayRef;
1296 assert_eq!(&expected, &b);
1297 }
1298
1299 #[test]
1300 fn test_quarter_month_dictionary_array() {
1301 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1566275025000)].into();
1304
1305 let keys = Int8Array::from_iter_values([0_i8, 1, 1, 0]);
1306 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1307
1308 let b = date_part(&dict, DatePart::Quarter).unwrap();
1309
1310 let expected =
1311 DictionaryArray::new(keys.clone(), Arc::new(Int32Array::from(vec![1, 3, 3, 1])));
1312 assert_eq!(b.as_ref(), &expected);
1313
1314 let b = date_part(&dict, DatePart::Month).unwrap();
1315
1316 let expected = DictionaryArray::new(keys, Arc::new(Int32Array::from(vec![1, 8, 8, 1])));
1317 assert_eq!(b.as_ref(), &expected);
1318 }
1319
1320 #[test]
1321 fn test_num_days_from_monday_sunday_day_doy_week_dictionary_array() {
1322 let a: PrimitiveArray<Date64Type> = vec![Some(1514764800000), Some(1550636625000)].into();
1325
1326 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1), Some(0), None]);
1327 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1328
1329 let b = date_part(&dict, DatePart::DayOfWeekMonday0).unwrap();
1330
1331 let a = Int32Array::from(vec![Some(0), Some(2), Some(2), Some(0), None]);
1332 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1333 assert_eq!(b.as_ref(), &expected);
1334
1335 let b = date_part(&dict, DatePart::DayOfWeekSunday0).unwrap();
1336
1337 let a = Int32Array::from(vec![Some(1), Some(3), Some(3), Some(1), None]);
1338 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1339 assert_eq!(b.as_ref(), &expected);
1340
1341 let b = date_part(&dict, DatePart::Day).unwrap();
1342
1343 let a = Int32Array::from(vec![Some(1), Some(20), Some(20), Some(1), None]);
1344 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1345 assert_eq!(b.as_ref(), &expected);
1346
1347 let b = date_part(&dict, DatePart::DayOfYear).unwrap();
1348
1349 let a = Int32Array::from(vec![Some(1), Some(51), Some(51), Some(1), None]);
1350 let expected = DictionaryArray::new(keys.clone(), Arc::new(a));
1351 assert_eq!(b.as_ref(), &expected);
1352
1353 let b = date_part(&dict, DatePart::Week).unwrap();
1354
1355 let a = Int32Array::from(vec![Some(1), Some(8), Some(8), Some(1), None]);
1356 let expected = DictionaryArray::new(keys, Arc::new(a));
1357 assert_eq!(b.as_ref(), &expected);
1358 }
1359
1360 #[test]
1361 fn test_temporal_array_date64_nanosecond() {
1362 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1369
1370 let b = date_part_primitive(&a, DatePart::Nanosecond).unwrap();
1371 assert!(!b.is_valid(0));
1372 assert_eq!(453_000_000, b.value(1));
1373
1374 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1375 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1376 let b = date_part(&dict, DatePart::Nanosecond).unwrap();
1377
1378 let a = Int32Array::from(vec![None, Some(453_000_000)]);
1379 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1380 let expected = Arc::new(expected_dict) as ArrayRef;
1381 assert_eq!(&expected, &b);
1382 }
1383
1384 #[test]
1385 fn test_temporal_array_date64_microsecond() {
1386 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1387
1388 let b = date_part_primitive(&a, DatePart::Microsecond).unwrap();
1389 assert!(!b.is_valid(0));
1390 assert_eq!(453_000, b.value(1));
1391
1392 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1393 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1394 let b = date_part(&dict, DatePart::Microsecond).unwrap();
1395
1396 let a = Int32Array::from(vec![None, Some(453_000)]);
1397 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1398 let expected = Arc::new(expected_dict) as ArrayRef;
1399 assert_eq!(&expected, &b);
1400 }
1401
1402 #[test]
1403 fn test_temporal_array_date64_millisecond() {
1404 let a: PrimitiveArray<Date64Type> = vec![None, Some(1667328721453)].into();
1405
1406 let b = date_part_primitive(&a, DatePart::Millisecond).unwrap();
1407 assert!(!b.is_valid(0));
1408 assert_eq!(453, b.value(1));
1409
1410 let keys = Int8Array::from(vec![Some(0_i8), Some(1), Some(1)]);
1411 let dict = DictionaryArray::new(keys.clone(), Arc::new(a));
1412 let b = date_part(&dict, DatePart::Millisecond).unwrap();
1413
1414 let a = Int32Array::from(vec![None, Some(453)]);
1415 let expected_dict = DictionaryArray::new(keys, Arc::new(a));
1416 let expected = Arc::new(expected_dict) as ArrayRef;
1417 assert_eq!(&expected, &b);
1418 }
1419
1420 #[test]
1421 fn test_temporal_array_time64_nanoseconds() {
1422 let input: Time64NanosecondArray = vec![Some(84_770_123_456_789)].into();
1424
1425 let actual = date_part(&input, DatePart::Hour).unwrap();
1426 let actual = actual.as_primitive::<Int32Type>();
1427 assert_eq!(23, actual.value(0));
1428
1429 let actual = date_part(&input, DatePart::Minute).unwrap();
1430 let actual = actual.as_primitive::<Int32Type>();
1431 assert_eq!(32, actual.value(0));
1432
1433 let actual = date_part(&input, DatePart::Second).unwrap();
1434 let actual = actual.as_primitive::<Int32Type>();
1435 assert_eq!(50, actual.value(0));
1436
1437 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1438 let actual = actual.as_primitive::<Int32Type>();
1439 assert_eq!(123, actual.value(0));
1440
1441 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1442 let actual = actual.as_primitive::<Int32Type>();
1443 assert_eq!(123_456, actual.value(0));
1444
1445 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1446 let actual = actual.as_primitive::<Int32Type>();
1447 assert_eq!(123_456_789, actual.value(0));
1448
1449 let input: Time64NanosecondArray = vec![
1451 Some(-1),
1452 Some(86_400_000_000_000),
1453 Some(86_401_000_000_000),
1454 None,
1455 ]
1456 .into();
1457 let actual = date_part(&input, DatePart::Hour).unwrap();
1458 let actual = actual.as_primitive::<Int32Type>();
1459 let expected: Int32Array = vec![None, None, None, None].into();
1460 assert_eq!(&expected, actual);
1461 }
1462
1463 #[test]
1464 fn test_temporal_array_time64_microseconds() {
1465 let input: Time64MicrosecondArray = vec![Some(84_770_123_456)].into();
1467
1468 let actual = date_part(&input, DatePart::Hour).unwrap();
1469 let actual = actual.as_primitive::<Int32Type>();
1470 assert_eq!(23, actual.value(0));
1471
1472 let actual = date_part(&input, DatePart::Minute).unwrap();
1473 let actual = actual.as_primitive::<Int32Type>();
1474 assert_eq!(32, actual.value(0));
1475
1476 let actual = date_part(&input, DatePart::Second).unwrap();
1477 let actual = actual.as_primitive::<Int32Type>();
1478 assert_eq!(50, actual.value(0));
1479
1480 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1481 let actual = actual.as_primitive::<Int32Type>();
1482 assert_eq!(123, actual.value(0));
1483
1484 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1485 let actual = actual.as_primitive::<Int32Type>();
1486 assert_eq!(123_456, actual.value(0));
1487
1488 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1489 let actual = actual.as_primitive::<Int32Type>();
1490 assert_eq!(123_456_000, actual.value(0));
1491
1492 let input: Time64MicrosecondArray =
1494 vec![Some(-1), Some(86_400_000_000), Some(86_401_000_000), None].into();
1495 let actual = date_part(&input, DatePart::Hour).unwrap();
1496 let actual = actual.as_primitive::<Int32Type>();
1497 let expected: Int32Array = vec![None, None, None, None].into();
1498 assert_eq!(&expected, actual);
1499 }
1500
1501 #[test]
1502 fn test_temporal_array_time32_milliseconds() {
1503 let input: Time32MillisecondArray = vec![Some(84_770_123)].into();
1505
1506 let actual = date_part(&input, DatePart::Hour).unwrap();
1507 let actual = actual.as_primitive::<Int32Type>();
1508 assert_eq!(23, actual.value(0));
1509
1510 let actual = date_part(&input, DatePart::Minute).unwrap();
1511 let actual = actual.as_primitive::<Int32Type>();
1512 assert_eq!(32, actual.value(0));
1513
1514 let actual = date_part(&input, DatePart::Second).unwrap();
1515 let actual = actual.as_primitive::<Int32Type>();
1516 assert_eq!(50, actual.value(0));
1517
1518 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1519 let actual = actual.as_primitive::<Int32Type>();
1520 assert_eq!(123, actual.value(0));
1521
1522 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1523 let actual = actual.as_primitive::<Int32Type>();
1524 assert_eq!(123_000, actual.value(0));
1525
1526 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1527 let actual = actual.as_primitive::<Int32Type>();
1528 assert_eq!(123_000_000, actual.value(0));
1529
1530 let input: Time32MillisecondArray =
1532 vec![Some(-1), Some(86_400_000), Some(86_401_000), None].into();
1533 let actual = date_part(&input, DatePart::Hour).unwrap();
1534 let actual = actual.as_primitive::<Int32Type>();
1535 let expected: Int32Array = vec![None, None, None, None].into();
1536 assert_eq!(&expected, actual);
1537 }
1538
1539 #[test]
1540 fn test_temporal_array_time32_seconds() {
1541 let input: Time32SecondArray = vec![84_770].into();
1543
1544 let actual = date_part(&input, DatePart::Hour).unwrap();
1545 let actual = actual.as_primitive::<Int32Type>();
1546 assert_eq!(23, actual.value(0));
1547
1548 let actual = date_part(&input, DatePart::Minute).unwrap();
1549 let actual = actual.as_primitive::<Int32Type>();
1550 assert_eq!(32, actual.value(0));
1551
1552 let actual = date_part(&input, DatePart::Second).unwrap();
1553 let actual = actual.as_primitive::<Int32Type>();
1554 assert_eq!(50, actual.value(0));
1555
1556 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1557 let actual = actual.as_primitive::<Int32Type>();
1558 assert_eq!(0, actual.value(0));
1559
1560 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1561 let actual = actual.as_primitive::<Int32Type>();
1562 assert_eq!(0, actual.value(0));
1563
1564 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1565 let actual = actual.as_primitive::<Int32Type>();
1566 assert_eq!(0, actual.value(0));
1567
1568 let input: Time32SecondArray = vec![Some(-1), Some(86_400), Some(86_401), None].into();
1570 let actual = date_part(&input, DatePart::Hour).unwrap();
1571 let actual = actual.as_primitive::<Int32Type>();
1572 let expected: Int32Array = vec![None, None, None, None].into();
1573 assert_eq!(&expected, actual);
1574 }
1575
1576 #[test]
1577 fn test_temporal_array_time_invalid_parts() {
1578 fn ensure_returns_error(array: &dyn Array) {
1579 let invalid_parts = [
1580 DatePart::Quarter,
1581 DatePart::Year,
1582 DatePart::Month,
1583 DatePart::Week,
1584 DatePart::Day,
1585 DatePart::DayOfWeekSunday0,
1586 DatePart::DayOfWeekMonday0,
1587 DatePart::DayOfYear,
1588 ];
1589
1590 for part in invalid_parts {
1591 let err = date_part(array, part).unwrap_err();
1592 let expected = format!(
1593 "Compute error: {part} does not support: {}",
1594 array.data_type()
1595 );
1596 assert_eq!(expected, err.to_string());
1597 }
1598 }
1599
1600 ensure_returns_error(&Time32SecondArray::from(vec![0]));
1601 ensure_returns_error(&Time32MillisecondArray::from(vec![0]));
1602 ensure_returns_error(&Time64MicrosecondArray::from(vec![0]));
1603 ensure_returns_error(&Time64NanosecondArray::from(vec![0]));
1604 }
1605
1606 #[test]
1607 fn test_interval_year_month_array() {
1608 let input: IntervalYearMonthArray = vec![0, 5, 24].into();
1609
1610 let actual = date_part(&input, DatePart::Year).unwrap();
1611 let actual = actual.as_primitive::<Int32Type>();
1612 assert_eq!(0, actual.value(0));
1613 assert_eq!(0, actual.value(1));
1614 assert_eq!(2, actual.value(2));
1615
1616 let actual = date_part(&input, DatePart::Month).unwrap();
1617 let actual = actual.as_primitive::<Int32Type>();
1618 assert_eq!(0, actual.value(0));
1619 assert_eq!(5, actual.value(1));
1620 assert_eq!(0, actual.value(2));
1621
1622 assert!(date_part(&input, DatePart::Day).is_err());
1623 assert!(date_part(&input, DatePart::Week).is_err());
1624 }
1625
1626 #[test]
1629 fn test_interval_day_time_array() {
1630 let input: IntervalDayTimeArray = vec![
1631 IntervalDayTime::ZERO,
1632 IntervalDayTime::new(10, 42), IntervalDayTime::new(10, 1042), IntervalDayTime::new(10, MILLISECONDS_IN_DAY as i32 + 1), IntervalDayTime::new(
1636 6,
1637 (MILLISECONDS * 60 * 60 * 4 + MILLISECONDS * 60 * 22 + MILLISECONDS * 11 + 3)
1638 as i32,
1639 ), ]
1641 .into();
1642
1643 let actual = date_part(&input, DatePart::Day).unwrap();
1645 let actual = actual.as_primitive::<Int32Type>();
1646 assert_eq!(0, actual.value(0));
1647 assert_eq!(10, actual.value(1));
1648 assert_eq!(10, actual.value(2));
1649 assert_eq!(10, actual.value(3));
1650 assert_eq!(6, actual.value(4));
1651
1652 let actual = date_part(&input, DatePart::Week).unwrap();
1653 let actual = actual.as_primitive::<Int32Type>();
1654 assert_eq!(0, actual.value(0));
1655 assert_eq!(1, actual.value(1));
1656 assert_eq!(1, actual.value(2));
1657 assert_eq!(1, actual.value(3));
1658 assert_eq!(0, actual.value(4));
1659
1660 let actual = date_part(&input, DatePart::Hour).unwrap();
1662 let actual = actual.as_primitive::<Int32Type>();
1663 assert_eq!(0, actual.value(0));
1664 assert_eq!(0, actual.value(1));
1665 assert_eq!(0, actual.value(2));
1666 assert_eq!(24, actual.value(3));
1667 assert_eq!(4, actual.value(4));
1668
1669 let actual = date_part(&input, DatePart::Minute).unwrap();
1670 let actual = actual.as_primitive::<Int32Type>();
1671 assert_eq!(0, actual.value(0));
1672 assert_eq!(0, actual.value(1));
1673 assert_eq!(0, actual.value(2));
1674 assert_eq!(0, actual.value(3));
1675 assert_eq!(22, actual.value(4));
1676
1677 let actual = date_part(&input, DatePart::Second).unwrap();
1678 let actual = actual.as_primitive::<Int32Type>();
1679 assert_eq!(0, actual.value(0));
1680 assert_eq!(0, actual.value(1));
1681 assert_eq!(1, actual.value(2));
1682 assert_eq!(0, actual.value(3));
1683 assert_eq!(11, actual.value(4));
1684
1685 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1686 let actual = actual.as_primitive::<Int32Type>();
1687 assert_eq!(0, actual.value(0));
1688 assert_eq!(42, actual.value(1));
1689 assert_eq!(1042, actual.value(2));
1690 assert_eq!(1, actual.value(3));
1691 assert_eq!(11003, actual.value(4));
1692
1693 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1694 let actual = actual.as_primitive::<Int32Type>();
1695 assert_eq!(0, actual.value(0));
1696 assert_eq!(42_000, actual.value(1));
1697 assert_eq!(1_042_000, actual.value(2));
1698 assert_eq!(1_000, actual.value(3));
1699 assert_eq!(11_003_000, actual.value(4));
1700
1701 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1702 let actual = actual.as_primitive::<Int32Type>();
1703 assert_eq!(0, actual.value(0));
1704 assert_eq!(42_000_000, actual.value(1));
1705 assert_eq!(1_042_000_000, actual.value(2));
1706 assert_eq!(1_000_000, actual.value(3));
1707 assert_eq!(0, actual.value(4));
1709
1710 assert!(date_part(&input, DatePart::Month).is_err());
1712 assert!(date_part(&input, DatePart::Year).is_err());
1713 }
1714
1715 #[test]
1718 fn test_interval_month_day_nano_array() {
1719 let input: IntervalMonthDayNanoArray = vec![
1720 IntervalMonthDayNano::ZERO,
1721 IntervalMonthDayNano::new(5, 10, 42), IntervalMonthDayNano::new(16, 35, NANOSECONDS_IN_DAY + 1), IntervalMonthDayNano::new(
1724 0,
1725 0,
1726 NANOSECONDS * 60 * 60 * 4
1727 + NANOSECONDS * 60 * 22
1728 + NANOSECONDS * 11
1729 + 1_000_000 * 33
1730 + 1_000 * 44
1731 + 5,
1732 ), ]
1734 .into();
1735
1736 let actual = date_part(&input, DatePart::Year).unwrap();
1738 let actual = actual.as_primitive::<Int32Type>();
1739 assert_eq!(0, actual.value(0));
1740 assert_eq!(0, actual.value(1));
1741 assert_eq!(1, actual.value(2));
1742 assert_eq!(0, actual.value(3));
1743
1744 let actual = date_part(&input, DatePart::Month).unwrap();
1745 let actual = actual.as_primitive::<Int32Type>();
1746 assert_eq!(0, actual.value(0));
1747 assert_eq!(5, actual.value(1));
1748 assert_eq!(4, actual.value(2));
1749 assert_eq!(0, actual.value(3));
1750
1751 let actual = date_part(&input, DatePart::Week).unwrap();
1753 let actual = actual.as_primitive::<Int32Type>();
1754 assert_eq!(0, actual.value(0));
1755 assert_eq!(1, actual.value(1));
1756 assert_eq!(5, actual.value(2));
1757 assert_eq!(0, actual.value(3));
1758
1759 let actual = date_part(&input, DatePart::Day).unwrap();
1760 let actual = actual.as_primitive::<Int32Type>();
1761 assert_eq!(0, actual.value(0));
1762 assert_eq!(10, actual.value(1));
1763 assert_eq!(35, actual.value(2));
1764 assert_eq!(0, actual.value(3));
1765
1766 let actual = date_part(&input, DatePart::Hour).unwrap();
1768 let actual = actual.as_primitive::<Int32Type>();
1769 assert_eq!(0, actual.value(0));
1770 assert_eq!(0, actual.value(1));
1771 assert_eq!(24, actual.value(2));
1772 assert_eq!(4, actual.value(3));
1773
1774 let actual = date_part(&input, DatePart::Minute).unwrap();
1775 let actual = actual.as_primitive::<Int32Type>();
1776 assert_eq!(0, actual.value(0));
1777 assert_eq!(0, actual.value(1));
1778 assert_eq!(0, actual.value(2));
1779 assert_eq!(22, actual.value(3));
1780
1781 let actual = date_part(&input, DatePart::Second).unwrap();
1782 let actual = actual.as_primitive::<Int32Type>();
1783 assert_eq!(0, actual.value(0));
1784 assert_eq!(0, actual.value(1));
1785 assert_eq!(0, actual.value(2));
1786 assert_eq!(11, actual.value(3));
1787
1788 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1789 let actual = actual.as_primitive::<Int32Type>();
1790 assert_eq!(0, actual.value(0));
1791 assert_eq!(0, actual.value(1));
1792 assert_eq!(0, actual.value(2));
1793 assert_eq!(11_033, actual.value(3));
1794
1795 let actual = date_part(&input, DatePart::Microsecond).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!(0, actual.value(2));
1800 assert_eq!(11_033_044, actual.value(3));
1801
1802 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1803 let actual = actual.as_primitive::<Int32Type>();
1804 assert_eq!(0, actual.value(0));
1805 assert_eq!(42, actual.value(1));
1806 assert_eq!(1, actual.value(2));
1807 assert_eq!(0, actual.value(3));
1809 }
1810
1811 #[test]
1812 fn test_interval_array_invalid_parts() {
1813 fn ensure_returns_error(array: &dyn Array) {
1814 let invalid_parts = [
1815 DatePart::Quarter,
1816 DatePart::DayOfWeekSunday0,
1817 DatePart::DayOfWeekMonday0,
1818 DatePart::DayOfYear,
1819 ];
1820
1821 for part in invalid_parts {
1822 let err = date_part(array, part).unwrap_err();
1823 let expected = format!(
1824 "Compute error: {part} does not support: {}",
1825 array.data_type()
1826 );
1827 assert_eq!(expected, err.to_string());
1828 }
1829 }
1830
1831 ensure_returns_error(&IntervalYearMonthArray::from(vec![0]));
1832 ensure_returns_error(&IntervalDayTimeArray::from(vec![IntervalDayTime::ZERO]));
1833 ensure_returns_error(&IntervalMonthDayNanoArray::from(vec![
1834 IntervalMonthDayNano::ZERO,
1835 ]));
1836 }
1837
1838 #[test]
1839 fn test_duration_second() {
1840 let input: DurationSecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1841
1842 let actual = date_part(&input, DatePart::Second).unwrap();
1843 let actual = actual.as_primitive::<Int32Type>();
1844 assert_eq!(0, actual.value(0));
1845 assert_eq!(42, actual.value(1));
1846 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1847
1848 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1849 let actual = actual.as_primitive::<Int32Type>();
1850 assert_eq!(0, actual.value(0));
1851 assert_eq!(42_000, actual.value(1));
1852 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1853
1854 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1855 let actual = actual.as_primitive::<Int32Type>();
1856 assert_eq!(0, actual.value(0));
1857 assert_eq!(42_000_000, actual.value(1));
1858 assert_eq!(0, actual.value(2));
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!(0, actual.value(1));
1864 assert_eq!(0, actual.value(2));
1865 }
1866
1867 #[test]
1868 fn test_duration_millisecond() {
1869 let input: DurationMillisecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1870
1871 let actual = date_part(&input, DatePart::Second).unwrap();
1872 let actual = actual.as_primitive::<Int32Type>();
1873 assert_eq!(0, actual.value(0));
1874 assert_eq!(0, actual.value(1));
1875 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1876
1877 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1878 let actual = actual.as_primitive::<Int32Type>();
1879 assert_eq!(0, actual.value(0));
1880 assert_eq!(42, actual.value(1));
1881 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1882
1883 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1884 let actual = actual.as_primitive::<Int32Type>();
1885 assert_eq!(0, actual.value(0));
1886 assert_eq!(42_000, actual.value(1));
1887 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1888
1889 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1890 let actual = actual.as_primitive::<Int32Type>();
1891 assert_eq!(0, actual.value(0));
1892 assert_eq!(42_000_000, actual.value(1));
1893 assert_eq!(0, actual.value(2));
1894 }
1895
1896 #[test]
1897 fn test_duration_microsecond() {
1898 let input: DurationMicrosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1899
1900 let actual = date_part(&input, DatePart::Second).unwrap();
1901 let actual = actual.as_primitive::<Int32Type>();
1902 assert_eq!(0, actual.value(0));
1903 assert_eq!(0, actual.value(1));
1904 assert_eq!(0, actual.value(2));
1905
1906 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1907 let actual = actual.as_primitive::<Int32Type>();
1908 assert_eq!(0, actual.value(0));
1909 assert_eq!(0, actual.value(1));
1910 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1911
1912 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1913 let actual = actual.as_primitive::<Int32Type>();
1914 assert_eq!(0, actual.value(0));
1915 assert_eq!(42, actual.value(1));
1916 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1917
1918 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1919 let actual = actual.as_primitive::<Int32Type>();
1920 assert_eq!(0, actual.value(0));
1921 assert_eq!(42_000, actual.value(1));
1922 assert_eq!((60 * 60 * 24 + 1) * 1_000, actual.value(2));
1923 }
1924
1925 #[test]
1926 fn test_duration_nanosecond() {
1927 let input: DurationNanosecondArray = vec![0, 42, 60 * 60 * 24 + 1].into();
1928
1929 let actual = date_part(&input, DatePart::Second).unwrap();
1930 let actual = actual.as_primitive::<Int32Type>();
1931 assert_eq!(0, actual.value(0));
1932 assert_eq!(0, actual.value(1));
1933 assert_eq!(0, actual.value(2));
1934
1935 let actual = date_part(&input, DatePart::Millisecond).unwrap();
1936 let actual = actual.as_primitive::<Int32Type>();
1937 assert_eq!(0, actual.value(0));
1938 assert_eq!(0, actual.value(1));
1939 assert_eq!(0, actual.value(2));
1940
1941 let actual = date_part(&input, DatePart::Microsecond).unwrap();
1942 let actual = actual.as_primitive::<Int32Type>();
1943 assert_eq!(0, actual.value(0));
1944 assert_eq!(0, actual.value(1));
1945 assert_eq!((60 * 60 * 24 + 1) / 1_000, actual.value(2));
1946
1947 let actual = date_part(&input, DatePart::Nanosecond).unwrap();
1948 let actual = actual.as_primitive::<Int32Type>();
1949 assert_eq!(0, actual.value(0));
1950 assert_eq!(42, actual.value(1));
1951 assert_eq!(60 * 60 * 24 + 1, actual.value(2));
1952 }
1953
1954 #[test]
1955 fn test_duration_invalid_parts() {
1956 fn ensure_returns_error(array: &dyn Array) {
1957 let invalid_parts = [
1958 DatePart::Year,
1959 DatePart::Quarter,
1960 DatePart::Month,
1961 DatePart::DayOfWeekSunday0,
1962 DatePart::DayOfWeekMonday0,
1963 DatePart::DayOfYear,
1964 ];
1965
1966 for part in invalid_parts {
1967 let err = date_part(array, part).unwrap_err();
1968 let expected = format!(
1969 "Compute error: {part} does not support: {}",
1970 array.data_type()
1971 );
1972 assert_eq!(expected, err.to_string());
1973 }
1974 }
1975
1976 ensure_returns_error(&DurationSecondArray::from(vec![0]));
1977 ensure_returns_error(&DurationMillisecondArray::from(vec![0]));
1978 ensure_returns_error(&DurationMicrosecondArray::from(vec![0]));
1979 ensure_returns_error(&DurationNanosecondArray::from(vec![0]));
1980 }
1981
1982 const TIMESTAMP_SECOND_1970_01_01: i64 = 0;
1983 const TIMESTAMP_SECOND_2018_01_01: i64 = 1_514_764_800;
1984 const TIMESTAMP_SECOND_2019_02_20: i64 = 1_550_636_625;
1985 const SECONDS_IN_DAY: i64 = 24 * 60 * 60;
1986 #[test]
1988 fn test_temporal_array_date64_week_iso() {
1989 let a: PrimitiveArray<Date64Type> = vec![
1990 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
1991 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
1992 ]
1993 .into();
1994
1995 let b = date_part(&a, DatePart::WeekISO).unwrap();
1996 let actual = b.as_primitive::<Int32Type>();
1997 assert_eq!(1, actual.value(0));
1998 assert_eq!(8, actual.value(1));
1999 }
2000
2001 #[test]
2002 fn test_temporal_array_date64_year_iso() {
2003 let a: PrimitiveArray<Date64Type> = vec![
2004 Some(TIMESTAMP_SECOND_2018_01_01 * 1000),
2005 Some(TIMESTAMP_SECOND_2019_02_20 * 1000),
2006 ]
2007 .into();
2008
2009 let b = date_part(&a, DatePart::YearISO).unwrap();
2010 let actual = b.as_primitive::<Int32Type>();
2011 assert_eq!(2018, actual.value(0));
2012 assert_eq!(2019, actual.value(1));
2013 }
2014
2015 #[test]
2016 fn test_temporal_array_timestamp_week_iso() {
2017 let a = TimestampSecondArray::from(vec![
2018 TIMESTAMP_SECOND_1970_01_01, SECONDS_IN_DAY * 4, SECONDS_IN_DAY * 4 - 1, ]);
2022 let b = date_part(&a, DatePart::WeekISO).unwrap();
2023 let actual = b.as_primitive::<Int32Type>();
2024 assert_eq!(1, actual.value(0));
2025 assert_eq!(2, actual.value(1));
2026 assert_eq!(1, actual.value(2));
2027 }
2028
2029 #[test]
2030 fn test_temporal_array_timestamp_year_iso() {
2031 let a = TimestampSecondArray::from(vec![
2032 TIMESTAMP_SECOND_1970_01_01,
2033 SECONDS_IN_DAY * 4,
2034 SECONDS_IN_DAY * 4 - 1,
2035 ]);
2036 let b = date_part(&a, DatePart::YearISO).unwrap();
2037 let actual = b.as_primitive::<Int32Type>();
2038 assert_eq!(1970, actual.value(0));
2039 assert_eq!(1970, actual.value(1));
2040 assert_eq!(1970, actual.value(2));
2041 }
2042
2043 const TIMESTAMP_SECOND_2015_12_28: i64 = 1_451_260_800;
2044 const TIMESTAMP_SECOND_2016_01_03: i64 = 1_451_779_200;
2045 #[test]
2049 fn test_temporal_array_date64_week_iso_edge_cases() {
2050 let a: PrimitiveArray<Date64Type> = vec![
2051 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2052 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2053 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2054 ]
2055 .into();
2056
2057 let b = date_part(&a, DatePart::WeekISO).unwrap();
2058 let actual = b.as_primitive::<Int32Type>();
2059 assert_eq!(53, actual.value(0));
2060 assert_eq!(53, actual.value(1));
2061 assert_eq!(1, actual.value(2));
2062 }
2063
2064 #[test]
2065 fn test_temporal_array_date64_year_iso_edge_cases() {
2066 let a: PrimitiveArray<Date64Type> = vec![
2067 Some(TIMESTAMP_SECOND_2015_12_28 * 1000),
2068 Some(TIMESTAMP_SECOND_2016_01_03 * 1000),
2069 Some((TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY) * 1000),
2070 ]
2071 .into();
2072
2073 let b = date_part(&a, DatePart::YearISO).unwrap();
2074 let actual = b.as_primitive::<Int32Type>();
2075 assert_eq!(2015, actual.value(0));
2076 assert_eq!(2015, actual.value(1));
2077 assert_eq!(2016, actual.value(2));
2078 }
2079
2080 #[test]
2081 fn test_temporal_array_timestamp_week_iso_edge_cases() {
2082 let a = TimestampSecondArray::from(vec![
2083 TIMESTAMP_SECOND_2015_12_28,
2084 TIMESTAMP_SECOND_2016_01_03,
2085 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2086 ]);
2087 let b = date_part(&a, DatePart::WeekISO).unwrap();
2088 let actual = b.as_primitive::<Int32Type>();
2089 assert_eq!(53, actual.value(0));
2090 assert_eq!(53, actual.value(1));
2091 assert_eq!(1, actual.value(2));
2092 }
2093
2094 #[test]
2095 fn test_temporal_array_timestamp_year_iso_edge_cases() {
2096 let a = TimestampSecondArray::from(vec![
2097 TIMESTAMP_SECOND_2015_12_28,
2098 TIMESTAMP_SECOND_2016_01_03,
2099 TIMESTAMP_SECOND_2016_01_03 + SECONDS_IN_DAY,
2100 ]);
2101 let b = date_part(&a, DatePart::YearISO).unwrap();
2102 let actual = b.as_primitive::<Int32Type>();
2103 assert_eq!(2015, actual.value(0));
2104 assert_eq!(2015, actual.value(1));
2105 assert_eq!(2016, actual.value(2));
2106 }
2107
2108 #[test]
2109 fn test_ree_timestamp_year() {
2110 let vals: TimestampSecondArray =
2111 vec![Some(1514764800), Some(1550636625), Some(1550636625)].into();
2112 let run_ends = Int32Array::from(vec![1, 2, 3]);
2113 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2114
2115 let b = date_part(&ree, DatePart::Year).unwrap();
2116 let ree_result = b.as_run_opt::<Int32Type>().unwrap();
2117 let values = ree_result.values().as_primitive::<Int32Type>();
2118 assert_eq!(2018, values.value(0));
2119 assert_eq!(2019, values.value(1));
2120 assert_eq!(2019, values.value(2));
2121 }
2122
2123 #[test]
2124 fn test_ree_date64_month() {
2125 let vals: PrimitiveArray<Date64Type> =
2126 vec![Some(1514764800000), Some(1550636625000)].into();
2127 let run_ends = Int64Array::from(vec![2, 4]);
2128 let ree = RunArray::try_new(&run_ends, &vals).unwrap();
2129
2130 let b = date_part(&ree, DatePart::Month).unwrap();
2131 let ree_result = b.as_run_opt::<Int64Type>().unwrap();
2132 let values = ree_result.values().as_primitive::<Int32Type>();
2133 assert_eq!(1, values.value(0));
2134 assert_eq!(2, values.value(1));
2135 }
2136
2137 #[test]
2138 fn test_date_part_from_str() {
2139 let cases = [
2140 ("y", DatePart::Year),
2141 ("yr", DatePart::Year),
2142 ("year", DatePart::Year),
2143 ("years", DatePart::Year),
2144 ("YEAR", DatePart::Year),
2145 ("isoyear", DatePart::YearISO),
2146 ("qtr", DatePart::Quarter),
2147 ("quarter", DatePart::Quarter),
2148 ("quarters", DatePart::Quarter),
2149 ("mon", DatePart::Month),
2150 ("mons", DatePart::Month),
2151 ("month", DatePart::Month),
2152 ("MONTHS", DatePart::Month),
2153 ("w", DatePart::Week),
2154 ("week", DatePart::Week),
2155 ("isoweek", DatePart::WeekISO),
2156 ("d", DatePart::Day),
2157 ("day", DatePart::Day),
2158 ("dow", DatePart::DayOfWeekSunday0),
2159 ("DayOfWeek", DatePart::DayOfWeekSunday0),
2160 ("doy", DatePart::DayOfYear),
2161 ("DayOfYear", DatePart::DayOfYear),
2162 ("h", DatePart::Hour),
2163 ("hr", DatePart::Hour),
2164 ("hour", DatePart::Hour),
2165 ("m", DatePart::Minute),
2169 ("min", DatePart::Minute),
2170 ("mins", DatePart::Minute),
2171 ("minute", DatePart::Minute),
2172 ("s", DatePart::Second),
2173 ("sec", DatePart::Second),
2174 ("second", DatePart::Second),
2175 ("ms", DatePart::Millisecond),
2176 ("msec", DatePart::Millisecond),
2177 ("mseconds", DatePart::Millisecond),
2178 ("millisecond", DatePart::Millisecond),
2179 ("us", DatePart::Microsecond),
2180 ("usec", DatePart::Microsecond),
2181 ("useconds", DatePart::Microsecond),
2182 ("microsecond", DatePart::Microsecond),
2183 ("nanosecond", DatePart::Nanosecond),
2184 ("nanoseconds", DatePart::Nanosecond),
2185 ];
2186 for (input, expected) in cases {
2187 assert_eq!(
2188 DatePart::from_str(input).unwrap(),
2189 expected,
2190 "parsing {input}"
2191 );
2192 }
2193 }
2194
2195 #[test]
2196 fn test_date_part_from_str_unknown() {
2197 let unknown = [
2201 "epoch",
2202 "century",
2203 "decade",
2204 "millennium",
2205 "timezone",
2206 "timezone_hour",
2207 "timezone_minute",
2208 "isodow",
2209 " year ",
2212 "year ",
2213 "",
2214 "nope",
2215 ];
2216 for s in unknown {
2217 let err = DatePart::from_str(s).unwrap_err();
2218 assert!(
2219 matches!(err, ArrowError::InvalidArgumentError(_)),
2220 "expected InvalidArgumentError for {s:?}, got: {err}"
2221 );
2222 }
2223 }
2224}