Skip to content

add_interval

yohou.utils.validation.add_interval(start, interval, n=1)

Add n intervals to a datetime (handles variable-length intervals).

Supports multi-period intervals like "2mo", "3mo", "6mo", etc.

Parameters

Name Type Description Default
start datetime

Starting datetime.

required
interval str or timedelta

Interval string like "1d", "1mo", "3mo", "1q", "1y" or a timedelta.

required
n int

Number of intervals to add.

1

Returns

Type Description
datetime

Result datetime.

Examples

>>> from datetime import datetime
>>> add_interval(datetime(2020, 1, 15), "1d", 5)
datetime.datetime(2020, 1, 20, 0, 0)
>>> add_interval(datetime(2020, 1, 31), "1mo", 1)
datetime.datetime(2020, 2, 29, 0, 0)
>>> add_interval(datetime(2020, 1, 31), "2mo", 2)
datetime.datetime(2020, 5, 31, 0, 0)

See Also

Source Code

Show/Hide source
def add_interval(start: datetime, interval: str | timedelta, n: int = 1) -> datetime:
    r"""Add n intervals to a datetime (handles variable-length intervals).

    Supports multi-period intervals like "2mo", "3mo", "6mo", etc.

    Parameters
    ----------
    start : datetime
        Starting datetime.

    interval : str or timedelta
        Interval string like "1d", "1mo", "3mo", "1q", "1y" or a timedelta.

    n : int, default=1
        Number of intervals to add.

    Returns
    -------
    datetime
        Result datetime.

    Examples
    --------
    >>> from datetime import datetime
    >>> add_interval(datetime(2020, 1, 15), "1d", 5)
    datetime.datetime(2020, 1, 20, 0, 0)
    >>> add_interval(datetime(2020, 1, 31), "1mo", 1)
    datetime.datetime(2020, 2, 29, 0, 0)
    >>> add_interval(datetime(2020, 1, 31), "2mo", 2)
    datetime.datetime(2020, 5, 31, 0, 0)

    See Also
    --------
    - [`parse_interval`][yohou.utils.validation.parse_interval] : Parse interval string into multiplier and unit.
    - [`interval_to_timedelta`][yohou.utils.validation.interval_to_timedelta] : Convert interval string to timedelta.
    - [`check_interval_consistency`][yohou.utils.validation.check_interval_consistency] : Validate uniform time spacing.

    """
    if isinstance(interval, timedelta):
        return start + (interval * n)

    multiplier, unit = parse_interval(interval)
    total_units = multiplier * n

    if unit == "d":
        return start + timedelta(days=total_units)
    elif unit == "h":
        return start + timedelta(hours=total_units)
    elif unit == "m":
        return start + timedelta(minutes=total_units)
    elif unit == "s":
        return start + timedelta(seconds=total_units)
    elif unit == "w":
        return start + timedelta(weeks=total_units)
    elif unit == "mo":
        # Add months with day-of-month preservation
        month = start.month - 1 + total_units
        year = start.year + month // 12
        month = month % 12 + 1
        day = min(start.day, calendar.monthrange(year, month)[1])
        return start.replace(year=year, month=month, day=day)
    elif unit == "q":
        # Quarters are 3 months
        return add_interval(start, "3mo", n)
    elif unit == "y":
        # Add years (handles leap years)
        return start.replace(year=start.year + total_units)
    else:
        raise ValueError(f"Unsupported interval unit: {unit}")