Where can I learn more about formatting values for Field Lookups of DurationFields?

I have discovered through trial and error that DurationFields can be filtered with formatted strings that are more powerful than just “hh:mm:ss”. I have been unable to find a formal spec on what works and what doesn’t. For example, say I have a model named Animal with an age field:

    age = models.DurationField(
        null=True,
        blank=True,
        validators=[MinValueValidator(timedelta(seconds=0))],
        help_text="The age of the animal at the time of sample collection.",
    )

We enter the value x in the DB using timedelta(weeks=x). And we have an advanced search interface where the user has been entering a value using the “hh:mm:ss” format, which essentially is executed like:

# 14 weeks
search_term = "2352:00:00"
Animal.objects.filter(age__gt=search_term)

We had tried strings like 98-00:00:00, as I’d seen that format somewhere, but it didn’t work. I’m finally sitting down to flesh the strategy out and give the user a units select list and I have tried various things to determine that roughly the following pattern is compatible:

[n{c[enturies],decades,y[ears],months,w[eeks],d[ays]}{:,\,}[ ]]*hh[h[ours]]:mm[m[inutes]]:ss[.f][s[econds]]

So for example, I can get correct results for ORM filters like:

In [64]: Animal.objects.filter(age__gt="97d:24h").values_list("age", flat=True)
Out[64]: <QuerySet [datetime.timedelta(days=105), datetime.timedelta(days=105), datetime.timedelta(days=105), datetime.timedelta(days=105), datetime.timedelta(days=105), datetime.timedelta(days=105)]>

In [65]: Animal.objects.filter(age__exact="97 d,24 h").values_list("age", flat=True)
Out[65]: <QuerySet [datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98), datetime.timedelta(days=98)]>

I couldn’t find shorter strings for indicating “decades” or “months”.

Note, I can supply strings and I don’t need to create timedelta objects (though if I did, those do work as well). But I’m interested is learning the direct string format that can be supplied to the filter.

I have posted about this on stack as well.

Those constants are passed through to the database engine as part of the generated SQL. So to some degree it’s going to depend upon which database is being used.

For PostgreSQL, you’ll find this information in section 8.5.4 at PostgreSQL: Documentation: 15: 8.5. Date/Time Types.

1 Like

Yeah, we’re using postgres.