Add timedelta field for storing timedelta objects

This commit is contained in:
Ethan Paul 2023-05-04 14:25:05 -04:00
parent 0693d19f7a
commit 027da380a5
1 changed files with 21 additions and 0 deletions

View File

@ -17,6 +17,7 @@ Various extensions, helpers, and utilities for `Peewee`_
.. _`Peewee documentation`: https://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings .. _`Peewee documentation`: https://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings
""" """
import contextlib import contextlib
import datetime
import enum import enum
import functools import functools
import json import json
@ -54,6 +55,7 @@ __all__ = [
"PrecisionFloatField", "PrecisionFloatField",
"SQLITE_DEFAULT_PRAGMAS", "SQLITE_DEFAULT_PRAGMAS",
"SQLITE_DEFAULT_VARIABLE_LIMIT", "SQLITE_DEFAULT_VARIABLE_LIMIT",
"TimedeltaField",
] ]
@ -399,3 +401,22 @@ class EnumField(peewee.CharField): # pylint: disable=abstract-method
raise peewee.IntegrityError( raise peewee.IntegrityError(
f"Enum {self.enumeration.__name__} has no value with name '{value}'" f"Enum {self.enumeration.__name__} has no value with name '{value}'"
) from None ) from None
class TimedeltaField(peewee.BigIntegerField):
"""Field class for storing python-native Timedelta objects
This is really just a helper wrapper around an integer field that performs the second conversions
automatically. It is a helpful helper though, so it's included.
.. note:: To avoid issues with float precision, this field stores the database value as an integer.
However, this necessitates the usage of the BigInt type to avoid overflowing the value.
Essentially, the value this field ends up storing is the number of microseconds in the
timedelta.
"""
def db_value(self, value: datetime.timedelta) -> int:
return super().db_value(int(value.total_seconds() * 1000000))
def python_value(self, value: int) -> datetime.timedelta:
return datetime.timedelta(seconds=super().python_value(value) / 1000000)