foragerDev
foragerDev

Reputation: 1409

Incorrect datetime conversion from America/New_York time to UTC and back to America/New_York

I am trying to convert time from America/New York to UTC and then converting it back to the New York time. But I get different results while doing with this with pytz.

I am doing this:

new_date = parser.parse("May 4, 2021")
new_date = new_date.replace(tzinfo=pytz.timezone("America/New_York"))
date = new_date.astimezone(pytz.timezone("UTC"))     

Output:

datetime.datetime(2021, 5, 4, 4, 56, tzinfo=<UTC>)

When I try to reconvert it back to the New York time I get this:

date.astimezone(pytz.timezone("America/New_York"))

I get:

datetime.datetime(2021, 5, 4, 0, 56, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

My Question is why there is 56 minute difference and what can be done to prevent this?

Upvotes: 2

Views: 1558

Answers (3)

Chris Charley
Chris Charley

Reputation: 6613

I was able to do the conversion from Eastern to UTC and then back to Eastern without the 56 minutes showing up. (I also changed the date to 11-10 to see the time in Standard Time)

from datetime import datetime
import pytz

t = '2024-11-10 13:00:00'
dt = datetime.strptime(t, '%Y-%m-%d %H:%M:%S')

eastern = pytz.timezone('US/Eastern')

east_dt = eastern.localize(dt)
print('eastern', east_dt)

utc = east_dt.astimezone(pytz.utc)
print('utc', utc)

back = utc.astimezone(eastern)
print('back', back)


"""
eastern 2024-11-10 13:00:00-05:00
utc 2024-11-10 18:00:00+00:00
back 2024-11-10 13:00:00-05:00
"""

""" is daylight savings/standard time aware"""

Upvotes: 0

FObersteiner
FObersteiner

Reputation: 25634

The 56 min difference originates from the fact that the first entry in the database that pytz accesses, refers to LMT (local mean time):

import pytz
t = pytz.timezone("America/New_York")
print(repr(t))
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

You can read more in P. Ganssle's Fastest Footgun blog post or in Weird timezone issue with pytz here on SO.

tl;dr - Never replace a tzinfo with a timezone object from pytz! Use localize (or astimezone) instead, to adjust the timezone to the year of the datetime object.

...But: since you use dateutil already, why don't you use it here as well:

import dateutil

new_date = dateutil.parser.parse("May 4, 2021")
# you can safely replace with dateutil's tz objects:
new_date = new_date.replace(tzinfo=dateutil.tz.gettz("America/New_York"))
date = new_date.astimezone(dateutil.tz.UTC)   

# date
# datetime.datetime(2021, 5, 4, 4, 0, tzinfo=tzutc())

date = date.astimezone(dateutil.tz.gettz("America/New_York"))
# date
# datetime.datetime(2021, 5, 4, 0, 0, tzinfo=tzfile('US/Eastern'))
print(date)
# 2021-05-04 00:00:00-04:00

Upvotes: 5

vvg
vvg

Reputation: 1213

The code is functioning as intended.

There is not a 56 minutes difference. There is a 4 hour difference.

datetime.datetime(
2021, // yyyy
5, // mm
4, // dd
4, // hh -- This is hours
56, // mi
tzinfo=)

4 hours also happens to be the hours by which UTC is ahead of US Eastern Time. When it is 00:56 Hrs in New York, in UTC time it will be 04:56 Hrs.

Upvotes: -1

Related Questions