<@ULVA73B9P> I have a prefect flow parameter that'...
# ask-marvin
i
@Marvin I have a prefect flow parameter that's a datetime.timedelta, what's the json format of a timedelta? in Python I would do datetime.timedelta(days=1) but I don't know ho to do that in json format so prefect can load it as a time delta. I can think of a couple of hacks but would like to know if there's a something that just works
m
thought for 856.7 seconds
Short answer: send it as seconds. In Prefect 3.x, flow parameters are validated with Pydantic v2 using your type hints. For a parameter annotated as
datetime.timedelta
, the most reliable JSON input is a number representing seconds (int or float). Pydantic will coerce that into a
timedelta
. Examples - Flow
Copy code
from datetime import timedelta
from prefect import flow

@flow
def my_flow(window: timedelta):
    print(window)

# window will be a real datetime.timedelta at runtime
- Parameters JSON (UI/API/etc.)
Copy code
{"window": 86400}          # 1 day
{"window": 90.5}           # 90.5 seconds
What else “may” work - ISO 8601 duration strings (e.g.,
"P1D"
,
"PT1H30M"
) are generally accepted by Pydantic for timedeltas, but if you want a format that just works everywhere in Prefect, use numeric seconds. If you hit any parsing issues with strings, switch to numeric seconds and it should resolve them. If you can share how you’re passing the parameter (UI, API, CLI) and an example value you tried, I can confirm exactly what will be accepted in that path.
i
@Marvin I want to express something like -24 days for example. Expressing this in seconds will be confusing, I guess I will either go with the ISO8601 format which I missed or check further is something like what we do in shell (date --date='30 days ago' -I) could be supported
m
thought for 56.7 seconds
Good news: negative durations are fine. What “just works” most reliably in Prefect 3.x is still numeric seconds, so for 24 days ago you can pass -2073600 as JSON. I get that it’s not very readable. If you want something more readable: - ISO 8601 duration strings: Try "-P24D" - Pydantic v2 (which Prefect uses for parameter parsing) generally accepts ISO 8601 duration strings for
timedelta
. Prefixing with a minus sign is the standard way to express a negative duration. - JSON examples:
Copy code
{"window": "-P24D"}     # 24 days ago
    {"window": "PT-36H"}    # 36 hours ago
    {"window": "P2DT-3H"}   # 2 days and 3 hours ago (note: some parsers prefer "-P2DT3H" instead)
- Caveat: exact string variants accepted can depend on the underlying parser. If you see a validation error, fall back to numeric seconds. - Not supported out-of-the-box: shell-like strings such as "30 days ago" or date’s
--date='30 days ago'
. Those won’t be parsed by Pydantic by default. If you want first-class readability without guessing parser behavior, you can keep your flow type as
timedelta
and accept friendly strings by adding a tiny validator. Example that supports ints/floats (seconds), ISO 8601, and simple “Xd/Xh/Xm/Xs” forms like "-24d":
Copy code
from datetime import timedelta
from typing import Annotated
from pydantic import BeforeValidator
from prefect import flow
import re

def parse_duration(v):
    if isinstance(v, timedelta):
        return v
    if isinstance(v, (int, float)):
        return timedelta(seconds=float(v))
    if isinstance(v, str):
        s = v.strip()
        # simple forms like "-24d", "36h", "90m", "45s"
        m = re.fullmatch(r'([+-]?\d+(?:\.\d+)?)\s*([dhms])', s, flags=re.I)
        if m:
            n = float(m.group(1))
            unit = m.group(2).lower()
            mult = dict(d=86400, h=3600, m=60, s=1)[unit]
            return timedelta(seconds=n * mult)
        # try ISO 8601 durations like "P1D", "-PT36H"
        try:
            import isodate  # pip install isodate
            td = isodate.parse_duration(s)
            # isodate returns timedelta for day/hour/minute/second durations
            return td if isinstance(td, timedelta) else td.tdelta
        except Exception:
            pass
    raise TypeError("Invalid duration format; use seconds, ISO 8601 (e.g. -P24D), or -24d/-36h/-90m/-45s")

Duration = Annotated[timedelta, BeforeValidator(parse_duration)]

@flow
def my_flow(window: Duration):
    print(window)
If you can share how you’re passing the parameter (UI input, API call body, or a deployment’s default parameters), I can confirm exactly which string forms will be accepted there. My quick recommendation to try first is: - JSON:
{"window": "-P24D"}
If that doesn’t parse in your path, switch to: - JSON:
{"window": "-24d"}
with the small validator above, or - JSON:
{"window": -2073600}
for guaranteed compatibility.