When I run the following code;
tz_Pacific = pytz.timezone('US/Pacific')
tz_Tasmania = pytz.timezone('Australia/Tasmania')
time1 = datetime(2020, 10, 7, 18, 0, 0, tzinfo=tz_Pacific)
time2 = datetime(2020, 10, 7, 14, 20, 21, tzinfo=tz_Tasmania)
print(time1)
print(time2)
I get the following output;
2020-10-07 18:00:00-07:53
2020-10-07 14:20:21+09:49
Why would the tz offsets be -07:53 and +09:49 respectively?
Why you get these "weired" offsets with pytz? Those are the first entries from the database for the respective time zones. With pytz, if you don't localize, these won't be adjusted to the time of your datetime object. Here's a nice blog post by Paul Ganssle giving more insights.
from datetime import datetime
import pytz
tz_Pacific = pytz.timezone('US/Pacific')
tz_Tasmania = pytz.timezone('Australia/Tasmania')
# note the LMT for local mean time:
print(repr(tz_Pacific))
print(repr(tz_Tasmania))
# <DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>
# <DstTzInfo 'Australia/Tasmania' LMT+9:49:00 STD>
# correctly localized you get
time1 = tz_Pacific.localize(datetime(2020, 10, 7, 18, 0, 0))
time2 = tz_Tasmania.localize(datetime(2020, 10, 7, 14, 20, 21))
print(time1)
print(time2)
# 2020-10-07 18:00:00-07:00
# 2020-10-07 14:20:21+11:00
Further remarks:
With Python 3.9+, you have zoneinfo as part of the standard library to do this.
Example: Display the time in a different time zone.
Note that there is a deprecation shim for pytz.
Related
I have time = '2020-06-24T13:30:00-04:00'. How can I change it to a dateTime object in UTC time. I would prefer not to use pd.Timestamp(time).tz_convert("UTC").to_pydatetime() because it returns a weird output that would look like this datetime.datetime(2020, 6, 24, 17, 30, tzinfo=<UTC>). As a result, when I check for equality with datetime.datetime(2020, 6, 24, 17, 30), it return False.
Edit:
import datetime
import pytz
time = '2020-06-24T13:30:00-04:00
dt = datetime.datetime(2020, 6, 24, 17, 30)
print("dt: ",dt)
so = datetime.datetime.strptime(time, '%Y-%m-%dT%H:%M:%S%z').astimezone(pytz.utc)
print("so:",so)
print(dt == so)
outputs
dt: 2020-06-24 17:30:00
so: 2020-06-24 17:30:00+00:00
False
How can I get it to properly evaluate to True?
#1 Since your string is ISO 8601 compatible, use fromisoformat() on Python 3.7+:
from datetime import datetime, timezone
s = '2020-06-24T13:30:00-04:00'
dtobj = datetime.fromisoformat(s)
# dtobj
# datetime.datetime(2020, 6, 24, 13, 30, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))
Note that this will give you a timezone-aware datetime object; the tzinfo property is a UTC offset. You can easily convert that to UTC using astimezone():
dtobj_utc = dtobj.astimezone(timezone.utc)
# dtobj_utc
# datetime.datetime(2020, 6, 24, 17, 30, tzinfo=datetime.timezone.utc)
#2 You can achieve the same with strptime (also Python3.7+ according to this):
dtobj = datetime.strptime(s, '%Y-%m-%dT%H:%M:%S%z')
dtobj_utc = dtobj.astimezone(timezone.utc)
# dtobj_utc
# datetime.datetime(2020, 6, 24, 17, 30, tzinfo=datetime.timezone.utc)
#3 If you want to turn the result into a naive datetime object, i.e. remove the tzinfo property, replace with None:
dtobj_utc_naive = dtobj_utc.replace(tzinfo=None)
# dtobj_utc_naive
# datetime.datetime(2020, 6, 24, 17, 30)
#4 For older Python versions, you should be able to use dateutil's parser:
from dateutil import parser
dtobj = parser.parse(s)
dtobj_utc = dtobj.astimezone(timezone.utc)
dtobj_utc_naive = dtobj_utc.replace(tzinfo=None)
# dtobj_utc_naive
# datetime.datetime(2020, 6, 24, 17, 30)
Alright so my previous answer was sort of wack because I did not understand your issue entirely so I am rewriting it. You problem is that you are constructing a datetime object from a string and it is timezone aware(UTC). However, whenever you make a datetime object in python, dt = datetime.datetime(2020, 6, 24, 17, 30), it is creating it but with no timezone information (which you can check using .tzinfo on it). All you would need to do is make dt timezone aware when you first create it. See below my code snippit.
import datetime
time = '2020-06-24T13:30:00-04:00'
dt = datetime.datetime(2020, 6, 24, 17, 30, tzinfo=datetime.timezone.utc)
print("dt: ",dt.tzinfo)
so = datetime.datetime.strptime(time, '%Y-%m-%dT%H:%M:%S%z')
print("so:",so.tzinfo)
print(dt == so)
I have a dictionary of timestamps which are strings which I first converted to datetime objects.
I need to do the sql equivalent of timestamp at time zone 'UTC' at time zone 'America/New_York'
Here I have a for loop
for x in dataj:
x['event_time'] = datetime.strptime(x['event_time'].split('.')[0], "%Y-%m-%d %H:%M:%S")
x['event_time'] = x['event_time'].replace(tzinfo=timezone('America/New_York'))
I get this error
TypeError: timezone() argument 1 must be datetime.timedelta, not str
dataj looks like so:
P(dataj[0])
{'$insert_id': '14ae91db-4b9e-4898-88dd-62fc9f99dcb4',
'$schema': 12,
'adid': None,
'event_time': '2019-12-01 00:00:19.251000'
}
This answer shows how to add the needed timezones to the datetime object. You need to use pytz.
Here is a segment that is similar to your post.
import datetime
import pytz
x = '2019-12-01 00:00:19.251000'
as_datetime = datetime.datetime.strptime(x.split('.')[0], "%Y-%m-%d %H:%M:%S")
as_datetime # datetime.datetime(2019, 12, 1, 0, 0, 19)
utcmoment = as_datetime.replace(tzinfo=pytz.utc)
as_nytz = utcmoment.astimezone(pytz.timezone('America/New_York'))
as_nytz # datetime.datetime(2019, 11, 30, 19, 0, 19, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
Without knowing all background...
from datetime import datetime, timedelta
from pytz import timezone
import pytz
dataj = {'$insert_id': '14ae91db-4b9e-4898-88dd-62fc9f99dcb4','$schema': 12, 'adid': None,'event_time': '2019-12-01 00:00:19.251000'}
print(dataj)
for schema, value in dataj.items():
if schema == 'event_time':
correct_time = datetime.strptime(dataj["event_time"].split('.')[0], "%Y-%m-%d %H:%M:%S")
dataj['event_time'] = correct_time.replace(tzinfo=timezone('America/New_York'))
print(dataj)
Is it possible to apply timezone when parsing ms to datetime?
My parsing is working but it is displaying local time instead of datetime with timezone:
timestamp = datetime.fromtimestamp(float(dt) / 1000.0,
tz=pytz.timezone("America/Sao_Paulo"))
Not sure if it is happening because timezone from my OS.
This just parses the timestamp as the tz you provide (so it assumes dt is a local time). If dt is absolute / UTC and you want to convert it to a local timezone, you need to first parse it it to a UTC datetime then move its timezone:
datetime.fromtimestamp(timestamp, pytz.utc).astimezone(pytz.timezone('America/Sao_Paulo'))
For instance using 1234567890:
>>> datetime.fromtimestamp(ts, pytz.utc)
datetime.datetime(2009, 2, 13, 23, 31, 30, tzinfo=<UTC>)
>>> datetime.fromtimestamp(ts, pytz.utc).astimezone(pytz.timezone('America/Sao_Paulo'))
datetime.datetime(2009, 2, 13, 21, 31, 30, tzinfo=<DstTzInfo 'America/Sao_Paulo' -02-1 day, 22:00:00 DST>)
Also note that for various historical reasons properly using pytz is not as simple as that (e.g.). If you're going to have to deal with timezones a lot, you may want to take a look at pendulum which tries to make timezone manipulations more reliable, and to provide a friendlier API.
Not sure what the problem is, it seems to be working as expected. My local time is 09:02 and with the Sao Paolo timezone it shows as 10:02, which seems correct.
>>> import datetime, time, pytz
>>> tz_1 = pytz.timezone("America/Sao_Paulo")
>>> tz_1
<DstTzInfo 'America/Sao_Paulo' LMT-1 day, 20:54:00 STD>
>>> now = time.time()
>>> now
1554382930.1575696
>>> datetime.datetime.fromtimestamp(now)
datetime.datetime(2019, 4, 4, 9, 2, 10, 157570)
>>> datetime.datetime.fromtimestamp(now, tz=tz_1)
datetime.datetime(2019, 4, 4, 10, 2, 10, 157570, tzinfo=<DstTzInfo 'America/Sao_Paulo' -03-1 day, 21:00:00 STD>)
Could you elaborate on which part is not displaying as you expected?
Why does calling thee below 2 functions on dt result in adding 5 hours? I figured it would remain the same.
from datetime import datetime, time, timedelta
from pytz import timezone
def est_datetime_to_utc_timestamp(dt):
dt_utc = dt.astimezone(timezone('UTC'))
ts = int(dt_utc.strftime("%s"))
return ts
def utc_timestamp_to_est_datetime(ts):
dt = datetime.fromtimestamp(ts, timezone('UTC'))
dt = dt.astimezone(timezone('America/New_York'))
return dt
dt = timezone('America/New_York').localize(datetime(2017, 11, 27, 0, 0))
utc_timestamp_to_est_datetime(est_datetime_to_utc_timestamp(dt))
> datetime.datetime(2017, 11, 27, 5, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
strftime("%s") is not defined in every implementation.
Replacing it with .timestamp() works for Python 3.3+, and gives the correct result.
Alternatively, you can use (dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds() if not on Python 3.3+.
How can I change a timezone in a datetimefield.
right now I have
datetime.datetime(2013, 7, 16, 4, 30, tzinfo=<UTC>)
how can modify the tzinfo just for display not to update on the db.
Use pytz for such things.
From the pytz docs, you can use astimezone() to transform time into different time zone, as example below.
>>> eastern = timezone('US/Eastern')
>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
>>> loc_dt = utc_dt.astimezone(eastern)
>>> loc_dt.strftime(fmt)
'2002-10-27 01:00:00 EST-0500'