timedelta преобразовать в time или int и сохранить его в хранилище данных GAE (python) - PullRequest
4 голосов
/ 10 марта 2010

Похоже, что это было несколько рассмотрено в других вопросах, но я все еще не совсем понимаю, как на самом деле это сделать. Мой недостаток опыта не очень помогает в этом.

У меня есть два свойства DateTime - StartTime и EndTime. Я вычитаю StartTime из EndTime, чтобы получить продолжительность. Из моего предыдущего вопроса (спасибо всем, кто ответил!) Похоже, что эта операция производит timedelta.

Кажется, нет простого способа сохранить таймделту непосредственно в хранилище данных GAE, поэтому это означает, что мне нужно преобразовать ее либо в целое число в миллисекундах, в число с плавающей запятой в секундах или во время.

Мне нужно будет позже сделать и другие расчеты, например, вычислить avg. продолжительность. Исходя из этого, мне кажется, что сейчас int имеет смысл.

Какой лучший способ сделать это или есть учебник, с которым я могу играть?

Спасибо!

Ответы [ 4 ]

12 голосов
/ 10 марта 2010

Чтобы сделать это максимально простым для работы, есть два шага: преобразование 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
1 голос
/ 20 мая 2012

Если вы собираетесь сохранить его как 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 лет.

0 голосов
/ 10 марта 2010

Это в конечном итоге сработало:

delta = StartTime - EndTime

event_record.Duration = int((delta.microseconds)/1000)

В основном, необходимо получить микросекунды из временной дельты и преобразовать ее в миллисекунды.

0 голосов
/ 10 марта 2010
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)

Вам все равно нужно будет преобразовать дельту в разрешение по вашему выбору, используя атрибуты дней, минут, секунд и микросекунд дельты времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...