great_tables
  • Get Started
  • Examples
  • Reference
  • Blog

On this page

  • Parameters
  • Returns
  • Output units for the colon-separated duration style
  • Compatibility of formatting function with data values
  • Examples
  • See Also

GT.fmt_duration

GT.fmt_duration(
    self,
    columns=None,
    rows=None,
    input_units=None,
    output_units=None,
    duration_style='narrow',
    trim_zero_units=True,
    max_output_units=None,
    pattern='{x}',
    use_seps=True,
    sep_mark=',',
    force_sign=False,
    locale=None,
)

Format numeric or duration values as styled time duration strings.

Format input values to time duration values whether those input values are numbers or of the timedelta class. We can specify which time units any numeric input values have (as weeks, days, hours, minutes, or seconds) and the output can be customized with a duration style (corresponding to narrow, wide, colon-separated, and ISO forms) and a choice of output units ranging from weeks to seconds.

Parameters

columns : SelectExpr = None

The columns to target. Can either be a single column name or a series of column names provided in a list.

rows : int | list[int] | None = None

In conjunction with columns=, we can specify which of their rows should undergo formatting. The default is all rows, resulting in all rows in targeted columns being formatted. Alternatively, we can supply a list of row indices.

input_units : str | None = None

If one or more selected columns contains numeric values (not timedelta values, which contain the duration units), a keyword must be provided for input_units for the values to be interpreted in terms of duration. The accepted units are: "seconds", "minutes", "hours", "days", and "weeks". This is required for numeric columns and ignored for timedelta columns.

output_units : str | list[str] | None = None

Controls the output time units. The default (None) means that output units will be automatically chosen based on the input duration value. To control which time units are to be considered for output (before trimming with trim_zero_units=) we can specify a list of one or more of the following keywords: "weeks", "days", "hours", "minutes", or "seconds".

duration_style : DurationStyle = 'narrow'

A choice of four formatting styles for the output duration values. With "narrow" (the default style), duration values will be formatted with single-letter time-part units (e.g., 1.35 days will be styled as "1d 8h 24m"). With "wide", this example value will be expanded to "1 day 8 hours 24 minutes" after formatting. The "colon-sep" style will put days, hours, minutes, and seconds in the "([D]/)[HH]:[MM]:[SS]" format. The "iso" style will produce a value that conforms to the ISO 8601 rules for duration values (e.g., 1.35 days will become "P1DT8H24M").

trim_zero_units : bool | list[str] = True

Provides methods to remove output time units that have zero values. By default this is True and duration values that might otherwise be formatted as "0w 1d 0h 4m 19s" with trim_zero_units=False are instead displayed as "1d 4m 19s". Aside from using True/False we could provide a list of keywords for more precise control. These keywords are: (1) "leading", to omit all leading zero-value time units (e.g., "0w 1d" -> "1d"), (2) "trailing", to omit all trailing zero-value time units (e.g., "3d 5h 0s" -> "3d 5h"), and (3) "internal", which removes all internal zero-value time units (e.g., "5d 0h 33m" -> "5d 33m").

max_output_units : int | None = None

If output_units is None, where the output time units are unspecified and left to be handled automatically, a numeric value provided for max_output_units= will be taken as the maximum number of time units to display in all output time duration values. By default, this is None and all possible time units will be displayed. This option has no effect when duration_style="colon-sep" (only output_units can be used to customize that type of duration output).

pattern : str = '{x}'

A formatting pattern that allows for decoration of the formatted value. The formatted value is represented by the {x} (which can be used multiple times, if needed) and all other characters will be interpreted as string literals.

use_seps : bool = True

The use_seps option allows for the use of digit group separators. The type of digit group separator is set by sep_mark and overridden if a locale ID is provided to locale. This setting is True by default.

sep_mark : str = ','

The string to use as a separator between groups of digits. For example, using sep_mark="," with a value of 1000 would result in a formatted value of "1,000". This argument is ignored if a locale is supplied (i.e., is not None).

force_sign : bool = False

Should the positive sign be shown for positive values (effectively showing a sign for all values except zero)? If so, use True for this option. The default is False, where only negative numbers will display a minus sign.

locale : str | None = None

An optional locale identifier that can be used for formatting values according the locale’s rules. Examples include "en" for English (United States) and "fr" for French (France).

Returns

: GT

The GT object is returned. This is the same object that the method is called on so that we can facilitate method chaining.

Output units for the colon-separated duration style

The colon-separated duration style (enabled when duration_style="colon-sep") is essentially a clock-based output format which uses the display logic of chronograph watch functionality. It will, by default, display duration values in the (D/)HH:MM:SS format. Any duration values greater than or equal to 24 hours will have the number of days prepended with an adjoining slash mark. While this output format is versatile, it can be changed somewhat with the output_units= option. The following combinations of output units are permitted:

  • ["minutes", "seconds"] -> MM:SS
  • ["hours", "minutes"] -> HH:MM
  • ["hours", "minutes", "seconds"] -> HH:MM:SS
  • ["days", "hours", "minutes"] -> (D/)HH:MM

Any other specialized combinations will result in the default set being used, which is ["days", "hours", "minutes", "seconds"].

Compatibility of formatting function with data values

fmt_duration() is compatible with body cells that are of int, float, or datetime.timedelta types. Any other types of body cells are ignored during formatting.

Examples

Let’s create a table with duration values in seconds and format them using the default narrow style. This produces compact output with single-letter unit abbreviations, ideal for space-constrained displays.

import pandas as pd
from great_tables import GT

df = pd.DataFrame({"duration_s": [3661, 86400, 172800, 60, 0]})

(
    GT(df)
    .fmt_duration(columns="duration_s", input_units="seconds")
)
duration_s
1h 1m 1s
1d
2d
1m
0s

Notice that zero-valued time units are automatically trimmed from the output, keeping the display clean. A value of 86400 seconds (exactly 1 day) simply shows "1d" rather than "0w 1d 0h 0m 0s".

For reporting contexts where readability is more important than compactness, the wide style spells out the full unit names with proper singular/plural forms.

df = pd.DataFrame({"hours": [1.5, 24.0, 0.5, 100.75]})

(
    GT(df)
    .fmt_duration(columns="hours", input_units="hours", duration_style="wide")
)
hours
1 hour 30 minutes
1 day
30 minutes
4 days 4 hours 45 minutes

The colon-separated style is useful for timing data, race results, or any context where a clock-like display is expected. Days are shown with a slash prefix when the duration is 24 hours or more.

df = pd.DataFrame({
    "event": ["Marathon", "Half Marathon", "10K", "Mile"],
    "winning_time_s": [7377, 3542, 1620, 233],
})

(
    GT(df)
    .fmt_duration(
        columns="winning_time_s",
        input_units="seconds",
        duration_style="colon-sep",
        output_units=["hours", "minutes", "seconds"],
    )
)
event winning_time_s
Marathon 02:02:57
Half Marathon 00:59:02
10K 00:27:00
Mile 00:03:53

The output is zero-padded in the familiar HH:MM:SS format. By specifying output_units we control exactly which components appear in the colon-separated output.

When working with timedelta columns (common in Pandas when computing differences between timestamps), fmt_duration() automatically detects the units—no input_units argument is needed.

from datetime import datetime

events = pd.DataFrame({
    "task": ["Build", "Test suite", "Deploy", "Full pipeline"],
    "elapsed": [
        datetime(2024, 1, 1, 0, 12, 45) - datetime(2024, 1, 1, 0, 0, 0),
        datetime(2024, 1, 1, 1, 5, 30) - datetime(2024, 1, 1, 0, 0, 0),
        datetime(2024, 1, 1, 0, 3, 15) - datetime(2024, 1, 1, 0, 0, 0),
        datetime(2024, 1, 1, 1, 21, 30) - datetime(2024, 1, 1, 0, 0, 0),
    ],
})

(
    GT(events, rowname_col="task")
    .fmt_duration(columns="elapsed", duration_style="narrow")
)
elapsed
Build 12m 45s
Test suite 1h 5m 30s
Deploy 3m 15s
Full pipeline 1h 21m 30s

Polars DataFrames work the same way. Here we format numeric duration values using the ISO 8601 duration style, which is useful for machine-readable output or standards-compliant reporting.

import polars as pl
from great_tables import GT

df = pl.DataFrame({"activity": ["Flight", "Layover", "Drive"], "seconds": [14400, 5400, 1830]})

(
    GT(df)
    .fmt_duration(columns="seconds", input_units="seconds", duration_style="iso")
)
activity seconds
Flight P4H
Layover P1H30M
Drive P30M30S

Polars also has native Duration dtype columns (created via temporal arithmetic or timedelta values). These are handled automatically without needing to specify input_units.

from datetime import timedelta

df = pl.DataFrame({
    "segment": ["Warm-up", "Main set", "Cool-down"],
    "duration": [timedelta(minutes=10), timedelta(minutes=45, seconds=30), timedelta(minutes=5)],
})

(
    GT(df)
    .fmt_duration(columns="duration", duration_style="wide")
)
segment duration
Warm-up 10 minutes
Main set 45 minutes 30 seconds
Cool-down 5 minutes

See Also

The functional version of this method, val_fmt_duration(), allows you to format a single numerical value (or a list of them).