Skip to content

Commit ab9c062

Browse files
esaviercrepererum
andauthored
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 <marco@crepererum.net>
1 parent c129c7c commit ab9c062

1 file changed

Lines changed: 73 additions & 1 deletion

File tree

arrow-arith/src/temporal.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ where
9393
T: ChronoDateExt + Datelike + Timelike,
9494
{
9595
match part {
96-
DatePart::Quarter => |d| d.quarter() as i32,
9796
DatePart::Year => |d| d.year(),
97+
// Datelike and ChronoDataExt does export .quarter() function
98+
// for this case we needs to be clarified which version are we using
99+
DatePart::Quarter => |d| Datelike::quarter(&d) as i32,
98100
DatePart::YearISO => |d| d.iso_week().year(),
99101
DatePart::Month => |d| d.month() as i32,
100102
DatePart::Week | DatePart::WeekISO => |d| d.iso_week().week() as i32,
@@ -791,6 +793,76 @@ mod tests {
791793
assert_eq!(1, b.value(0));
792794
}
793795

796+
#[test]
797+
fn test_all_quarters_date64() {
798+
// verify all 4 quarters return 1-4 (not 0-indexed!)
799+
// 1767225600000 -> 2026-01-01 (Q1)
800+
// 1775001600000 -> 2026-04-01 (Q2, +90 days: jan31+feb28+mar31)
801+
// 1782864000000 -> 2026-07-01 (Q3, +181 days)
802+
// 1790812800000 -> 2026-10-01 (Q4, +273 days)
803+
let a: PrimitiveArray<Date64Type> = vec![
804+
Some(1767225600000),
805+
Some(1775001600000),
806+
Some(1782864000000),
807+
Some(1790812800000),
808+
None,
809+
]
810+
.into();
811+
812+
let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
813+
assert_eq!(1, b.value(0)); // jan -> q1
814+
assert_eq!(2, b.value(1)); // apr -> q2
815+
assert_eq!(3, b.value(2)); // jul -> q3
816+
assert_eq!(4, b.value(3)); // oct -> q4
817+
assert!(!b.is_valid(4));
818+
}
819+
820+
#[test]
821+
fn test_all_quarters_date32() {
822+
// verify all 4 quarters for Date32 (days since epoch)
823+
// 20454 -> 2026-01-01 (Q1)
824+
// 20544 -> 2026-04-01 (Q2, +90 days)
825+
// 20635 -> 2026-07-01 (Q3, +181 days)
826+
// 20727 -> 2026-10-01 (Q4, +273 days)
827+
let a: PrimitiveArray<Date32Type> =
828+
vec![Some(20454), Some(20544), Some(20635), Some(20727), None].into();
829+
830+
let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
831+
assert_eq!(1, b.value(0));
832+
assert_eq!(2, b.value(1));
833+
assert_eq!(3, b.value(2));
834+
assert_eq!(4, b.value(3));
835+
assert!(!b.is_valid(4));
836+
}
837+
838+
#[test]
839+
fn test_quarter_timestamp_microsecond() {
840+
// timestamps are in microseconds (ms * 1000)
841+
// 1767225600000000 -> 2026-01-01 (Q1)
842+
// 1782864000000000 -> 2026-07-01 (Q3)
843+
let a: TimestampMicrosecondArray =
844+
vec![Some(1767225600000000), None, Some(1782864000000000)].into();
845+
846+
let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
847+
assert_eq!(1, b.value(0));
848+
assert!(!b.is_valid(1));
849+
assert_eq!(3, b.value(2));
850+
}
851+
852+
#[test]
853+
fn test_quarter_timestamp_nanosecond() {
854+
// same as `test_quarter_timestamp_microsecond` but nanosecond precision (ms * 1_000_000)
855+
// 1775001600000000000 -> 2026-04-01 (Q2)
856+
// 1790812800000000000 -> 2026-10-01 (Q4)
857+
let a: TimestampNanosecondArray =
858+
vec![Some(1775001600000000000), None, Some(1790812800000000000)].into();
859+
860+
let b = date_part_primitive(&a, DatePart::Quarter).unwrap();
861+
assert_eq!(2, b.value(0));
862+
assert!(!b.is_valid(1));
863+
assert_eq!(4, b.value(2));
864+
}
865+
794866
#[test]
795867
fn test_temporal_array_date64_month() {
796868
//1514764800000 -> 2018-01-01

0 commit comments

Comments
 (0)