How could I format a Duration in a HH:MM:SS
format?
As a test sample, I have
fn main() {
let df = df! {
"a" => ["2022-11-21T12:00:00"],
"b" => ["2022-11-21T14:00:00"]
}
.unwrap()
.lazy()
.with_column(
col("a")
.str()
.strptime(StrpTimeOptions {
date_dtype: DataType::Datetime(TimeUnit::Milliseconds, None),
fmt: Some("%Y-%m-%dT%H:%M:%S".into()),
strict: false,
exact: true,
})
.alias("a"),
)
.with_column(
col("b")
.str()
.strptime(StrpTimeOptions {
date_dtype: DataType::Datetime(TimeUnit::Milliseconds, None),
fmt: Some("%Y-%m-%dT%H:%M:%S".into()),
strict: false,
exact: true,
})
.alias("b"),
)
.with_column((col("b") - col("a")).alias("duration"))
.collect()
.unwrap();
println!("{:?}", df);
}
It outputs
┌─────────────────────┬─────────────────────┬──────────────┐
│ a ┆ b ┆ duration │
│ --- ┆ --- ┆ --- │
│ datetime[ms] ┆ datetime[ms] ┆ duration[ms] │
╞═════════════════════╪═════════════════════╪══════════════╡
│ 2022-11-21 12:00:00 ┆ 2022-11-21 14:00:00 ┆ 2h │
└─────────────────────┴─────────────────────┴──────────────┘
How could I convert duration to "02:00:00" in the previous example?
Unfortunately I don't think you can do any better than this (but I'd love to be proved wrong).
.with_column(
col("duration")
.map(
|srs| {
Ok(srs
.duration()?
.into_iter()
.map(|d| {
d.map(|millisecs| {
let secs = millisecs / 1000;
let h = secs / (60 * 60);
let m = (secs / 60) % 60;
let s = secs % 60;
format!("{}:{:0<2}:{:0<2}", h, m, s)
})
})
.collect::<Utf8Chunked>()
.into_series())
},
GetOutput::from_type(DataType::Utf8),
)
.alias("duration_str"),
)
This leads to 2:00:00
. It's hardcoded that you're dealing with milliseconds; you might want to store a variable with the TimeUnit
and then switch over it to determine the denominator instead of always using 1000.