将timedelta转换为时间或整数并存储在GAE(Python)数据存储中
看起来这个问题在其他讨论中已经提到过一些,但我还是有点困惑,不太清楚该怎么做。我的经验不足也没能帮上什么忙。
我有两个时间属性 - 开始时间(StartTime)和结束时间(EndTime)。我想通过把结束时间减去开始时间来得到持续时间(Duration)。根据我之前的问题(感谢所有回答的人!),这个操作似乎会产生一个时间差(timedelta)。
在GAE的数据存储中,似乎没有简单的方法可以直接存储时间差,这意味着我需要把它转换成毫秒的整数、秒的浮点数或者时间格式。
我之后还需要进行其他计算,比如算平均持续时间。根据这一点,现在我觉得用整数来表示最合适。
请问有什么好的方法可以做到这一点,或者有没有可以让我练习的教程?
谢谢!
4 个回答
最后这个方法成功了:
delta = StartTime - EndTime
event_record.Duration = int((delta.microseconds)/1000)
其实就是需要从时间差中提取微秒,然后把它转换成毫秒。
如果你打算把它存储为 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
准确性
在 Python 中,timedelta
可以处理大约 +/-270 万年的时间差。然而,datetime
只覆盖大约 10,000 年的范围。要在 datetime 中存储更大的时间差,你需要做一些调整,并牺牲一些准确性。
上面的方法将时间差限制在这个范围的一半,大约 +/-5000 年,因为选择了参考时间点。
如果你知道你的时间差总是正值,可以使用 ref_datetime = datetime.min
(或者如果你知道它总是负值,可以使用 ref_datetime = datetime.max
)来获取大约 10,000 年的完整范围。
为了让这个过程尽可能简单,有两个步骤:将时间差(timedelta)转换成整数或浮点数,然后把它存储到数据存储中。首先,我们要把时间差转换成微秒时间(microtime):
def timedelta_to_microtime(td):
return td.microseconds + (td.seconds + td.days * 86400) * 1000000
不过,你不需要自己去做这个转换——你可以定义一个自定义的数据存储属性,这样就可以直接把时间差存储到你的模型里:
class TimeDeltaProperty(db.Property):
def get_value_for_datastore(self, model_instance):
value = self.__get__(model_instance, model_instance.__class__)
if value is not None:
return timedelta_to_microtime(value)
def make_value_from_datastore(self, value):
if value is not None:
return datetime.timedelta(microseconds=value)
现在你可以像使用其他属性一样使用这个属性了:
class MyModel(db.Model):
td = TimeDeltaProperty(required=True)
entity = MyModel(td=datetime.datetime.now()-some_datetime)
key = entity.put()
entity = db.get(key)
print entity.td