Skip to content

Commit e2f2749

Browse files
authored
Improve Display formatting of DataType::Timestamp (#8425)
# Which issue does this PR close? * Part of #8351 # Rationale for this change DataType:s end up in a lot of error messages, and we want them easy and readable, without and Rust-stuff in them like `Some` and `None` # What changes are included in this PR? Before: > `Timestamp(Millisecond, None)` > `Timestamp(Nanosecond, Some("UTC"))` After > `Timestamp(ms)` > `Timestamp(ns, "UTC")` # Are these changes tested? Yes # Are there any user-facing changes? Yes, this is a **breaking change**
1 parent f7ea0aa commit e2f2749

File tree

10 files changed

+107
-109
lines changed

10 files changed

+107
-109
lines changed

arrow-arith/src/temporal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ impl ExtractDatePartExt for PrimitiveArray<DurationNanosecondType> {
649649

650650
macro_rules! return_compute_error_with {
651651
($msg:expr, $param:expr) => {
652-
return { Err(ArrowError::ComputeError(format!("{}: {:?}", $msg, $param))) }
652+
return { Err(ArrowError::ComputeError(format!("{}: {}", $msg, $param))) }
653653
};
654654
}
655655

arrow-array/src/array/primitive_array.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,7 +2099,7 @@ mod tests {
20992099
let arr: PrimitiveArray<TimestampMillisecondType> =
21002100
TimestampMillisecondArray::from(vec![1546214400000, 1546214400000, -1546214400000]);
21012101
assert_eq!(
2102-
"PrimitiveArray<Timestamp(Millisecond, None)>\n[\n 2018-12-31T00:00:00,\n 2018-12-31T00:00:00,\n 1921-01-02T00:00:00,\n]",
2102+
"PrimitiveArray<Timestamp(ms)>\n[\n 2018-12-31T00:00:00,\n 2018-12-31T00:00:00,\n 1921-01-02T00:00:00,\n]",
21032103
format!("{arr:?}")
21042104
);
21052105
}
@@ -2110,7 +2110,7 @@ mod tests {
21102110
TimestampMillisecondArray::from(vec![1546214400000, 1546214400000, -1546214400000])
21112111
.with_timezone_utc();
21122112
assert_eq!(
2113-
"PrimitiveArray<Timestamp(Millisecond, Some(\"+00:00\"))>\n[\n 2018-12-31T00:00:00+00:00,\n 2018-12-31T00:00:00+00:00,\n 1921-01-02T00:00:00+00:00,\n]",
2113+
"PrimitiveArray<Timestamp(ms, \"+00:00\")>\n[\n 2018-12-31T00:00:00+00:00,\n 2018-12-31T00:00:00+00:00,\n 1921-01-02T00:00:00+00:00,\n]",
21142114
format!("{arr:?}")
21152115
);
21162116
}
@@ -2122,7 +2122,7 @@ mod tests {
21222122
TimestampMillisecondArray::from(vec![1546214400000, 1546214400000, -1546214400000])
21232123
.with_timezone("Asia/Taipei".to_string());
21242124
assert_eq!(
2125-
"PrimitiveArray<Timestamp(Millisecond, Some(\"Asia/Taipei\"))>\n[\n 2018-12-31T08:00:00+08:00,\n 2018-12-31T08:00:00+08:00,\n 1921-01-02T08:00:00+08:00,\n]",
2125+
"PrimitiveArray<Timestamp(ms, \"Asia/Taipei\")>\n[\n 2018-12-31T08:00:00+08:00,\n 2018-12-31T08:00:00+08:00,\n 1921-01-02T08:00:00+08:00,\n]",
21262126
format!("{arr:?}")
21272127
);
21282128
}
@@ -2137,7 +2137,7 @@ mod tests {
21372137
println!("{arr:?}");
21382138

21392139
assert_eq!(
2140-
"PrimitiveArray<Timestamp(Millisecond, Some(\"Asia/Taipei\"))>\n[\n 2018-12-31T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n 2018-12-31T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n 1921-01-02T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n]",
2140+
"PrimitiveArray<Timestamp(ms, \"Asia/Taipei\")>\n[\n 2018-12-31T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n 2018-12-31T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n 1921-01-02T00:00:00 (Unknown Time Zone 'Asia/Taipei'),\n]",
21412141
format!("{arr:?}")
21422142
);
21432143
}
@@ -2148,7 +2148,7 @@ mod tests {
21482148
TimestampMillisecondArray::from(vec![1546214400000, 1546214400000, -1546214400000])
21492149
.with_timezone("+08:00".to_string());
21502150
assert_eq!(
2151-
"PrimitiveArray<Timestamp(Millisecond, Some(\"+08:00\"))>\n[\n 2018-12-31T08:00:00+08:00,\n 2018-12-31T08:00:00+08:00,\n 1921-01-02T08:00:00+08:00,\n]",
2151+
"PrimitiveArray<Timestamp(ms, \"+08:00\")>\n[\n 2018-12-31T08:00:00+08:00,\n 2018-12-31T08:00:00+08:00,\n 1921-01-02T08:00:00+08:00,\n]",
21522152
format!("{arr:?}")
21532153
);
21542154
}
@@ -2159,7 +2159,7 @@ mod tests {
21592159
TimestampMillisecondArray::from(vec![1546214400000, 1546214400000, -1546214400000])
21602160
.with_timezone("xxx".to_string());
21612161
assert_eq!(
2162-
"PrimitiveArray<Timestamp(Millisecond, Some(\"xxx\"))>\n[\n 2018-12-31T00:00:00 (Unknown Time Zone 'xxx'),\n 2018-12-31T00:00:00 (Unknown Time Zone 'xxx'),\n 1921-01-02T00:00:00 (Unknown Time Zone 'xxx'),\n]",
2162+
"PrimitiveArray<Timestamp(ms, \"xxx\")>\n[\n 2018-12-31T00:00:00 (Unknown Time Zone 'xxx'),\n 2018-12-31T00:00:00 (Unknown Time Zone 'xxx'),\n 1921-01-02T00:00:00 (Unknown Time Zone 'xxx'),\n]",
21632163
format!("{arr:?}")
21642164
);
21652165
}
@@ -2175,7 +2175,7 @@ mod tests {
21752175
])
21762176
.with_timezone("America/Denver".to_string());
21772177
assert_eq!(
2178-
"PrimitiveArray<Timestamp(Millisecond, Some(\"America/Denver\"))>\n[\n 2022-03-13T01:59:59-07:00,\n 2022-03-13T03:00:00-06:00,\n 2022-11-06T00:59:59-06:00,\n 2022-11-06T01:00:00-06:00,\n]",
2178+
"PrimitiveArray<Timestamp(ms, \"America/Denver\")>\n[\n 2022-03-13T01:59:59-07:00,\n 2022-03-13T03:00:00-06:00,\n 2022-11-06T00:59:59-06:00,\n 2022-11-06T01:00:00-06:00,\n]",
21792179
format!("{arr:?}")
21802180
);
21812181
}
@@ -2193,7 +2193,7 @@ mod tests {
21932193
fn test_time32second_fmt_debug() {
21942194
let arr: PrimitiveArray<Time32SecondType> = vec![7201, 60054].into();
21952195
assert_eq!(
2196-
"PrimitiveArray<Time32(Second)>\n[\n 02:00:01,\n 16:40:54,\n]",
2196+
"PrimitiveArray<Time32(s)>\n[\n 02:00:01,\n 16:40:54,\n]",
21972197
format!("{arr:?}")
21982198
);
21992199
}
@@ -2203,8 +2203,8 @@ mod tests {
22032203
// chrono::NaiveDatetime::from_timestamp_opt returns None while input is invalid
22042204
let arr: PrimitiveArray<Time32SecondType> = vec![-7201, -60054].into();
22052205
assert_eq!(
2206-
"PrimitiveArray<Time32(Second)>\n[\n Cast error: Failed to convert -7201 to temporal for Time32(Second),\n Cast error: Failed to convert -60054 to temporal for Time32(Second),\n]",
2207-
// "PrimitiveArray<Time32(Second)>\n[\n null,\n null,\n]",
2206+
"PrimitiveArray<Time32(s)>\n[\n Cast error: Failed to convert -7201 to temporal for Time32(s),\n Cast error: Failed to convert -60054 to temporal for Time32(s),\n]",
2207+
// "PrimitiveArray<Time32(s)>\n[\n null,\n null,\n]",
22082208
format!("{arr:?}")
22092209
)
22102210
}
@@ -2214,7 +2214,7 @@ mod tests {
22142214
// replicate the issue from https://github.com/apache/arrow-datafusion/issues/3832
22152215
let arr: PrimitiveArray<TimestampMicrosecondType> = vec![9065525203050843594].into();
22162216
assert_eq!(
2217-
"PrimitiveArray<Timestamp(Microsecond, None)>\n[\n null,\n]",
2217+
"PrimitiveArray<Timestamp(µs)>\n[\n null,\n]",
22182218
format!("{arr:?}")
22192219
)
22202220
}
@@ -2855,7 +2855,7 @@ mod tests {
28552855
]
28562856
.into();
28572857
let debug_str = format!("{array:?}");
2858-
assert_eq!("PrimitiveArray<Time32(Second)>\n[\n Cast error: Failed to convert -1 to temporal for Time32(Second),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400 to temporal for Time32(Second),\n Cast error: Failed to convert 86401 to temporal for Time32(Second),\n null,\n]",
2858+
assert_eq!("PrimitiveArray<Time32(s)>\n[\n Cast error: Failed to convert -1 to temporal for Time32(s),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400 to temporal for Time32(s),\n Cast error: Failed to convert 86401 to temporal for Time32(s),\n null,\n]",
28592859
debug_str
28602860
);
28612861
}
@@ -2872,7 +2872,7 @@ mod tests {
28722872
]
28732873
.into();
28742874
let debug_str = format!("{array:?}");
2875-
assert_eq!("PrimitiveArray<Time32(Millisecond)>\n[\n Cast error: Failed to convert -1 to temporal for Time32(Millisecond),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000 to temporal for Time32(Millisecond),\n Cast error: Failed to convert 86401000 to temporal for Time32(Millisecond),\n null,\n]",
2875+
assert_eq!("PrimitiveArray<Time32(ms)>\n[\n Cast error: Failed to convert -1 to temporal for Time32(ms),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000 to temporal for Time32(ms),\n Cast error: Failed to convert 86401000 to temporal for Time32(ms),\n null,\n]",
28762876
debug_str
28772877
);
28782878
}
@@ -2890,7 +2890,7 @@ mod tests {
28902890
.into();
28912891
let debug_str = format!("{array:?}");
28922892
assert_eq!(
2893-
"PrimitiveArray<Time64(Nanosecond)>\n[\n Cast error: Failed to convert -1 to temporal for Time64(Nanosecond),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000000000 to temporal for Time64(Nanosecond),\n Cast error: Failed to convert 86401000000000 to temporal for Time64(Nanosecond),\n null,\n]",
2893+
"PrimitiveArray<Time64(ns)>\n[\n Cast error: Failed to convert -1 to temporal for Time64(ns),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000000000 to temporal for Time64(ns),\n Cast error: Failed to convert 86401000000000 to temporal for Time64(ns),\n null,\n]",
28942894
debug_str
28952895
);
28962896
}
@@ -2907,7 +2907,7 @@ mod tests {
29072907
]
29082908
.into();
29092909
let debug_str = format!("{array:?}");
2910-
assert_eq!("PrimitiveArray<Time64(Microsecond)>\n[\n Cast error: Failed to convert -1 to temporal for Time64(Microsecond),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000000 to temporal for Time64(Microsecond),\n Cast error: Failed to convert 86401000000 to temporal for Time64(Microsecond),\n null,\n]", debug_str);
2910+
assert_eq!("PrimitiveArray<Time64(µs)>\n[\n Cast error: Failed to convert -1 to temporal for Time64(µs),\n 00:00:00,\n 23:59:59,\n Cast error: Failed to convert 86400000000 to temporal for Time64(µs),\n Cast error: Failed to convert 86401000000 to temporal for Time64(µs),\n null,\n]", debug_str);
29112911
}
29122912

29132913
#[test]

arrow-array/src/builder/struct_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ mod tests {
690690

691691
#[test]
692692
#[should_panic(
693-
expected = "Incorrect datatype for StructArray field \\\"timestamp\\\", expected Timestamp(Nanosecond, Some(\\\"UTC\\\")) got Timestamp(Nanosecond, None)"
693+
expected = "Incorrect datatype for StructArray field \\\"timestamp\\\", expected Timestamp(ns, \\\"UTC\\\") got Timestamp(ns)"
694694
)]
695695
fn test_struct_array_mismatch_builder() {
696696
let fields = vec![Field::new(

arrow-cast/src/cast/decimal.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,7 @@ where
488488
parse_string_to_decimal_native::<T>(v, scale as usize)
489489
.map_err(|_| {
490490
ArrowError::CastError(format!(
491-
"Cannot cast string '{}' to value of {:?} type",
492-
v,
491+
"Cannot cast string '{v}' to value of {} type",
493492
T::DATA_TYPE,
494493
))
495494
})

arrow-cast/src/cast/mod.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4905,7 +4905,10 @@ mod tests {
49054905
format_options: FormatOptions::default(),
49064906
};
49074907
let err = cast_with_options(array, &to_type, &options).unwrap_err();
4908-
assert_eq!(err.to_string(), "Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(Second) type");
4908+
assert_eq!(
4909+
err.to_string(),
4910+
"Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(s) type"
4911+
);
49094912
}
49104913
}
49114914

@@ -4947,7 +4950,10 @@ mod tests {
49474950
format_options: FormatOptions::default(),
49484951
};
49494952
let err = cast_with_options(array, &to_type, &options).unwrap_err();
4950-
assert_eq!(err.to_string(), "Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(Millisecond) type");
4953+
assert_eq!(
4954+
err.to_string(),
4955+
"Cast error: Cannot cast string '08:08:61.091323414' to value of Time32(ms) type"
4956+
);
49514957
}
49524958
}
49534959

@@ -4981,7 +4987,10 @@ mod tests {
49814987
format_options: FormatOptions::default(),
49824988
};
49834989
let err = cast_with_options(array, &to_type, &options).unwrap_err();
4984-
assert_eq!(err.to_string(), "Cast error: Cannot cast string 'Not a valid time' to value of Time64(Microsecond) type");
4990+
assert_eq!(
4991+
err.to_string(),
4992+
"Cast error: Cannot cast string 'Not a valid time' to value of Time64(µs) type"
4993+
);
49854994
}
49864995
}
49874996

@@ -5015,7 +5024,10 @@ mod tests {
50155024
format_options: FormatOptions::default(),
50165025
};
50175026
let err = cast_with_options(array, &to_type, &options).unwrap_err();
5018-
assert_eq!(err.to_string(), "Cast error: Cannot cast string 'Not a valid time' to value of Time64(Nanosecond) type");
5027+
assert_eq!(
5028+
err.to_string(),
5029+
"Cast error: Cannot cast string 'Not a valid time' to value of Time64(ns) type"
5030+
);
50195031
}
50205032
}
50215033

@@ -8704,7 +8716,7 @@ mod tests {
87048716
};
87058717
assert_eq!(
87068718
t,
8707-
r#"Casting from Map(Field { "entries": Struct(key Utf8, value nullable Interval(DayTime)) }, false) to Map(Field { "entries": Struct(key Utf8, value Duration(Second)) }, true) not supported"#
8719+
r#"Casting from Map(Field { "entries": Struct(key Utf8, value nullable Interval(DayTime)) }, false) to Map(Field { "entries": Struct(key Utf8, value Duration(s)) }, true) not supported"#
87088720
);
87098721
}
87108722

arrow-cast/src/cast/string.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ fn parse_string_iter<
107107
.map(|x| match x {
108108
Some(v) => P::parse(v).ok_or_else(|| {
109109
ArrowError::CastError(format!(
110-
"Cannot cast string '{}' to value of {:?} type",
111-
v,
110+
"Cannot cast string '{v}' to value of {} type",
112111
P::DATA_TYPE
113112
))
114113
}),

arrow-schema/src/datatype.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,17 @@ pub enum TimeUnit {
454454
Nanosecond,
455455
}
456456

457+
impl std::fmt::Display for TimeUnit {
458+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459+
match self {
460+
TimeUnit::Second => write!(f, "s"),
461+
TimeUnit::Millisecond => write!(f, "ms"),
462+
TimeUnit::Microsecond => write!(f, "µs"),
463+
TimeUnit::Nanosecond => write!(f, "ns"),
464+
}
465+
}
466+
}
467+
457468
/// YEAR_MONTH, DAY_TIME, MONTH_DAY_NANO interval in SQL style.
458469
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
459470
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

arrow-schema/src/datatype_display.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,17 @@ impl fmt::Display for DataType {
5050
Self::Float32 => write!(f, "Float32"),
5151
Self::Float64 => write!(f, "Float64"),
5252
Self::Timestamp(time_unit, timezone) => {
53-
write!(f, "Timestamp({time_unit:?}, {timezone:?})")
53+
if let Some(timezone) = timezone {
54+
write!(f, "Timestamp({time_unit}, {timezone:?})")
55+
} else {
56+
write!(f, "Timestamp({time_unit})")
57+
}
5458
}
5559
Self::Date32 => write!(f, "Date32"),
5660
Self::Date64 => write!(f, "Date64"),
57-
Self::Time32(time_unit) => write!(f, "Time32({time_unit:?})"),
58-
Self::Time64(time_unit) => write!(f, "Time64({time_unit:?})"),
59-
Self::Duration(time_unit) => write!(f, "Duration({time_unit:?})"),
61+
Self::Time32(time_unit) => write!(f, "Time32({time_unit})"),
62+
Self::Time64(time_unit) => write!(f, "Time64({time_unit})"),
63+
Self::Duration(time_unit) => write!(f, "Duration({time_unit})"),
6064
Self::Interval(interval_unit) => write!(f, "Interval({interval_unit:?})"),
6165
Self::Binary => write!(f, "Binary"),
6266
Self::FixedSizeBinary(bytes_per_value) => {
@@ -131,13 +135,13 @@ impl fmt::Display for DataType {
131135
write!(f, "Union({union_fields:?}, {union_mode:?})")
132136
}
133137
Self::Dictionary(data_type, data_type1) => {
134-
write!(f, "Dictionary({data_type}, {data_type1:?})")
138+
write!(f, "Dictionary({data_type}, {data_type1})")
135139
}
136-
Self::Decimal32(precision, scale) => write!(f, "Decimal32({precision:?}, {scale:?})"),
137-
Self::Decimal64(precision, scale) => write!(f, "Decimal64({precision:?}, {scale:?})"),
138-
Self::Decimal128(precision, scale) => write!(f, "Decimal128({precision:?}, {scale:?})"),
139-
Self::Decimal256(precision, scale) => write!(f, "Decimal256({precision:?}, {scale:?})"),
140-
Self::Map(field, keys_are_sorted) => write!(f, "Map({field}, {keys_are_sorted:?})"),
140+
Self::Decimal32(precision, scale) => write!(f, "Decimal32({precision}, {scale})"),
141+
Self::Decimal64(precision, scale) => write!(f, "Decimal64({precision}, {scale})"),
142+
Self::Decimal128(precision, scale) => write!(f, "Decimal128({precision}, {scale})"),
143+
Self::Decimal256(precision, scale) => write!(f, "Decimal256({precision}, {scale})"),
144+
Self::Map(field, keys_are_sorted) => write!(f, "Map({field}, {keys_are_sorted})"),
141145
Self::RunEndEncoded(run_ends_field, values_field) => {
142146
write!(f, "RunEndEncoded({run_ends_field}, {values_field})")
143147
}

0 commit comments

Comments
 (0)