timedelta转换为time或int并将其存储在GAE(python)数据中

2024-09-29 21:44:16 发布

您现在位置:Python中文网/ 问答频道 /正文

看起来这已经在其他问题中有所涉及,但我仍然对如何真正做到这一点相当困惑。我缺乏经验对这没什么帮助。

我有两个datetime属性-StartTime和EndTime。我从结束时间中减去StartTime得到持续时间。从我的上一个问题(谢谢你所有的答案!)看起来这个操作产生了一个timedelta。

似乎没有一种简单的方法可以直接将timedelta存储在GAE数据存储中,因此这意味着我需要将其转换为in t(毫秒)、float(秒)或time。

我以后还需要做其他的计算,比如计算平均持续时间。基于此,int对我来说似乎是最有意义的。

最好的方法是什么?或者有什么教程我可以玩?

谢谢你!


Tags: 数据方法答案indatetime属性time时间
3条回答

为了尽可能简单地使用它,有两个步骤:将timedelta转换为int或float,并将其存储在数据存储中。首先,将时间增量转换为微时间:

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
import pickle
import datetime

...

delta = end_time - start_time
for_storage = pickle.dumps(delta)
#now you have a string representation of your timedelta object that you can store

#sometime later...
delta = pickle.loads(from_storage)

您仍然需要使用时间增量的days、mins、seconds和microseconds属性将增量转换为您选择的时间分辨率。

如果您打算将它存储为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万年的三角洲。然而,a datetime只覆盖了大约10000年的时间范围。要在datetime中存储更大的timedelta,必须进行一些移位并牺牲一些准确性。

由于参考日期时间的选择,上面的方法将时间增量限制在这个范围的一半-大约为+/-5000年。

如果你知道你的时间增量总是正的,你可以使用ref_datetime = datetime.min(或者如果你知道它总是负的,你可以使用ref_datetime = datetime.max)来得到大约10000年的完整范围。

相关问题 更多 >

    热门问题