Subclassing datetime64

332 Views Asked by At

How can I subclass from numpy datetime64 ? For instance using the standard datetime I can easily subclass:

import datetime as dt

class SubFromDateTime(dt.datetime):
    def __new__(cls):
        return dt.datetime.__new__(cls, 2012, 1, 1)

print type(SubFromDateTime())

>>> 
<class '__main__.SubFromDateTime'>

However, using datetime64 the following always returns the datetime64 reference, not my class...

from numpy import datetime64

class SubFromDT64(datetime64):
    def __new__(cls):
        return datetime64.__new__(cls, '20120101')

print type(SubFromDT64())

>>>
<type 'numpy.datetime64'>

How can I fix this? I'd basically like to write a simple wrapper for datetime64, which allows me to add custom functions, such as obtaining the month of a given date with a simple .Month() method. With the upper example I can easily add methods, in the lower example it will never recognize my methods and thinks it's a datetime64 object.

1

There are 1 best solutions below

0
On

I ended up subclassing ndarray which creates a datetime64 array. Works like a charm for my purposes. In case anyone is interested here the code:

import numpy as np

class Date64(np.ndarray):
    def __new__(cls, data):
        data = np.asarray(data, dtype='datetime64')
        if (data.dtype != 'datetime64[D]'):
            raise Exception('Unable to parse dates adequately to datetime64[D]: %s' % data)
        obj = data.view(cls)
        return obj

    def Year(self):
        return self.astype('datetime64[Y]').astype(int) + 1970

    def Month(self):
        return self.astype('datetime64[M]').astype(int) % 12 + 1

    def Day(self):
        return (self - self.astype('datetime64[M]') + 1).astype(int)

    def ISO(self):
        if (self.shape):
            out = zip(self.Year(), self.Month(), self.Day())
            iso = [ '%04d-%02d-%02d' % each for each in out ]
        else:
            iso = '%04d-%02d-%02d' % (self.Year(), self.Month(), self.Day())
        return iso

    def Export(self):
        return self

    def __array_finalize__(self, obj):
        if obj is None:
            return


if (__name__ == '__main__'):
    a = [ dt.date(2013, 1, 1), '2012-03-01', '2012-07-02', '2012-01-03', '2012-01-04', '2011-01-05' ]
    b = Date64(a)

    print b
    print b.ISO()