Skip to content

Commit

Permalink
Make display of interval types more pretty (#6006)
Browse files Browse the repository at this point in the history
* improve dispaly for interval.

* update test in pretty, and fix display problem.

* tmp

* fix tests in arrow-cast.

* fix tests in pretty.

* fix style.
  • Loading branch information
Rachelint authored Jul 16, 2024
1 parent 8f76248 commit bb5f12b
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 80 deletions.
26 changes: 13 additions & 13 deletions arrow-cast/src/cast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
]
Expand All @@ -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,
]
);
Expand Down
196 changes: 156 additions & 40 deletions arrow-cast/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,73 +654,189 @@ 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(())
}
}

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(())
}
}
Expand Down
54 changes: 27 additions & 27 deletions arrow-cast/src/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit bb5f12b

Please sign in to comment.