[DB-SIG] DateTime: Changing the time value handling ?!
M.-A. Lemburg
lemburg@uni-duesseldorf.de
Sat, 14 Mar 1998 12:56:19 +0100
--------------7CF3CC331E9AD3E47ED3FB94
Content-type: text/plain; charset="us-ascii"
M.-A. Lemburg wrote:
>
> Jim Fulton wrote:
> >
> > M.-A. Lemburg wrote:
> > >
> > > How would I store the time zone offset in those databases ?
> >
> > I guess you don't. But that doesn't mean you shouldn't make it
> > possible to handle the time zone (offset) in the underlying type.
>
> Hmm, I'll think about it. The offset should be declared as such
> though, e.g. a 0 offset wouldn't necessarily mean that you have
> UTC stored in your object. And the offset would probably only be
> used for arithmetic, so that the internals don't have to be touched.
>
> I think I'll try that as an experiment...
> (An offset in minutes should be ok; that'll result in an extra
> short, or 2 bytes, per object)
Here are my findings:
- including the offset in the basic type introduces too many
complications
- it's usage would not be transparent, e.g. some values might have
an offset, some others don't; when you do calculations with them
you suddenly get strange results and tracing these back is no fun
at all
- inventing new schemes on top of the two basic types *is* fun:
I wrote a set of ODMG type classes that do handle offsets using
the two basic types in some 20 minutes
Conclusion: I'll leave the DateTime[Delta] as they are -- without
hidden offsets (but with the change in the way ticks are handled).
--
Marc-Andre Lemburg
--------------7CF3CC331E9AD3E47ED3FB94
Content-type: text/plain; charset="us-ascii"
""" ODMG type classes for date/time handling
These are built on top of the basic types and include rudimentary
time zone handling through an offset in minutes. It is the applications
responsibility to set the offset to correct values. The offsets are
then used in date calculations.
The implementation has not yet been thoroughly tested, but provides
a good example of the swiftness with which you can build new date/time
classes on top of the two basic types. If you find any errors or would
like to see new features, mail them to mal@lemburg.com.
"""
__version__ = '0.1alpha'
__author__ = 'Marc-Andre Lemburg, mailto:mal@lemburg.com'
import DateTime
class _EmptyClass: pass
class Date:
offset = 0 # from some imaginary time zone in minutes
def __init__(self,*args):
self.data = apply(DateTime.DateTime,args)
def set_timezone(self,offset):
self.offset = offset
def __getattr__(self,what):
return getattr(self.data,what)
def __sub__(self,other):
if isinstance(other,Date):
if self.offset != other.offset:
# Be careful about different offsets:
d = (self.data - self.offset * DateTime.oneMinute) \
- (other.data - other.offset * DateTime.oneMinute)
else:
# Offsets are equal: no adjustment needed
d = self.data - other.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
elif isinstance(other,Interval):
d = self.data - other.data
o = _EmptyClass()
o.__class__ = Date
o.data = d
o.offset = self.offset # inherit the offset
return o
else:
raise TypeError,"operation not supported"
def __add__(self,other):
if isinstance(other,Interval):
d = self.data + other.data
o = _EmptyClass()
o.__class__ = Date
o.data = d
o.offset = self.offset # inherit the offset
return o
else:
raise TypeError,"operation not supported"
def __str__(self):
return str(self.data)
def __repr__(self):
return '<Date object for "%s" at %x>' % (str(self.data),id(self))
class Timestamp(Date):
def __repr__(self):
return '<Timestamp object for "%s" at %x>' % (str(self.data),id(self))
class Time:
def __init__(self,*args):
self.data = apply(DateTime.TimeDelta,args)
def __getattr__(self,what):
return getattr(self.data,what)
def __sub__(self,other):
if isinstance(other,Time):
d = self.data - other.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
elif isinstance(other,Interval):
d = self.data - other.data
o = _EmptyClass()
o.__class__ = Time
o.data = d
return o
else:
raise TypeError,"operation not supported"
def __add__(self,other):
if isinstance(other,Time):
d = self.data + other.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
elif isinstance(other,Interval):
d = self.data + other.data
o = _EmptyClass()
o.__class__ = Time
o.data = d
return o
else:
raise TypeError,"operation not supported"
def __str__(self):
return str(self.data)
def __repr__(self):
return '<Time object for "%s" at %x>' % (str(self.data),id(self))
class Interval:
def __init__(self,*args):
self.data = apply(DateTime.DateTimeDelta,args)
def __getattr__(self,what):
return getattr(self.data,what)
def __sub__(self,other):
if isinstance(other,Interval):
d = self.data - other.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
else:
raise TypeError,"operation not supported"
def __add__(self,other):
if isinstance(other,Interval):
d = self.data + other.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
else:
raise TypeError,"operation not supported"
def __mul__(self,other):
value = float(other)
d = value * self.data
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
__rmul__ = __mul__
def __div__(self,other):
value = float(other)
d = self.data / value
o = _EmptyClass()
o.__class__ = Interval
o.data = d
return o
def __str__(self):
return str(self.data)
def __repr__(self):
return '<Interval object for "%s" at %x>' % (str(self.data),id(self))
if __name__ == '__main__':
# Some test instances to play around with
d = Date(1998,3,2)
e = Date(1998,1,2)
f = Date(1998,1,2)
f.set_timezone(60)
t = Time(12,0,0)
u = Time(13,0,0)
--------------7CF3CC331E9AD3E47ED3FB94--
_______________
DB-SIG - SIG on Tabular Databases in Python
send messages to: db-sig@python.org
administrivia to: db-sig-request@python.org
_______________