Поляры (Rust), форматирование длительности в строку

Как я могу отформатировать Duration в формате HH:MM:SS?

В качестве тестового образца у меня есть

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);
}

Он выводит

┌─────────────────────┬─────────────────────┬──────────────┐
│ a                   ┆ b                   ┆ duration     │
│ ---                 ┆ ---                 ┆ ---          │
│ datetime[ms]        ┆ datetime[ms]        ┆ duration[ms] │
╞═════════════════════╪═════════════════════╪══════════════╡
│ 2022-11-21 12:00:00 ┆ 2022-11-21 14:00:00 ┆ 2h           │
└─────────────────────┴─────────────────────┴──────────────┘

Как преобразовать продолжительность в «02:00:00» в предыдущем примере?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
0
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

К сожалению, я не думаю, что вы можете сделать лучше, чем это (но я хотел бы оказаться неправым).

.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"),
)

Это приводит к 2:00:00. Жестко закодировано, что вы имеете дело с миллисекундами; вы можете сохранить переменную с помощью TimeUnit, а затем переключить ее, чтобы определить знаменатель, вместо того, чтобы всегда использовать 1000.

Как вау. Теперь я понимаю, почему я не могу заставить его работать 🙃. Спасибо. Могу я спросить вас, зачем нам нужна тройная карта? (Я все еще не знаком с Rust и Polars)

ohe 21.11.2022 19:18

@ohe Эти три карты совершенно разные 🙃 (если вы не используете Haskell или что-то еще, и в этом случае все карты одинаковы). Первый — это ленивое преобразование Expr (col("duration")). Второй — отображение итератора на серию с именем "duration". Третий — сопоставление с Option, которое применяет функцию к содержащемуся значению, если оно есть (если это Some).

BallpointBen 21.11.2022 20:40

Другие вопросы по теме