Search code examples
pythonpython-3.xdatetimetzinfo

How do I implement 'tzinfo' to offset current GMT to EST (GMT -4:00)?


My function takes a UTC datetime string as a parameter, converts it to a datetime object which I then need to offset to EST(GMT -4:00). For example, passing “2019-07-01T00:00:00Z” to the function should return “06/30/2019 08:00:00”.

Here's how I implemented the subclass for 'tzinfo' and its standard methods.

from datetime import datetime, tzinfo, timedelta

class EST(tzinfo):

    def tzname(self, dt):
        return "US/Eastern"

    def utcoffset(self, dt):
        return timedelta(hours=-4) + self.dst(dt)

    def dst(self, dt):
        return timedelta(0)


TEST_UTC = "2019-07-01T00:00:00Z"
dt_object = datetime.strptime(TEST_UTC, "%Y-%m-%dT%H:%M:%SZ")  # String to datetime object -> 2019-07-01 00:00:00
print(dt_object.astimezone(EST()))

The expected output for the last print statement is 2019-06-30 20:00:00-04:00 but the program returns 2019-06-30 14:30:00-04:00. It shows the expected result only if I set the values in the 'timedelta' of the 'utcoffset' function to timedelta(hours=1, minutes=30).

Please note I want to implement this using 'datetime' library only.


Solution

  • I found the solution. I wrongly concluded that print(dt_object.astimezone(EST())) was implementing the offset of EST() class relative to the timestamp of dt_object assigned in the statement above. It was actually implementing according to the UTC time at the moment of running the code. So before implementing my class, I had to first set the timezone of dt_object to UTC and then offset it with EST(). Here's the code I used.

    from datetime import datetime, timedelta, tzinfo, timezone
    
    class EST(tzinfo):
        def utcoffset(self, dt):
            return timedelta(hours=-4) + self.dst(dt)
    
        def dst(self, dt):
            return timedelta(0)
    
        def tzname(self, dt):
            return "US/Eastern"
    
    
    def utc_to_eastern(utc_timestring):
        dt = datetime.strptime(utc_timestring, "%Y-%m-%dT%H:%M:%SZ")
        dt = dt.replace(tzinfo=timezone.utc) # This was the step I missed earlier
        dt = dt.astimezone(EST())
        return dt
    
    
    TEST_UTC = "2019-07-01T00:00:00Z"
    print(utc_to_eastern(TEST_UTC))
    
    

    Note: If you want to adjust for daylight saving as well using the dst() method, you can refer to this thread >> How to get python to display current time (eastern)