Search code examples
pythontypeerrortimedelta

timedelta issue in python3.9 vs.python3.6


I have the following class in a file called 'GPS_Date.py':

import datetime
from math import floor

class GPS_Date(datetime.datetime):

    ref_date = datetime.datetime(1980, 1, 6)

    def __init__(self, year, month, day, hour=0, minute=0, second=0):
        datetime.datetime.__init__(year, month, day, hour, minute, second)

    def gps_week(self):
        difftime = self-self.ref_date
        return floor(difftime.days / 7)

    def day_of_week(self):
        difftime = self-self.ref_date
        return difftime.days % 7

    def day_of_year(self):
        return self.timetuple().tm_yday

    @staticmethod
    def to_GPS_date(date):
        return GPS_Date(date.year, date.month, date.day, date.hour, date.minute, date.second)

    @staticmethod
    def now():
        return GPS_Date.to_GPS_date(datetime.datetime.utcnow())

When I run the following code in python3.6 I get the correct solution:

import datetime
from GPS_Date import GPS_Date

time_string = '2019-01-01 23:59:30.0'
date_format = '%Y-%m-%d %H:%M:%S.%f'

time_1 = datetime.datetime.strptime(time_string, date_format)

time_2 = GPS_Date.to_GPS_date(time_1)

add_time = time_2 + datetime.timedelta(minutes=30)

But when I run it with python3.9 I get the following error:

    add_time = time_2 + datetime.timedelta(minutes=30)
TypeError: __init__() takes from 4 to 7 positional arguments but 9 were given

I assume something has been changed between python3.6 and python3.9. I've looked at documentation but haven't found anything. Can anyone enlighten me?


Solution

  • datetime.datetime does have more arguments that can be passed than GPS_Date accounts for (i.e. tzinfo and fold). Why this doesn't blow up in Python3.6, I am not sure. But you don't need to override __init__ at all, since you aren't doing anything:

    class GPS_Date(datetime.datetime):
    
        ref_date = datetime.datetime(1980, 1, 6)
    
        def gps_week(self):
            difftime = self - self.ref_date
            return floor(difftime.days / 7)
    
        def day_of_week(self):
            difftime = self - self.ref_date
            return difftime.days % 7
    
        def day_of_year(self):
            return self.timetuple().tm_yday
    
        @staticmethod
        def to_GPS_date(date):
            return GPS_Date(date.year, date.month, date.day, date.hour, date.minute, date.second)
    
        @staticmethod
        def now():
            return GPS_Date.to_GPS_date(datetime.datetime.utcnow())
    

    is perfectly fine. (Also note: If you were to do something, you need to override __new__ instead of __init__)