Source code for time_split_app.widgets.time._duration

import datetime
from typing import Self

import pandas as pd
import streamlit as st

from time_split_app import config


[docs] class DurationWidget: """Duration specified by unit and count. Args: default_unit: Default unit; must be a key in `periods`. periods: A dict ``{unit: default_periods}``. """ def __init__( self, default_unit: str, *, periods: dict[str, int], ) -> None: self._unit = default_unit self._periods = periods
[docs] @classmethod def from_delta(cls, delta: datetime.timedelta | int, date_only: bool | None = None) -> Self: if isinstance(delta, int): delta = datetime.timedelta(days=delta) if date_only is None: date_only = config.DATE_ONLY units = ["days"] if date_only: default_unit = "days" else: default_unit = "minutes" units.extend(("seconds", "minutes", "hours")) periods = {} for unit in units: kwargs = {unit: 1} n = delta / datetime.timedelta(**kwargs) periods[unit] = round(n) return cls(default_unit, periods=periods)
[docs] def select(self, label: str, *, horizontal: bool = True) -> 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: with st.container(key=f"tight-columns-DurationWidget.select-{label}"): left, right = st.columns(2) else: container = st.container() left = right = container with right: options = [*self._periods] unit = st.selectbox( f"select-{label}-unit", options=options, index=options.index(self._unit), label_visibility="collapsed", disabled=len(options) == 1, ) 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 = True, delta: datetime.timedelta | int = 7, date_only: bool | None = None, ) -> datetime.timedelta: """See :meth:`DurationWidget.select`.""" return DurationWidget.from_delta(delta, date_only).select(label, horizontal=horizontal)