pythonpython-polars

Converting pl.Duration to human string


When printing a polars data frame, pl.Duration are printed in a "human format" by default. What function is used to do this conversion? Is it possible to use it? Trying "{}".format() returns something readable but not as good.

import polars as pl

data = {"end": ["2024/11/13 10:28:00",
                "2024/10/10 10:10:10",
                "2024/09/13 09:12:29",
                "2024/08/31 14:57:02",
               ],
        "start": ["2024/11/13 10:27:33",
                  "2024/10/10 10:01:01",
                  "2024/09/13 07:07:07",
                  "2024/08/25 13:48:28",
        ]
       }

df = pl.DataFrame(data)
df = df.with_columns(
        pl.col("end").str.to_datetime(),
        pl.col("start").str.to_datetime(),
        )

df = df.with_columns(
        duration = pl.col("end") - pl.col("start"),
        )
df = df.with_columns(
        pl.col("duration").map_elements(lambda t: "{}".format(t), return_dtype=pl.String()).alias("duration_str")
        )
print(df)
shape: (4, 4)
┌─────────────────────┬─────────────────────┬──────────────┬─────────────────┐
│ end                 ┆ start               ┆ duration     ┆ duration_str    │
│ ---                 ┆ ---                 ┆ ---          ┆ ---             │
│ datetime[μs]        ┆ datetime[μs]        ┆ duration[μs] ┆ str             │
╞═════════════════════╪═════════════════════╪══════════════╪═════════════════╡
│ 2024-11-13 10:28:00 ┆ 2024-11-13 10:27:33 ┆ 27s          ┆ 0:00:27         │
│ 2024-10-10 10:10:10 ┆ 2024-10-10 10:01:01 ┆ 9m 9s        ┆ 0:09:09         │
│ 2024-09-13 09:12:29 ┆ 2024-09-13 07:07:07 ┆ 2h 5m 22s    ┆ 2:05:22         │
│ 2024-08-31 14:57:02 ┆ 2024-08-25 13:48:28 ┆ 6d 1h 8m 34s ┆ 6 days, 1:08:34 │
└─────────────────────┴─────────────────────┴──────────────┴─────────────────┘

Solution

  • Polars 1.14.0 added Duration type support to .dt.to_string()

    It can produce iso and polars formatted strings.

    pl.select(
        pl.duration(hours=1, minutes=2).dt.to_string() # format="iso"
    ).item()
    
    # 'PT1H2M'
    
    pl.select(
        pl.duration(hours=1, minutes=2).dt.to_string(format="polars")
    ).item()
    
    # '1h 2m'