from datetime import timedelta from marshmallow.fields import Field class TimeDelta1(Field): DAYS = 'days' SECONDS = 'seconds' MICROSECONDS = 'microseconds' def __init__(self, precision='seconds', error=None, **kwargs): precision = precision.lower() units = (self.DAYS, self.SECONDS, self.MICROSECONDS) if precision not in units: msg = 'The precision must be "{0}", "{1}" or "{2}".'.format(*units) raise ValueError(msg) self.precision = precision super(TimeDelta1, self).__init__(error=error, **kwargs) def _serialize(self, value, attr, obj): try: days = value.days seconds = days * 86400 + value.seconds microseconds = seconds * 10**6 + value.microseconds except AttributeError: msg = '{0!r} cannot be formatted as a timedelta.'.format(value) raise MarshallingError(getattr(self, 'error', None) or msg) return locals()[self.precision] class TimeDelta2(Field): DAYS = 'days' SECONDS = 'seconds' MICROSECONDS = 'microseconds' def __init__(self, precision='seconds', error=None, **kwargs): precision = precision.lower() units = (self.DAYS, self.SECONDS, self.MICROSECONDS) if precision not in units: msg = 'The precision must be "{0}", "{1}" or "{2}".'.format(*units) raise ValueError(msg) self.precision = precision super(TimeDelta2, self).__init__(error=error, **kwargs) def _serialize(self, value, attr, obj): try: days = value.days if self.precision == self.DAYS: return days else: seconds = days * 86400 + value.seconds if self.precision == self.SECONDS: return seconds else: # microseconds return seconds * 10**6 + value.microseconds except AttributeError: msg = '{0!r} cannot be formatted as a timedelta.'.format() raise MarshallingError(getattr(self, 'error', None) or msg) def seconds1(): f = TimeDelta1(precision='microseconds') for i in range(999999): obj = {'foo': timedelta(microseconds=i)} f.serialize('foo', obj) def seconds2(): f = TimeDelta2(precision='microseconds') for i in range(999999): obj = {'foo': timedelta(microseconds=i)} f.serialize('foo', obj) %timeit seconds1() %timeit seconds2()