Source code for time_split_app.widgets.time._duration

import datetime
from collections.abc import Iterable

import pandas as pd
import streamlit as st


[docs] class DurationWidget: """Duration specified by unit and count. Args: default_unit: Default unit. Must be in `units`. Default is ``units[0]``. units: An iterable of permitted units. default_periods: Default period counts per unit. """ def __init__( self, default_unit: str | None = None, units: Iterable[str] = ("days", "hours", "minutes"), default_periods: dict[str, int] | None = None, ) -> None: units = (*units,) if not units: raise ValueError("Need at least one unit.") if default_unit is None: self._unit = units[0] else: if default_unit not in units: raise ValueError(f"{default_unit=} must be in {units=}") self._unit = default_unit default_periods = {} if default_periods is None else default_periods.copy() for unit, periods in default_periods.items(): if periods <= 0: raise ValueError(f"Bad default {periods=} for {unit=}.") defaults = {"days": 7, "hours": 7 * 60, "minutes": 7 * 60 * 60} for unit in units: default = defaults.get(unit, 1) default_periods.setdefault(unit, default) self._units = units self._periods = default_periods
[docs] def select(self, label: str, *, horizontal: bool = False) -> datetime.timedelta: """Prompt user to select a duration. Args: label: Label to show. horizontal: If ``True``, show elements side-by-side. Returns: A timedelta. """ if horizontal: left, right = st.columns(2) else: container = st.container() left = right = container with right: unit = st.selectbox( f"select-{label}-unit", options=self._units, index=self._units.index(self._unit), label_visibility="collapsed", ) assert isinstance(unit, str) with left: periods = st.number_input( f"select-{label}-periods", min_value=1, max_value=None, value=self._periods[unit], label_visibility="collapsed", ) assert isinstance(periods, int) timedelta = pd.Timedelta(f"{periods} {unit}").to_pytimedelta() assert isinstance(timedelta, datetime.timedelta) return timedelta
[docs] def select_duration(label: str, *, horizontal: bool = False) -> datetime.timedelta: """See :meth:`DurationWidget.select`.""" return DurationWidget().select(label, horizontal=horizontal)