This is an automated email from the ASF dual-hosted git repository.
mneumann pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new ab9c062789 fix: fixed trait functions clash
get_date_time_part_extract_fn (#8221) (#9424)
ab9c062789 is described below
commit ab9c0627892586e5e45832999253d2877a54c3d4
Author: Mateusz Matejuk <[email protected]>
AuthorDate: Thu Feb 19 10:49:00 2026 +0100
fix: fixed trait functions clash get_date_time_part_extract_fn (#8221)
(#9424)
# Which issue does this PR close?
fixes #8221
# Rationale for this change
It blocks users from building if the overall build state in Cargo.lock
has `Chrono` in versions >= 0.4.40.
Recently `Chrono` added `quarter()` function that clashes with
`Datelike`'s, and requires disambiguation, or build will fail. That also
makes users unable to use it in larger projects.
# What changes are included in this PR?
`arrow-rs/arrow-arith/src/temporal.rs:91`
`get_date_time_part_extract_fn()`
I forced `DatePart::Quarter` to return `Datelike::quarter()`.
With versions < 0.4.40 of `Chrono` it worked since it did not export
this function.
# Are these changes tested?
Full testing suite is not failing.
I added a few tests confirming that quarter() does it job, but those are
not regression tests. Those will only test if the quarter() actually
works.
Build-related tests are difficult to achieve and require extra setup,
moreover are very fragile.
Benchmarks were run, no deviation was found.
# Are there any user-facing changes?
No, users should not be affected.
---------
Co-authored-by: Marco Neumann <[email protected]>
---
arrow-arith/src/temporal.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 73 insertions(+), 1 deletion(-)
diff --git a/arrow-arith/src/temporal.rs b/arrow-arith/src/temporal.rs
index 771d0f97b7..12970f4498 100644
--- a/arrow-arith/src/temporal.rs
+++ b/arrow-arith/src/temporal.rs
@@ -93,8 +93,10 @@ where
T: ChronoDateExt + Datelike + Timelike,
{
match part {
- DatePart::Quarter => |d| d.quarter() as i32,
DatePart::Year => |d| d.year(),
+ // Datelike and ChronoDataExt does export .quarter() function
+ // for this case we needs to be clarified which version are we using
+ DatePart::Quarter => |d| Datelike::quarter(&d) as i32,
DatePart::YearISO => |d| d.iso_week().year(),
DatePart::Month => |d| d.month() as i32,
DatePart::Week | DatePart::WeekISO => |d| d.iso_week().week() as i32,
@@ -791,6 +793,76 @@ mod tests {
assert_eq!(1, b.value(0));
}
+ #[test]
+ fn test_all_quarters_date64() {
+ // verify all 4 quarters return 1-4 (not 0-indexed!)
+ // 1767225600000 -> 2026-01-01 (Q1)
+ // 1775001600000 -> 2026-04-01 (Q2, +90 days: jan31+feb28+mar31)
+ // 1782864000000 -> 2026-07-01 (Q3, +181 days)
+ // 1790812800000 -> 2026-10-01 (Q4, +273 days)
+ let a: PrimitiveArray<Date64Type> = vec![
+ Some(1767225600000),
+ Some(1775001600000),
+ Some(1782864000000),
+ Some(1790812800000),
+ None,
+ ]
+ .into();
+
+ let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
+ assert_eq!(1, b.value(0)); // jan -> q1
+ assert_eq!(2, b.value(1)); // apr -> q2
+ assert_eq!(3, b.value(2)); // jul -> q3
+ assert_eq!(4, b.value(3)); // oct -> q4
+ assert!(!b.is_valid(4));
+ }
+
+ #[test]
+ fn test_all_quarters_date32() {
+ // verify all 4 quarters for Date32 (days since epoch)
+ // 20454 -> 2026-01-01 (Q1)
+ // 20544 -> 2026-04-01 (Q2, +90 days)
+ // 20635 -> 2026-07-01 (Q3, +181 days)
+ // 20727 -> 2026-10-01 (Q4, +273 days)
+ let a: PrimitiveArray<Date32Type> =
+ vec![Some(20454), Some(20544), Some(20635), Some(20727),
None].into();
+
+ let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
+ 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));
+ }
+
+ #[test]
+ fn test_quarter_timestamp_microsecond() {
+ // timestamps are in microseconds (ms * 1000)
+ // 1767225600000000 -> 2026-01-01 (Q1)
+ // 1782864000000000 -> 2026-07-01 (Q3)
+ let a: TimestampMicrosecondArray =
+ vec![Some(1767225600000000), None, Some(1782864000000000)].into();
+
+ let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
+ assert_eq!(1, b.value(0));
+ assert!(!b.is_valid(1));
+ assert_eq!(3, b.value(2));
+ }
+
+ #[test]
+ fn test_quarter_timestamp_nanosecond() {
+ // same as `test_quarter_timestamp_microsecond` but nanosecond
precision (ms * 1_000_000)
+ // 1775001600000000000 -> 2026-04-01 (Q2)
+ // 1790812800000000000 -> 2026-10-01 (Q4)
+ let a: TimestampNanosecondArray =
+ vec![Some(1775001600000000000), None,
Some(1790812800000000000)].into();
+
+ let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
+ assert_eq!(2, b.value(0));
+ assert!(!b.is_valid(1));
+ assert_eq!(4, b.value(2));
+ }
+
#[test]
fn test_temporal_array_date64_month() {
//1514764800000 -> 2018-01-01