views:

92

answers:

2

I'm processing data from an application that has a few quirks in how it keeps time. One of the simpler quirks is that it uses "day of year" (Jan 1 is 1, Febuary 1 is 32, etc) instead of month + day. So I want to make my own date class that inherits from the default datetime class and has a few custom methods. I'm calling this daytime. In addition to methods that output to my weird formats, I need methods that input the weird format into a daytime. Just like the method .fromordinal()can be called from datetime, I want to have a method .fromdayofyear() which can be called from daytime. So far I got:

import datetime

class daytime(datetime.datetime):
    @property
    def dayofyear(self):
        return (self.date - datetime.date(self.year,1,1)).days + 1
    def fromdayofyear(year,dayofyear):
        return datetime(year,1,1)+datetime.timedelta(dayofyear-1)

The problem is that since fromdayofyear is a class, it needs an instance of daytime to perform any methods.

>>> from utils import daytime
>>> day = daytime.fromdayofyear(2010,32)          #should give a datetime, Feburary first
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method from_datetime() must be called with DayTime instance as first argument (got str instance instead)
>>>

I could easily write a series of functions to do this, but that defeats the point of making a custom class to begin with. I realize that I probably shouldn't be using a class here. Can someone point me in the right direction?

EDIT:

Here's what I settled on:

import datetime

class daytime(datetime.datetime):
    @property
    def dayofyear(self):
        return (self.date - datetime.date(self.year,1,1)).days + 1
    @classmethod
    def fromdayofyear(cls,year,dayofyear):
        dt = cls(year,1,1)+datetime.timedelta(dayofyear-1)
        return cls(dt.year,dt.month,dt.day)
+8  A: 

You want @classmethod decorator. Then your method gets the class instead of object instance as the first argument. It's customary to call it cls:

@classmethod
def from_file(cls, f):
    return cls(f.read())
Radomir Dopieralski
You rock. I'll edit my question to reflect this
dustynachos
+2  A: 

The OP's "settled on" solution has serious bugs (self.date needs to be called, not just mentioned; and the fromdayofyear method actually returns a datetime.datetime instance, not a daytime one, despite the apparent attempt to do so by using cls).

Here's a version which I believe works as intended:

class daytime(datetime.datetime):

    @property
    def dayofyear(self):
        return (self.date() - datetime.date(self.year, 1, 1)).days + 1

    @classmethod
    def fromdayofyear(cls, year, dayofyear):
        dt = datetime.datetime(year, 1, 1) + datetime.timedelta(dayofyear-1)
        return cls(dt.year, dt.month, dt.day)
Alex Martelli
Your comment on THC4K's answer was correct. I'll update my solution.
dustynachos