<p>如果您打算将它存储为<code>datetime</code>(我同意这是一个好主意),我将扩展<code>DateTimeProperty</code>-然后您可以免费获得各种解析和验证。</p>
<p>此外,作为<code>timedelta</code>存储为<code>datetime</code>比这里给出的其他方法要容易得多,方法是将其存储为日期时间,与引用日期时间相距一定距离,这样差异表示时间增量。这真的很容易,这要感谢datetime模块给我们的操作符重载。</p>
<pre><code>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
</code></pre>
<p>这里有一个<a href="https://developers.google.com/appengine/docs/python/ndb/" rel="nofollow">NDB API</a>的等价实现,如果您有这种倾向:</p>
<pre><code>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
</code></pre>
<h2>准确度</h2>
<p>Python中的<code>timedelta</code>可以处理大约+/-270万年的三角洲。然而,a <code>datetime</code>只覆盖了大约10000年的时间范围。要在datetime中存储更大的timedelta,必须进行一些移位并牺牲一些准确性。</p>
<p>由于参考日期时间的选择,上面的方法将时间增量限制在这个范围的一半-大约为+/-5000年。</p>
<p>如果你知道你的时间增量总是正的,你可以使用<code>ref_datetime = datetime.min</code>(或者如果你知道它总是负的,你可以使用<code>ref_datetime = datetime.max</code>)来得到大约10000年的完整范围。</p>