This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch 53.0.0-dev
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/53.0.0-dev by this push:
new bb5f12bd78 Make display of interval types more pretty (#6006)
bb5f12bd78 is described below
commit bb5f12bd784af8a9e42843aa572fe5fef89d5752
Author: kamille <[email protected]>
AuthorDate: Wed Jul 17 06:09:51 2024 +0800
Make display of interval types more pretty (#6006)
* improve dispaly for interval.
* update test in pretty, and fix display problem.
* tmp
* fix tests in arrow-cast.
* fix tests in pretty.
* fix style.
---
arrow-cast/src/cast/mod.rs | 26 +++---
arrow-cast/src/display.rs | 196 ++++++++++++++++++++++++++++++++++++---------
arrow-cast/src/pretty.rs | 54 ++++++-------
3 files changed, 196 insertions(+), 80 deletions(-)
diff --git a/arrow-cast/src/cast/mod.rs b/arrow-cast/src/cast/mod.rs
index c9de714e7d..3f9c9c8a33 100644
--- a/arrow-cast/src/cast/mod.rs
+++ b/arrow-cast/src/cast/mod.rs
@@ -4314,8 +4314,8 @@ mod tests {
IntervalUnit::YearMonth,
IntervalYearMonthArray,
vec![
- Some("1 years 1 mons 0 days 0 hours 0 mins 0.00 secs"),
- Some("2 years 7 mons 0 days 0 hours 0 mins 0.00 secs"),
+ Some("1 years 1 mons"),
+ Some("2 years 7 mons"),
None,
None,
None,
@@ -4338,9 +4338,9 @@ mod tests {
IntervalUnit::DayTime,
IntervalDayTimeArray,
vec![
- Some("0 years 0 mons 390 days 0 hours 0 mins 0.000 secs"),
- Some("0 years 0 mons 930 days 0 hours 0 mins 0.000 secs"),
- Some("0 years 0 mons 30 days 0 hours 0 mins 0.000 secs"),
+ Some("390 days"),
+ Some("930 days"),
+ Some("30 days"),
None,
None,
]
@@ -4366,16 +4366,16 @@ mod tests {
IntervalUnit::MonthDayNano,
IntervalMonthDayNanoArray,
vec![
- Some("0 years 13 mons 1 days 0 hours 0 mins 0.000000000 secs"),
+ Some("13 mons 1 days"),
None,
- Some("0 years 31 mons 35 days 0 hours 0 mins 0.001400000
secs"),
- Some("0 years 0 mons 3 days 0 hours 0 mins 0.000000000 secs"),
- Some("0 years 0 mons 0 days 0 hours 0 mins 8.000000000 secs"),
+ Some("31 mons 35 days 0.001400000 secs"),
+ Some("3 days"),
+ Some("8.000000000 secs"),
None,
- Some("0 years 0 mons 1 days 0 hours 0 mins 29.800000000 secs"),
- Some("0 years 3 mons 0 days 0 hours 0 mins 1.000000000 secs"),
- Some("0 years 0 mons 0 days 0 hours 8 mins 0.000000000 secs"),
- Some("0 years 63 mons 9 days 19 hours 9 mins 2.222000000
secs"),
+ Some("1 days 29.800000000 secs"),
+ Some("3 mons 1.000000000 secs"),
+ Some("8 mins"),
+ Some("63 mons 9 days 19 hours 9 mins 2.222000000 secs"),
None,
]
);
diff --git a/arrow-cast/src/display.rs b/arrow-cast/src/display.rs
index 6a40d03635..ab172cb240 100644
--- a/arrow-cast/src/display.rs
+++ b/arrow-cast/src/display.rs
@@ -654,10 +654,7 @@ impl<'a> DisplayIndex for &'a
PrimitiveArray<IntervalYearMonthType> {
let years = (interval / 12_f64).floor();
let month = interval - (years * 12_f64);
- write!(
- f,
- "{years} years {month} mons 0 days 0 hours 0 mins 0.00 secs",
- )?;
+ write!(f, "{years} years {month} mons",)?;
Ok(())
}
}
@@ -665,62 +662,181 @@ impl<'a> DisplayIndex for &'a
PrimitiveArray<IntervalYearMonthType> {
impl<'a> DisplayIndex for &'a PrimitiveArray<IntervalDayTimeType> {
fn write(&self, idx: usize, f: &mut dyn Write) -> FormatResult {
let value = self.value(idx);
+ let mut first_part = true;
- let secs = value.milliseconds / 1_000;
+ if value.days != 0 {
+ write!(f, "{} days", value.days)?;
+ first_part = false;
+ }
+
+ if value.milliseconds != 0 {
+ let millis_fmt = MillisecondsFormatter {
+ milliseconds: value.milliseconds,
+ first_part,
+ };
+
+ f.write_fmt(format_args!("{millis_fmt}"))?;
+ }
+
+ Ok(())
+ }
+}
+
+impl<'a> DisplayIndex for &'a PrimitiveArray<IntervalMonthDayNanoType> {
+ fn write(&self, idx: usize, f: &mut dyn Write) -> FormatResult {
+ let value = self.value(idx);
+ let mut first_part = true;
+
+ if value.months != 0 {
+ write!(f, "{} mons", value.months)?;
+ first_part = false;
+ }
+
+ if value.days != 0 {
+ if first_part {
+ write!(f, "{} days", value.days)?;
+ first_part = false;
+ } else {
+ write!(f, " {} days", value.days)?;
+ }
+ }
+
+ if value.nanoseconds != 0 {
+ let nano_fmt = NanosecondsFormatter {
+ nanoseconds: value.nanoseconds,
+ first_part,
+ };
+ f.write_fmt(format_args!("{nano_fmt}"))?;
+ }
+
+ Ok(())
+ }
+}
+
+struct NanosecondsFormatter {
+ nanoseconds: i64,
+ first_part: bool,
+}
+
+impl Display for NanosecondsFormatter {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut first_part = self.first_part;
+
+ let secs = self.nanoseconds / 1_000_000_000;
let mins = secs / 60;
let hours = mins / 60;
let secs = secs - (mins * 60);
let mins = mins - (hours * 60);
- let milliseconds = value.milliseconds % 1_000;
+ let nanoseconds = self.nanoseconds % 1_000_000_000;
- let secs_sign = if secs < 0 || milliseconds < 0 {
- "-"
- } else {
- ""
- };
+ if hours != 0 {
+ if first_part {
+ write!(f, "{} hours", hours)?;
+ first_part = false;
+ } else {
+ write!(f, " {} hours", hours)?;
+ }
+ }
+
+ if mins != 0 {
+ if first_part {
+ write!(f, "{} mins", mins)?;
+ first_part = false;
+ } else {
+ write!(f, " {} mins", mins)?;
+ }
+ }
+
+ if secs != 0 || nanoseconds != 0 {
+ let secs_sign = if secs < 0 || nanoseconds < 0 { "-" } else { "" };
+
+ if first_part {
+ write!(
+ f,
+ "{}{}.{:09} secs",
+ secs_sign,
+ secs.abs(),
+ nanoseconds.abs()
+ )?;
+ } else {
+ write!(
+ f,
+ " {}{}.{:09} secs",
+ secs_sign,
+ secs.abs(),
+ nanoseconds.abs()
+ )?;
+ }
+ }
- write!(
- f,
- "0 years 0 mons {} days {} hours {} mins {}{}.{:03} secs",
- value.days,
- hours,
- mins,
- secs_sign,
- secs.abs(),
- milliseconds.abs(),
- )?;
Ok(())
}
}
-impl<'a> DisplayIndex for &'a PrimitiveArray<IntervalMonthDayNanoType> {
- fn write(&self, idx: usize, f: &mut dyn Write) -> FormatResult {
- let value = self.value(idx);
+struct MillisecondsFormatter {
+ milliseconds: i32,
+ first_part: bool,
+}
+
+impl Display for MillisecondsFormatter {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut first_part = self.first_part;
- let secs = value.nanoseconds / 1_000_000_000;
+ let secs = self.milliseconds / 1_000;
let mins = secs / 60;
let hours = mins / 60;
let secs = secs - (mins * 60);
let mins = mins - (hours * 60);
- let nanoseconds = value.nanoseconds % 1_000_000_000;
-
- let secs_sign = if secs < 0 || nanoseconds < 0 { "-" } else { "" };
-
- write!(
- f,
- "0 years {} mons {} days {} hours {} mins {}{}.{:09} secs",
- value.months,
- value.days,
- hours,
- mins,
- secs_sign,
- secs.abs(),
- nanoseconds.abs(),
- )?;
+ let milliseconds = self.milliseconds % 1_000;
+
+ if hours != 0 {
+ if first_part {
+ write!(f, "{} hours", hours,)?;
+ first_part = false;
+ } else {
+ write!(f, " {} hours", hours,)?;
+ }
+ }
+
+ if mins != 0 {
+ if first_part {
+ write!(f, "{} mins", mins,)?;
+ first_part = false;
+ } else {
+ write!(f, " {} mins", mins,)?;
+ }
+ }
+
+ if secs != 0 || milliseconds != 0 {
+ let secs_sign = if secs < 0 || milliseconds < 0 {
+ "-"
+ } else {
+ ""
+ };
+
+ if first_part {
+ write!(
+ f,
+ "{}{}.{:03} secs",
+ secs_sign,
+ secs.abs(),
+ milliseconds.abs()
+ )?;
+ } else {
+ write!(
+ f,
+ " {}{}.{:03} secs",
+ secs_sign,
+ secs.abs(),
+ milliseconds.abs()
+ )?;
+ }
+ }
+
Ok(())
}
}
diff --git a/arrow-cast/src/pretty.rs b/arrow-cast/src/pretty.rs
index 9383b9f73f..f41471e38d 100644
--- a/arrow-cast/src/pretty.rs
+++ b/arrow-cast/src/pretty.rs
@@ -986,16 +986,16 @@ mod tests {
let table = pretty_format_batches(&[batch]).unwrap().to_string();
let expected = vec![
- "+----------------------------------------------------+",
- "| IntervalDayTime |",
- "+----------------------------------------------------+",
- "| 0 years 0 mons -1 days 0 hours -10 mins 0.000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins -1.001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins -0.001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.010 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.100 secs |",
- "+----------------------------------------------------+",
+ "+------------------+",
+ "| IntervalDayTime |",
+ "+------------------+",
+ "| -1 days -10 mins |",
+ "| -1.001 secs |",
+ "| -0.001 secs |",
+ "| 0.001 secs |",
+ "| 0.010 secs |",
+ "| 0.100 secs |",
+ "+------------------+",
];
let actual: Vec<&str> = table.lines().collect();
@@ -1032,23 +1032,23 @@ mod tests {
let table = pretty_format_batches(&[batch]).unwrap().to_string();
let expected = vec![
- "+-----------------------------------------------------------+",
- "| IntervalMonthDayNano |",
- "+-----------------------------------------------------------+",
- "| 0 years -1 mons -1 days 0 hours -10 mins 0.000000000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins -1.000000001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins -0.000000001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000000001 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000000010 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000000100 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000001000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000010000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.000100000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.001000000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.010000000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 0.100000000 secs |",
- "| 0 years 0 mons 0 days 0 hours 0 mins 1.000000000 secs |",
- "+-----------------------------------------------------------+",
+ "+--------------------------+",
+ "| IntervalMonthDayNano |",
+ "+--------------------------+",
+ "| -1 mons -1 days -10 mins |",
+ "| -1.000000001 secs |",
+ "| -0.000000001 secs |",
+ "| 0.000000001 secs |",
+ "| 0.000000010 secs |",
+ "| 0.000000100 secs |",
+ "| 0.000001000 secs |",
+ "| 0.000010000 secs |",
+ "| 0.000100000 secs |",
+ "| 0.001000000 secs |",
+ "| 0.010000000 secs |",
+ "| 0.100000000 secs |",
+ "| 1.000000000 secs |",
+ "+--------------------------+",
];
let actual: Vec<&str> = table.lines().collect();