sub-classing the types in the builtin module datetime

Colin J. Williams cjw at sympatico.ca
Wed Aug 15 20:54:13 EDT 2007


I posted this about 5 hours ago, but it seems to have gone astray.

cjw


Jay Loden wrote:
 > Colin J. Williams wrote:
 >
 >> I wish to sub-class (if that's the right word) datetime and to use a
 >> different signature for the constructor.
 >>
 >> The second part has gone smoothly, but it is difficult to access the
 >> type's methods from the sub-class instance.
 >>
 >> I'm beginning to wonder whether it might might be simpler to write my
 >> own Date class.
 >>
 >> Does anyone have any comments please?
 >>
 >> Colin W.
 >>
 >
 > I think it would be most effective if you can post the code you're 
using that illustrates the issue, and what you're trying to do so that 
the list members can analyze the actual problem. Tracebacks etc are 
also welcome if applicable.
 >
 > -Jay
 >
 >
Jay,

Yes, I should have posted an example, but I thought that others might 
have experienced the problem.

It is illustrated at the bottom of this script:

# subClassing.py

import datetime
import new
import sys
import types

class Date(datetime.datetime):
   ''' Date(s) -> a date object.__class__
         where s is an 8 digit string'''

   def __new__(cls, YYmmdd):
     ''' YYmmdd is a string, in the form yyyymmdd i.e. 8 digits.
     or            a 3-tuple of integers in the form (y, m, d)
     or            a 6-tuple of integers in the form (y, m, d, h, m, 
s) '''
     #todo needs a cleanup
     print '__new__'
     self= datetime.datetime.__new__(cls, 1, 1, 1)
     ln= len(YYmmdd)
     if type(YYmmdd) not in (types.StringType, types.TupleType):
       raise ValueError, str(YYmmdd) + '  is invalid for Date'
     ids= ('year', 'momth', 'day', 'hour', 'minute', 'second', 
'microsecond')
     if type(YYmmdd) is types.StringType:
       if ln is 8:
         try:
           values= [int((YYmmdd[:4], YYmmdd[4:6], YYmmdd[6:8])[i]) for 
i in range(3)]
         except:
           raise ValueError, YYmmdd + '  should be an eight digit date 
string'
       else:
         raise ValueError, YYmmdd + '  should be an eight digit date 
string'
     elif ln in (3, 6):
       try:
         for i in range(ln):
           if type(YYmmdd[i]) == types.IntType:
             self.__setattr__(ids[i], YYmmdd[i])
           else:
             raise ValueError, str(YYmmdd) + '  contains a non-integer'
       except:
         print sys.exc_info()
         raise ValueError, 'This should not occur, drop after tests #todo'
     else:
       raise ValueError, str(YYmmdd) + ' is not of an acceptable length'

     return datetime.datetime.__new__(cls, *values)

   def __repr__(self):
     return self.__class__.__name__ +  ' : ' + str(self)

   def __str__(self):
     return "%04d%02d%02d" % (self.year, self.month, self.day)

##  # Failures of subclassing
##  def ctime(self):
##    ''' ctime: Not available in Date. '''
##    pass
##  def date(self):
##    pass
##  def now(self):
##    pass
##  def today(self):
##    pass

a= datetime.datetime(2007, 7, 31)
d= Date('20070731')
tm= datetime.time(1, 2)
try:
   print a.today()
#  print d.today()        # grief
   print a.now()
#  print d.now()          # grief
   print a.combine(a, tm)  # OK, but  why not a.combine(tm)?
#  e= d.combine(d, tm)    # grief
   print a.utcnow()
#  print d.utcnow()       # grief
   print a.ctime()
   print d.ctime()
except:
   print 'Grief'
   print sys.exc_info()

Colin W.




More information about the Python-list mailing list