alamb commented on code in PR #7189: URL: https://github.com/apache/arrow-rs/pull/7189#discussion_r1984944810
########## arrow-arith/src/temporal.rs: ########## @@ -488,25 +492,31 @@ impl ExtractDatePartExt for PrimitiveArray<IntervalMonthDayNanoType> { fn date_part(&self, part: DatePart) -> Result<Int32Array, ArrowError> { match part { DatePart::Year => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months / 12))), - DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months))), + DatePart::Month => Ok(self.unary_opt(|d: IntervalMonthDayNano| Some(d.months % 12))), Review Comment: Postgres agrees ```sql postgres=# SELECT extract (month from interval '12 month'); extract --------- 0 (1 row) ``` Before this PR arrow also currently says 12. ```sql > SELECT datepart('month', interval '12 month'); +---------------------------------------------------------------------------------------------------------------+ | date_part(Utf8("month"),IntervalMonthDayNano("IntervalMonthDayNano { months: 12, days: 0, nanoseconds: 0 }")) | +---------------------------------------------------------------------------------------------------------------+ | 12 | +---------------------------------------------------------------------------------------------------------------+ 1 row(s) fetched. Elapsed 0.001 seconds. ``` I think this change makes sense ########## arrow-arith/src/temporal.rs: ########## @@ -464,11 +464,15 @@ impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> { DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))), DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))), DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))), - DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000)))), - DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000))), - DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds))), - DatePart::Microsecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000))), - DatePart::Nanosecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000_000))), + DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))), + DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))), + DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))), + DatePart::Microsecond => { + Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000))) + } + DatePart::Nanosecond => { + Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000))) + } Review Comment: This is a behavior change for arrow-rs. # duckdb says 1 ```sql SELECT datepart('s', interval '1m 61s 33ms 44us'); ┌─────────────────────────────────────────────────────┐ │ datepart('s', CAST('1m 61s 33ms 44us' AS INTERVAL)) │ │ int64 │ ├─────────────────────────────────────────────────────┤ │ 1 │ └─────────────────────────────────────────────────────┘ ``` # postgres says almost 1: ```sql postgres=# SELECT extract (seconds from interval '1m 61s 33ms 44us'); extract ---------- 1.033044 (1 row) ``` Arrow says `121` (before this PR) ```sql > SELECT datepart('s', interval '1m 61s 33ms 44us'); +---------------------------------------------------------------------------------------------------------------------+ | date_part(Utf8("s"),IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 0, nanoseconds: 121033044000 }")) | +---------------------------------------------------------------------------------------------------------------------+ | 121 | +---------------------------------------------------------------------------------------------------------------------+ 1 row(s) fetched. Elapsed 0.004 seconds. ``` ########## arrow-arith/src/temporal.rs: ########## @@ -464,11 +464,15 @@ impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> { DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))), DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))), DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))), Review Comment: For the record, the current arrow behavior is the same it seems: ``` > SELECT datepart('hour', interval '25 hour'); +--------------------------------------------------------------------------------------------------------------------------+ | date_part(Utf8("hour"),IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 0, nanoseconds: 90000000000000 }")) | +--------------------------------------------------------------------------------------------------------------------------+ | 25 | +--------------------------------------------------------------------------------------------------------------------------+ 1 row(s) fetched. Elapsed 0.030 seconds. > SELECT datepart('day', interval '25 hour'); +-------------------------------------------------------------------------------------------------------------------------+ | date_part(Utf8("day"),IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 0, nanoseconds: 90000000000000 }")) | +-------------------------------------------------------------------------------------------------------------------------+ | 0 | +-------------------------------------------------------------------------------------------------------------------------+ ``` ########## arrow-arith/src/temporal.rs: ########## @@ -464,11 +464,15 @@ impl ExtractDatePartExt for PrimitiveArray<IntervalDayTimeType> { DatePart::Week => Ok(self.unary_opt(|d| Some(d.days / 7))), DatePart::Day => Ok(self.unary_opt(|d| Some(d.days))), DatePart::Hour => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 60 * 1_000)))), - DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000)))), - DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000))), - DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds))), - DatePart::Microsecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000))), - DatePart::Nanosecond => Ok(self.unary_opt(|d| d.milliseconds.checked_mul(1_000_000))), + DatePart::Minute => Ok(self.unary_opt(|d| Some(d.milliseconds / (60 * 1_000) % 60))), + DatePart::Second => Ok(self.unary_opt(|d| Some(d.milliseconds / 1_000 % 60))), + DatePart::Millisecond => Ok(self.unary_opt(|d| Some(d.milliseconds % (60 * 1_000)))), + DatePart::Microsecond => { + Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000))) + } + DatePart::Nanosecond => { + Ok(self.unary_opt(|d| (d.milliseconds % (60 * 1_000)).checked_mul(1_000_000))) + } Review Comment: Same thing for millisecond and microseconds -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@arrow.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org