Converting time_struct with timezone to datetime GMT in Python - python

I'm retrieving struct_time dates from Feedparser.
Like you can see below, FeedParser automatically parses the dates into GMT (second line, EDT, get converted from 19:19 to 23:19)
FeedParser converted Sun, 06 Sep 2020 23:07:16 GMT into struct_time((2020, 9, 6, 23, 7, 16, 6, 250, 0))
FeedParser converted Fri, 11 Sep 2020 19:19:01 EDT into struct_time((2020, 9, 11, 23, 19, 1, 4, 255, 0))
When I try to convert the struct_time to a datetime with the below, I get GMT + 1 (my timezone).
from datetime import datetime
from time import mktime
datetime.fromtimestamp(mktime(struct_time((2020, 9, 6, 23, 7, 16, 6, 250, 0))))
> datetime.datetime(2020, 9, 7, 0, 7, 16)
How can I convert these struct_time into datetimes GMT?

to get a time zone aware datetime object, you could unpack the relevant part of the timetuple into a datetime object and set the tzinfo attribute to UTC:
from datetime import datetime, timezone
# given a time_struct tuple like
s = (2020, 9, 6, 23, 7, 16, 6, 250, 0)
# convert to datetime object as
dt = datetime(*s[:6], tzinfo=timezone.utc)
print(dt)
>>> 2020-09-06 23:07:16+00:00

Related

Convert UTC date string to PST and then subtract 12 hours from it

I have incoming strings that are UTC dates in ISO format like,
2021-11-21T12:16:42Z
I wish to convert these dates into PST and then subtract 12 hours from it.
import datetime
time_list_utc=2021-11-21T12:16:42Z
time_list_pst=time_list_utc.convert(pst)
print(time_list_pst-8hours)
I am new to datetime manipulation so any input is greatly appreciated
Use datetime, tzinfo and timedelta modules since Python 3.9:
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
s = '2021-11-21T12:16:42Z'
# Convert to datetime (UTC)
dt_utc = datetime.strptime(utc, "%Y-%m-%dT%H:%M:%S%z")
# Convert to PST
dt_pst = dt_utc.astimezone(ZoneInfo('US/Pacific'))
# Subtract 12 hours
dt = dt_pst - timedelta(hours=12)
Output:
>>> dt
datetime.datetime(2021, 11, 20, 16, 16, 42, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific'))
>>> dt_pst
datetime.datetime(2021, 11, 21, 4, 16, 42, tzinfo=zoneinfo.ZoneInfo(key='US/Pacific'))
>>> dt_utc
datetime.datetime(2021, 11, 21, 12, 16, 42, tzinfo=datetime.timezone.utc)

set datetime object time value to 0

I need to set the time value of detatime objects to 00:00, so I can easily compare two 'dates'
Now I do:
extracted_start_date = datetime.strptime(extracted_start_date.strftime('%Y-%m-%d'), '%Y-%m-%d')
so I have my datetime object
$ datetime.datetime(2021, 3, 18, 11, 13, 53, 782088),
I extract the date string strftime('%Y-%m-%d')
$ '2021-03-18'
and put this back into a datetime object now wch has time 00:00
$ datetime.datetime(2021, 3, 18, 0, 0)
This seems quite elaborate, is there a more efficient way, or is it OK like this?
datetime.datetime objects have method date which return datetime.date instance and these might be used for day-based comparison, consider following example:
import datetime
d1 = datetime.datetime(2021, 3, 17, 9, 0, 0) # yesterday 9:00
d2 = datetime.datetime(2021, 3, 18, 9, 0, 0) # today 9:00
d3 = datetime.datetime(2021, 3, 18, 12, 0, 0) # today 12:00
print(d1.date() == d2.date())
print(d2.date() == d3.date())
output:
False
True
You could use the replace method instead.
from datetime import datetime
d = datetime(2021, 3, 18, 11, 13, 53, 782088)
d.replace(hour=0, minute=0, second=0, microsecond=0)
> datetime.datetime(2021, 3, 18, 0, 0)

Daylight time saving aware conversion of timestamps in python

Given a timestamp without time zone (e.g. 2018-03-12 09:30:00) AND the timezone EST5EDT, the goal is to parse the data returning a datetime object that is time zone AND daylight saving aware.
from datetime import datetime
import pytz
datetime(2018, 3, 8, 9, 30, tzinfo=pytz.timezone('EST5EDT')).astimezone(pytz.utc)
# returns:
# datetime.datetime(2018, 3, 8, 14, 30, tzinfo=<UTC>)
datetime(2018, 3, 12, 9, 30, tzinfo=pytz.timezone('EST5EDT')).astimezone(pytz.utc)
# returns:
# datetime.datetime(2018, 3, 12, 14, 30, tzinfo=<UTC>)
# BUT should return (second Sunday of march the daylight saving changes by 1 hour):
# datetime.datetime(2018, 3, 12, 13, 30, tzinfo=<UTC>)
Never set tzinfo directly when creating datetimes. Always use the localize() method of the timezone (see the note at the top of http://pytz.sourceforge.net/):
pytz.timezone('EST5EDT').localize(
datetime(2018, 3, 12, 9, 30)
).astimezone(pytz.utc)

Convert Dates in python to compare

I have two dates in Python. One is received from the database:
(datetime.datetime(2017, 10, 10, 10, 10, 10),)
And the other from the email:
Thu, 18 Jan 2018 15:50:49 -0500.
I want to compare these two dates in Python for which I think these dates need to be converted in one specific format. How to convert these dates in one specific format to compare?
Convert both to datetime (very powerful with dates).
dt_date = datetime.datetime(2017, 10, 10, 10, 10, 10)
str_date = 'Thu, 18 Jan 2018 15:50:49 -0500'
pd.to_datetime([dt_date,str_date])
Output:
DatetimeIndex(['2017-10-10 10:10:10', '2018-01-18 20:50:49']
from datetime import datetime
start_date = datetime(2017, 10, 10, 10, 10, 10)
email_date = datetime.strptime("Thu, 18 Jan 2018 15:50:49", "%a, %d %b %Y %H:%M:%S")
start_date, email_date
>>>datetime.datetime(2017, 10, 10, 10, 10, 10) datetime.datetime(2018, 1, 18, 15, 50, 49)

timezone conversion in Python

I'm probably missing something about timezones:
>>> import datetime, pytz
>>> date = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.timezone("Europe/Paris"))
>>> date.astimezone(pytz.UTC)
datetime.datetime(2013, 9, 3, 15, 51, tzinfo=<UTC>)
I was expecting
datetime.datetime(2013, 9, 3, 15, 00, tzinfo=<UTC>)
Can anyone explain me where these 51 minutes come from?
Thanks,
Jean-Philippe
The UTC offset gives (date.tzinfo.utcoffset(date)):
datetime.timedelta(0, 540)
This is 540 seconds or 9 minutes.
In France the switch to UTC was made on March 11, 1911 and the clocks were turned back 9 minutes and 21 seconds (source 1, source 2):
Until 1911, Paris was 9 minutes and 21 seconds off UTC.
You can also see it here (Paris time in 1911) where the time goes from March 11, 12:01:00 AM to March 10, 11:51:39 PM.
Read the note at the very begining of pytz documentation ; use .localize() method to create timezone-aware datetime object:
import datetime
import pytz
naive_dt = datetime.datetime(2013,9,3,16,0)
dt = pytz.timezone("Europe/Paris").localize(naive_dt, is_dst=None)
to_s = lambda d: d.strftime('%Y-%m-%d %H:%M:%S %Z%z')
print(to_s(dt))
print(to_s(dt.astimezone(pytz.utc)))
Output
2013-09-03 16:00:00 CEST+0200
2013-09-03 14:00:00 UTC+0000
I don't know why you are expecting 15:00 UTC here.
Thanks Simeon for your answer. It made me realize how shallow is my understanding of all of this. The following experimentations lost me a little more...
>>> import datetime, pytz
>>> date_paris = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.timezone("Europe/Paris"))
>>> date_utc = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.utc)
>>> date_paris.astimezone(pytz.utc)
datetime.datetime(2013, 9, 3, 15, 51, tzinfo=<UTC>)
>>> date_utc.astimezone(pytz.timezone("Europe/Paris"))
datetime.datetime(2013, 9, 3, 18, 0, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)
Why this 9 minutes offset shows up when converting in one direction but not the other? The following piece of code concentrate all disappointment:
>>> date_paris
datetime.datetime(2013, 9, 3, 16, 0, tzinfo=<DstTzInfo 'Europe/Paris' PMT+0:09:00 STD>)
>>> date_paris.astimezone(pytz.utc).astimezone(pytz.timezone("Europe/Paris"))
datetime.datetime(2013, 9, 3, 17, 51, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)

Categories