I'm trying to get UTC times for dates before 1970 but tz and tzinfo in Python only contain timezone databases for dates post-1970.
If I'm trying to find the UTC time for a date before 1970, say, Bill Clinton's birthday:
August 16, 1946 8:51AM
Hope, AK
datetime and tzinfo will return 16 Aug 1946 13:51 UTC
But it turns out that that is incorrect because it uses Chicago's timezone (which had its own timezone)
How can I find the proper time conversion and trust it for dates before 1970 in Python?
Time zone rules as we know them today came into play around 1900, see e.g. P. Eggert's tz repo. So Bill Clinton's birthday should not suffer from missing tz rules.
Ex, using pytz (deprecated):
from datetime import datetime
import pytz
bday = "August 16, 1946 8:51AM Hope, AK"
# Hope, AK is not a time zone, so strip it
bday = bday.rstrip(" Hope, AK")
# Hope in Arkansas uses US Central time, so we can use
tz = pytz.timezone("America/Chicago")
bday_dt = tz.localize(datetime.strptime(bday, "%B %d, %Y %I:%M%p"))
print(bday_dt)
# 1946-08-16 08:51:00-05:00
print(bday_dt.astimezone(pytz.UTC))
# 1946-08-16 13:51:00+00:00
...or using Python 3.9's zoneinfo
from zoneinfo import ZoneInfo
bday_dt = datetime.strptime(bday, "%B %d, %Y %I:%M%p").replace(tzinfo=ZoneInfo("America/Chicago"))
print(bday_dt)
# 1946-08-16 08:51:00-05:00
print(bday_dt.astimezone(ZoneInfo("UTC")))
# 1946-08-16 13:51:00+00:00
Related
This is the data that is being returned from my API:
"Jun 02, 2021, 2 PMEST"
If I'm within 7 days of the current date which I'm getting by doing this:
from datetime import date
today = date.today()
print("Today's date:", today)
Just need to convert Jun to a number and 02 and compare to see if it's within 7 days in the future of the current date, then return True
APPROACH 0:
Given the format of your example data, you should be able to convert it to a datetime using this code:
datetime.strptime("Jun 02, 2021, 2 PMEST", "%b %d, %Y, %I %p%Z")
The details about this format string are here: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
However, when I tested this locally, it worked for this input:
"Jun 02, 2021, 2 PMUTC"
but not for your input (which has different timezone):
"Jun 02, 2021, 2 PMEST"
I have investigated this some more and "read the docs" (https://docs.python.org/3/library/time.html).
To get EST parsing to work, you would have to change your OS timezone and reset the time module's timezones like this:
from datetime import datetime
import os
import time
os.environ["TZ"] = "US/Eastern". # change timezone
time.tzset(). # reset time.tzname tuple
datetime.strptime("Jun 02, 2021, 2 PMEST", "%b %d, %Y, %I %p%Z")
When you're done, be safe and delete the "hacked" environment variable:
del os.environ["TZ"]
Note - Since your system timezone is presumably still UTC, it can still parse UTC timezone too.
See this thread for detailed discussion: https://bugs.python.org/issue22377
Also note that the timestamp is not actually captured. The result you get with EST and UTC is a naive datetime object.
APPROACH 1
So, it seems like there is a better way to approach this.
First, you need to pip install dateutils if you don't already have it.
THen do something like this:
from dateutil import parser
from dateutil.tz import gettz
tzinfos = {"EST": gettz("US/Eastern")}
my_datetime = parser.parse("Jun 02, 2021, 2 PM EST", tzinfos=tzinfos)
What's happening here is we use gettz to get timezone information from the timezones listed in usr/share/zoneinfo. Then the parse function can (fuzzy) parse your string (no format needs to be specified!) and returns my_datetime which has timezone information on it. Here are the parser docs: https://dateutil.readthedocs.io/en/stable/parser.html
I don't know how many different timezones you need to deal with so the rest is up to you. Good luck.
Convert the date to a datetime structure and take the direct difference. Note that today must be a datetime, too.
import datetime
date_string = "Jun 02, 2021, 2 PMEST"
today = datetime.datetime.today()
date = datetime.datetime.strptime(date_string,
"%b %d, %Y, %I %p%Z") # Corrected
(date - today).days
#340
In python, I am trying to convert a bunch of UTC datetimes into a localized timezone but STANDARD time year round. For example, for pacific time, I need PST year round, not PDT and PST switching from summer to winter. Or to rephrase my question, is there a way to specify 'Standard' time for a timezone?
You can specify the UTC offset for a specific time zone that does not change with daylight savings. Following example converts UTC to Pacific Standard Time (PST).
from datetime import datetime, timedelta, timezone
utc = datetime(2019, 8, 7, 10, 30, tzinfo=timezone.utc)
pst = utc.astimezone(timezone(-timedelta(hours=8)))
print(utc)
# 2019-08-07 10:30:00+00:00
print(pst)
# 2019-08-07 02:30:00-08:00
To obtain the number of hours of offset for a named time zone:
import pytz
def get_standard_time_offset(tz_name):
t = pytz.timezone(tz_name)
# DATE HERE IS AN ARBITRARY WINTER DATE THAT WOULDN'T WORK IN THE SOUTHERN HEMISPHERE
offset = t.utcoffset(datetime(2010,1,1))
hrsoffset = offset.total_seconds()/3600
return hrsoffset
from datetime import datetime, timezone
utc_dt = "enter here UTC time "
utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
If I have the following timestring:
20150505
How would I convert this into the date May 5, 2015 in Python? So far I've tried:
from datetime import datetime
sd = datetime.strptime('20150504', '%Y%M%d')
But this outputs:
2015-01-04 00:05:00
The capital M denotes minute not month. Use the lowercase m and then call the strftime method to refactor the format:
>>> datetime.strptime('20150504', '%Y%m%d').strftime('%b %d, %Y')
'May 04, 2015'
You can remove the zero padding from the month by using the -d directive in place of d:
%-d Day of the month as a decimal number. (Platform specific)
For longer month names, you can use the directive %B in place of %b to get the full month name.
Reference:
http://strftime.org/
If you know it's a date and not a datetime, or you don't know the format. You can use dateutil.
from dateutil.parser import parse
print(parse('20150504'))
This is the anwser, wihout leading zero for day, as OP's example:
print(sd.strftime('%b %-d, %Y'))
# Jan 4, 2015 # note your sd parsing is wrong. Thus Jan
I have to create a code that can tell me the current time in any city (as a variable) and print the utc offset between that time and utc. I already have the following code which gives the current time and the offset from a timezone, but this timezone is not always utc. Note: the city names are stored in a text file and the user should be able to add and remove any city. I am using tkinter for the gui.
from datetime import datetime, timedelta
from pytz import timezone
import pytz
def tz():
utc = pytz.utc
amsterdam = timezone('Europe/Amsterdam')
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
loc_dt = utc.localize(datetime.today())
tz = loc_dt.astimezone(amsterdam)
print(tz.strftime(fmt))
The file contents are as follows:
Amsterdam
Brasilia
Los Angeles
Abu Dhabi
Tokyo
Singapore
Can someone please help me with an easy code to do this? Thank you in advance
You're using pytz already, so I'd go for:
from datetime import datetime
from pytz import timezone, all_timezones
def to_timezone(dt, tz):
assert dt.tzinfo is not None
assert tz in all_timezones
return dt.astimezone(timezone(tz))
print to_timezone(datetime.now(timezone('UTC')), 'Europe/Amsterdam')
I set it to UTC by default but the point is:
have a non naive datetime
convert it
There are a ton of questions about UTC datetime conversions and there doesn't seems to be a consensus of a "best way".
According to this: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ , pytz is the best way to go. he shows converting to timezone like this datetime.datetime.utcnow().replace(tzinfo=pytz.utc) but he doesn't say how to get the user's timezone...
This guy https://stackoverflow.com/a/7465359/523051 says "localize adjusts for Daylight Savings Time, replace does not"
Everyone I see using pytz is supplying their own timezone (users_timezone = timezone("US/Pacific")), which I don't understand because you can't know if that's where your viewer is...
This guy https://stackoverflow.com/a/4771733/523051 has a way to auto-detect the timezones, but this is using the dateutil library, and not pytz, as is recommended by both Armin Ronacher and the official python docs ( http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior , just above that anchor in yellow box)
All I need is the most simplest, future-proof, all daylight savings time/etc considered way to take my datetime.utcnow() stamp (2012-08-25 10:59:56.511479), convert it the user's timezone. And show it like this:
Aug 25 - 10:59AM
and if the year is not the current year, I'd like to say
Aug 25 '11 - 10:59AM
alright, here it is (also, my first contribution to SO :))
it does require 2 external libraries which may throw some off...
from datetime import datetime
from dateutil import tz
import pytz
def standard_date(dt):
"""Takes a naive datetime stamp, tests if time ago is > than 1 year,
determines user's local timezone, outputs stamp formatted and at local time."""
# determine difference between now and stamp
now = datetime.utcnow()
diff = now - dt
# show year in formatting if date is not this year
if (diff.days / 365) >= 1:
fmt = "%b %d '%y # %I:%M%p"
else:
fmt = '%b %d # %I:%M%p'
# get users local timezone from the dateutils library
# http://stackoverflow.com/a/4771733/523051
users_tz = tz.tzlocal()
# give the naive stamp timezone info
utc_dt = dt.replace(tzinfo=pytz.utc)
# convert from utc to local time
loc_dt = utc_dt.astimezone(users_tz)
# apply formatting
f = loc_dt.strftime(fmt)
return f