Idea: Adding a Time Base Type

Updated November 25, 2002 | Fredrik Lundh

I propose adding an “abstract” basetype for time objects, which can be subclassed by more elaborate date/time/timestamp implementations, such as mxDateTime, custom types provided by DB-API implementations, etc.

This proposal contains two parts; an “abstract” base type (an interface) from which all time types can inherit, and a simple implementation, providing an object oriented wrapper for C’s time_t type (as used by the time module).

The base type is designed to make it easy to extract the year, month, day, hour, minute, and second from any given time object.

Or to put it another way, I want the following to work for any time object, including mxDateTime objects, any date/timestamp returned by a DB-API driver, and weird date/time-like types I’ve developed myself.

if isinstance(t, basetime):
    print t.timetuple()

where basetime is the proposed name of this type.

Alternatively, the type can be replaced with an (informal) interface:

if hasattr(t, "timetuple"):
    print t.timetuple()

The goal is not to standardize any behaviour beyond this; anything else should be provided by subtypes.

The simple type provides a number of functions from the time module, as methods of the time object.

The Base Type

The basetime type provides a minimal interface, with three standard methods.

 
class basetime(object):

    def timetuple(self):
        # return time as 9-item time tuple (local time)
        # the first six fields must be filled in.  the last
        # three may be set to -1, if not known

    def __cmp__(self, other):
        # compare this time object with other time object of
        # same type

    def __hash__(self):
        # return hash signature

FIXME/FL: Several reviewers has pointed out that this class probably should define basic arithmetics as well (subtract time from time to get time delta, add time and delta to get a new time). I’m not sure if we can/should standarize on a delta representation, though: maybe this is better left for subclasses. A compromise could be to define that the following should work (where deltaobject is an unknown type):

deltaobject = timeobject - timeobject
floatobject = float(deltaobject) # fractional seconds
timeobject = timeobject + integerobject
timeobject = timeobject + floatobject
timeobject = timeobject + deltaobject

The timetuple method

This method returns the current date/time value, as a 9-item tuple similar to the tuples used by the time module. For date/time types that knows about timezones, this method should return the local time.

The year, month, day, hour, minute, and second fields must always be set. Any (or all) of the remaining three items may be -1 if not known.

This is the same thing as calling time.localtime(t) with a time_t value, or calling mxDateTime’s tuple() method.

The Simple Time Type

In addition to the base type, I propose adding a minimal time type to the time module. Thanks to __int__ and __float__ hooks, it will still work with code that asks for an integer (including the functions provided by the current time module), but the user will have to explitly wrap return values from time.time() and time.mktime() to use them as objects.

FIXME: now that utc* is gone, add a separate simpleutctime subclass instead.

Here’s a simple reference implementation:

 
#
# simple time wrapper

import time

class simpletime(basetime):

    def __init__(self, ticks):
        self.ticks = ticks

    #
    # standard basetime protocol

    def timetuple(self):
        return time.localtime(self.ticks)

    def __cmp__(self, other):
        return cmp(self.ticks, other.ticks)

    def __hash__(self):
        return hash(self.ticks)

    #
    # convenience functions

    def __int__(self):
        return int(self.ticks)

    def __float__(self):
        return float(self.ticks)

    def __repr__(self):
        return "<simpletime %s at %x>" % (self.ctime(), id(self))

    def ctime(self):
        return time.ctime(self.ticks)

    def strftime(self, format):
        return time.strftime(format, self.timetuple())

Questions

Q. Is it really a good idea to set the daynumber and dayofweek fields to -1.

A. Both fields can be calculated from the date. However, the calculations are not trivial (where “trivial” is defined as “most programmers can write them without looking them up”). We could address this by providing a reference implementation, but that’s outside the scope of this proposal.

Q. Why not standardize more methods while we’re at it?

A. Keep it simple. The goal is to let generic time-using code to access the time tuple, not to support any fancier processing. Use packages like mxDateTime for that purpose.


Changes

July 12, 2002: moved from “ideas” directory, removed diff markup, removed utc* methods (use “naive time”), and fixed a few typos.

November 25, 2002: added hasattr note.

 

A Django site. rendered by a django application. hosted by webfaction.