Reputation: 4289
python version: 3.7
I am trying to convert utc timestamps to a given timezone using pytz
and astimezone
.
(I have timestamps stored in my db in utc timezone and I amtrynig to convert them)
For example:
'US/Pacific'
timezone will result '2022-07-18 12:43:26.164345-07:00' 'UTC'
timezone will not affect any change - will result '2022-07-18 19:43:26.164345'here is what I tried:
import pytz
def convert_utc_timestamp_to_timezone(utc_timestamp, dt_timezone):
return utc_timestamp.astimezone(pytz.timezone(dt_timezone))
expected:
> dt = datetime.datetime.now()
> convert_utc_timestamp_to_timezone(dt, 'UTC') // expected result: dt
but no.., actual result::
> dt = datetime.datetime.now()
> converted = convert_utc_timestamp_to_timezone(dt, 'UTC')
> print(dt) # 2022-07-18 23:10:34.061169
> print(converted) # 2022-07-18 20:10:34.061169+00:00
# dt != converted not as I expect
This works when my local timezone is set to utc - for example when running on online browser
import datetime
import pytz
def convert_utc_timestamp_to_timezone(utc_timestamp, dt_timezone):
return utc_timestamp.astimezone(pytz.timezone(dt_timezone))
dt = datetime.datetime.utcnow()
a = convert_utc_timestamp_to_timezone(dt, 'US/Pacific')
print('in utc timezone',dt)
print('after convert to US/Pacific timezone: ',a)
# results:
#in utc timezone 2022-07-18 20:18:37.253062
# after convert to US/Pacific timezone: 2022-07-18 13:18:37.253062-07:00
dt2 = datetime.datetime.utcnow()
a2 = convert_utc_timestamp_to_timezone(dt, 'UTC')
print('in utc timezone', dt2)
print('after convert to UTC timezone: ',a2)
# results:
# in utc timezone 2022-07-18 20:18:37.264363
# after convert to UTC timezone: 2022-07-18 20:18:37.253062+00:00
But does not work well when running locally - since my pc timezone isn't utc
(the doc actually states that astimezone
“converts to local time”)
import pytz
def convert_utc_timestamp_to_timezone(utc_timestamp, dt_timezone):
return utc_timestamp.astimezone(pytz.timezone(dt_timezone))
dt = datetime.datetime.utcnow()
a = convert_utc_timestamp_to_timezone(dt, 'US/Pacific')
print('in utc timezone', dt)
print('after convert to US/Pacific timezone: ', a)
# result:
# in utc timezone 2022-07-18 20:22:05.526588
# after convert to US/Pacific timezone: 2022-07-18 10:22:05.526588-07:00
dt2 = datetime.datetime.utcnow()
a2 = convert_utc_timestamp_to_timezone(dt, 'UTC')
print('in utc timezone', dt2)
print('after convert to UTC timezone: ', a2)
# result:
# in utc timezone 2022-07-18 20:22:05.576213
# after convert to UTC timezone: 2022-07-18 17:22:05.526588+00:00
what is the correct way to convert timestamp in utc timezone to a given timezone?
I tried pytz localize
, but also doesn't give expected result
Upvotes: 0
Views: 294
Reputation: 178409
Fetch a timezone-aware datetime
. Here's an example:
>>> from datetime import datetime
>>> datetime.now() # timezone unaware, shows my local time
datetime.datetime(2022, 7, 18, 13, 16, 50, 249012)
>>> from datetime import timezone
>>> datetime.now(tz=timezone.utc) # timezone aware, UTC
datetime.datetime(2022, 7, 18, 20, 17, 28, 760889, tzinfo=datetime.timezone.utc)
Converting from UTC to a particular time zone:
>>> import pytz
>>> now = datetime.now(tz=timezone.utc)
>>> now.astimezone(tz=pytz.timezone('US/Pacific'))
datetime.datetime(2022, 7, 18, 13, 18, 6, 929968, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
Upvotes: 2
Reputation: 16737
This is related to a common gotcha with Python datetime types, kinda due to legacy code reasons. The short answer is that you're mixing timezone aware and timezone un-aware types.
Here's the right way to get a utc timestamp:
In [85]: bad_utc = dt.datetime.utcnow() # no timezone info
...: (bad_utc, bad_utc.astimezone(pytz.utc))
...:
Out[85]:
(
datetime.datetime(2022, 7, 18, 20, 23, 44, 583377),
datetime.datetime(2022, 7, 19, 3, 23, 44, 583377, tzinfo=<UTC>),
)
In [86]: good_utc = dt.datetime.now(datetime.timezone.utc) # has timezone info
...: (good_utc, good_utc.astimezone(pytz.utc))
...:
Out[86]:
(
datetime.datetime(2022, 7, 18, 20, 23, 47, 323579, tzinfo=datetime.timezone.utc),
datetime.datetime(2022, 7, 18, 20, 23, 47, 323579, tzinfo=<UTC>),
)
For this reason, there are libraries like pendulum
that "do the right thing" and avoid these gotchas, e.g.:
In [79]: dt.datetime.utcnow() # wrong
Out[79]: datetime.datetime(2022, 7, 18, 20, 20, 41, 681750)
In [80]: dt.datetime.now(datetime.timezone.utc) # right
Out[80]: datetime.datetime(2022, 7, 18, 20, 20, 45, 947941, tzinfo=datetime.timezone.utc)
In [81]: pendulum.now().utcnow() # without gotchas
Out[81]: DateTime(2022, 7, 18, 20, 20, 48, 501773, tzinfo=Timezone('UTC'))
Upvotes: 2