6 de fevereiro de 2009

Freetime: a Time OO Module

As datetime.time and time (module) didn't solve my problem, I wrote this one for time calculation free of date. Here are some examples of use:


>>> from freetime import Time
>>> # Let's begin calling the static method 'now'
>>> now = Time.now()
>>> now
freetime.Time(hours=9, minutes=21, seconds=52, microseconds=609000)
>>> now.minutes
21
>>> # calc 1034 minutes from now
>>> after = now + Time(minutes=1034)
>>> after
freetime.Time(hours=26, minutes=35, seconds=52, microseconds=609000)
>>> # Let's know how it represents in seconds
>>> after_in_seconds = Time(None, None, microseconds=None) + after
>>> after_in_seconds
freetime.Time(hours=None, minutes=None, seconds=95752.01015, microseconds=None)
>>> after_in_seconds.seconds
95752.010150000002
>>> # But they are equal, aren't they?
>>> after == after_in_seconds
True
>>> # Let's rollback to full time
>>> full = after_in_seconds.to_full_time()
>>> full
freetime.Time(hours=26, minutes=35, seconds=52, microseconds=609000.0)
>>> # Sum 'now' and 'after_in_seconds'
>>> added = now + after_in_seconds
>>> added
freetime.Time(hours=35, minutes=57, seconds=44, microseconds=1218000.0)
>>> # If in your case time can only have 24 hours
>>> added.to_24_hours()
freetime.Time(hours=11, minutes=57, seconds=44, microseconds=1218000.0)
>>> # To know how many days and hours it would be
>>> days, obj = added.calc_days()
>>> days
1
>>> obj
freetime.Time(hours=11, minutes=57, seconds=44, microseconds=1218000.0)

___________________________

AND HERE IS THE CODE:


"""
OO Time module for calculation free of date.
>>> from freetime import Time
>>> # Let's begin calling the static method 'now'
>>> now = Time.now()
>>> now
freetime.Time(hours=9, minutes=21, seconds=52, microseconds=609000)
>>> now.minutes
21
>>> # calc 1034 minutes from now
>>> after = now + Time(minutes=1034)
>>> after
freetime.Time(hours=26, minutes=35, seconds=52, microseconds=609000)
>>> # Let's know how it represents in seconds
>>> after_in_seconds = Time(None, None, microseconds=None) + after
>>> after_in_seconds
freetime.Time(hours=None, minutes=None, seconds=95752.01015, microseconds=None)
>>> after_in_seconds.seconds
95752.010150000002
>>> # But they are equal, aren't they?
>>> after == after_in_seconds
True
>>> # Let's rollback to full time
>>> full = after_in_seconds.to_full_time()
>>> full
freetime.Time(hours=26, minutes=35, seconds=52, microseconds=609000.0)
>>> # Sum 'now' and 'after_in_seconds'
>>> added = now + after_in_seconds
>>> added
freetime.Time(hours=35, minutes=57, seconds=44, microseconds=1218000.0)
>>> # If in your case time can only have 24 hours
>>> added.to_24_hours()
freetime.Time(hours=11, minutes=57, seconds=44, microseconds=1218000.0)
>>> # To know how many days and hours it would be
>>> days, obj = added.calc_days()
>>> days
1
>>> obj
freetime.Time(hours=11, minutes=57, seconds=44, microseconds=1218000.0)
"""

from __future__ import division

__author__ = "Eduardo Willians Oliveira Bandeira de Melo "
__file__ = "freetime.py"
__license__ = ("LGPL", 3.0)

import datetime

class Time(object):

def __init__(self, hours=0, minutes=0, seconds=0,
microseconds=0):
self.hours = hours
self.minutes = minutes
self.seconds = seconds
self.microseconds = microseconds

@staticmethod
def now():
t = datetime.datetime.now().time()
return Time(t.hour, t.minute, t.second, t.microsecond)

def __str__(self):
return ("freetime.Time(hours=%s, minutes=%s, seconds=%s, "
"microseconds=%s)" % (
self.hours, self.minutes, self.seconds, self.microseconds))

def __repr__(self):
return self.__str__()

def __add__(self, other):
x, y = self._shared_op(other)
return self._to_time(x+y)

def __sub__(self, other):
x, y = self._shared_op(other)
return self._to_time(x-y)

def __div__(self, other):
x, y = self._shared_op(other)
return self._to_time(x/y)

def __truediv__(self, other):
x, y = self._shared_op(other)
return self._to_time(x/y)

def __mul__(self, other):
x, y = self._shared_op(other)
return self._to_time(x*y)

def __eq__(self, other):
x, y = self._shared_op(other)
return (x == y)

def __ne__(self, other):
eq = self.__eq__(other)
return False if eq else True

def __lt__(self, other):
x, y = self._shared_op(other)
return x < y =" self._shared_op(other)" y =" self._shared_op(other)"> y

def __ge__(self, other):
x, y = self._shared_op(other)
return x >= y

def _shared_op(self, other):
if other.__class__ != self.__class__:
raise TypeError
self_ms = self._to_microseconds(self)
other_ms = self._to_microseconds(other)
return (self_ms, other_ms)

def _to_microseconds(self, obj):
ms = obj.microseconds or 0
ms += ((obj.hours or 0) * 60 * 60 * 60000000)
ms += ((obj.minutes or 0) * 60 * 60000000)
ms += ((obj.seconds or 0) * 60000000)
return ms

def _to_time(self, microseconds):
h = 0
m = 0
s = 0
ms = microseconds
if self.microseconds is None:
s += (ms/60000000)
ms = None
elif None not in (self.seconds, self.minutes, self.hours):
while ms >= 60000000:
s += 1
ms -= 60000000
if self.seconds is None:
m += s/60
s = None
elif None not in (self.minutes, self.hours):
while s >= 60:
m += 1
s -= 60
if self.minutes is None:
h += m/60
m = None
elif self.hours is not None:
while m >= 60:
h += 1
m -= 60
if self.hours is None:
h = None
return self.__class__(h, m, s, ms)

def to_full_time(self):
"@return: a new object"
obj = self.__class__()
return obj + self

def to_24_hours(self):
"@return: a new object"
obj = self.to_full_time()
h = obj.hours
while h >= 24:
h -= 24
return self.__class__(h, obj.minutes, obj.seconds, obj.microseconds)

def calc_days(self):
"@return: tuple(days, freetime.Time obj)"
obj = self.to_full_time()
h = obj.hours
days = 0
while h >= 24:
days += 1
h -= 24
new = self.__class__(h, obj.minutes, obj.seconds, obj.microseconds)
return (days, new)