Если вы собираетесь сохранить его как datetime
(что, я согласен, хорошая идея), я бы расширил DateTimeProperty
- тогда вы получите различные биты для анализа и проверки бесплатно.
Кроме того, сохранение как timedelta
как datetime
может быть намного проще, чем другие методы, приведенные здесь, сохраняя его как дату-время на некотором расстоянии от эталонной даты-времени, так что разница представляет временную дельту. Это действительно легко благодаря перегрузке оператора, который дает нам модуль datetime.
from datetime import datetime, timedelta
from google.appengine.ext import db
class TimeDeltaProperty(db.DateTimeProperty):
# Use a reference datetime half way between the min and max possible
# datetimes, so that we can support both +ve and -ve timedeltas
ref_datetime = (datetime.max - datetime.min) / 2 + datetime.min
def get_value_for_datastore(self, model_instance):
# Get the timedelta instance assigned to this property
td = super(TimeDeltaProperty, self).get_value_for_datastore(model_instance)
if td is not None:
# datetime + timedelta = datetime
return self.ref_datetime + td
def make_value_from_datastore(self, dt):
if dt is not None:
# datetime - datetime = timedelta
return dt - self.ref_datetime
И вот эквивалентная реализация для NDB API , если вы склонны к этому:
from datetime import datetime, timedelta
from google.appengine.ext import ndb
class TimeDeltaProperty(ndb.DateTimeProperty):
# Use a reference datetime half way between the min and max possible
# datetimes, so that we can support both +ve and -ve timedeltas
ref_datetime = (datetime.max - datetime.min) / 2 + datetime.min
def _validate(self, value):
if not isinstance(value, timedelta):
raise TypeError('expected a datetime.timedelta, got %r' % value)
def _to_base_type(self, value):
# datetime + timedelta = datetime
return self.ref_datetime + td
def _from_base_type(self, value):
# datetime - datetime = timedelta
return dt - self.ref_datetime
Точность
A timedelta
в Python может обрабатывать дельты примерно +/- 2,7 миллиона лет. Тем не менее, datetime
охватывает только диапазон около 10000 лет. Чтобы сохранить большую временную дельту в дате, вам нужно будет немного сдвинуть и пожертвовать некоторой точностью.
Приведенный выше подход ограничивает временные интервалы до половины этого диапазона - около +/- 5000 лет из-за выбора эталонной даты и времени.
Если вы знаете, что ваша timedelta всегда будет положительной, вы можете использовать ref_datetime = datetime.min
(или, если вы знаете, что она всегда будет отрицательной, вы можете использовать ref_datetime = datetime.max
), чтобы получить полный диапазон около 10000 лет.