Difference between revisions of "Using Python datetime with Timezones"
Jump to navigation
Jump to search
PeterHarding (talk | contribs) |
PeterHarding (talk | contribs) |
||
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=Links= | |||
* https://vinta.ws/code/timezone-in-python-offset-naive-and-offset-aware-datetimes.html | |||
=Distinguishing between TZ Aware and TZ Naive Objects= | |||
<pre> | |||
from datetime import datetime | |||
now = datetime.now() | |||
now = now.replace(tzinfo=datetime.timezone.utc) | |||
if now.tzinfo == None or \ | |||
now.tzinfo.utcoffset(now) == None: | |||
# If these conditions are met the object is unaware | |||
print("Unaware") | |||
else: | |||
print("Aware") | |||
print(now.isoformat()) | |||
</pre> | |||
=Binding with Timezone Info= | |||
<pre> | |||
cat !$ | |||
cat ./py_tz_example_01.py | |||
#!/usr/bin/env python3 | |||
import pytz | |||
from datetime import datetime | |||
def list_tz(): | |||
for tz in pytz.all_timezones: | |||
print(tz) | |||
def example(tz_name): | |||
specified_tz = pytz.timezone(tz_name) | |||
# transform to a time using a specific timezone | |||
tz_aware_dt = datetime.now(tz=specified_tz) | |||
print(f"TZ aware datetime value |{tz_aware_dt.isoformat()}| for timezone - '{tz_name}'") | |||
# list_tz() | |||
print(f"TZ naive datetime value |{datetime.now().isoformat()}|") | |||
example("America/New_York") | |||
example("America/Vancouver") | |||
example("Asia/Tokyo") | |||
example("Australia/Sydney") | |||
example("Europe/London") | |||
example("Europe/Paris") | |||
</pre> | |||
==Output== | |||
<pre> | |||
% ./py_tz_example_01.py | |||
TZ naive datetime value |2022-06-05T09:48:41.237251| | |||
TZ aware datetime value |2022-06-04T19:48:41.249310-04:00| for timezone - 'America/New_York' | |||
TZ aware datetime value |2022-06-04T16:48:41.249630-07:00| for timezone - 'America/Vancouver' | |||
TZ aware datetime value |2022-06-05T08:48:41.249701+09:00| for timezone - 'Asia/Tokyo' | |||
TZ aware datetime value |2022-06-05T09:48:41.249923+10:00| for timezone - 'Australia/Sydney' | |||
TZ aware datetime value |2022-06-05T00:48:41.250303+01:00| for timezone - 'Europe/London' | |||
TZ aware datetime value |2022-06-05T01:48:41.250543+02:00| for timezone - 'Europe/Paris' | |||
</pre> | |||
=Explicit Numerical Offsets from UTC= | =Explicit Numerical Offsets from UTC= | ||
Line 12: | Line 90: | ||
# This is a naive datetime value | # This is a naive datetime value | ||
print(dt.isoformat()) | print(f" TZ naive datetime value |{dt.isoformat()}|") | ||
print(dt.tzinfo) | print(f" dt.tzinfo |{dt.tzinfo}|") | ||
# Cast this as UTC | # Cast this as UTC | ||
Line 21: | Line 99: | ||
# Define the offset | # Define the offset | ||
offset = "+1000" | offset = "+1000" # "Australia/Melbourne" | ||
# Convert as so... | # Convert as so... | ||
Line 27: | Line 105: | ||
tz_aware_dt = dt.astimezone(datetime.strptime(offset, "%z").tzinfo) | tz_aware_dt = dt.astimezone(datetime.strptime(offset, "%z").tzinfo) | ||
print(tz_aware_dt.isoformat()) | print(f" TZ Aware datetime value |{tz_aware_dt.isoformat()}|") | ||
</pre> | |||
==Output== | |||
<pre> | |||
% ./py_tz_example_02.py | |||
TZ naive datetime value |2022-06-05T09:49:37.782118| | |||
dt.tzinfo |None| | |||
TZ Aware datetime value |2022-06-05T19:49:37.782118+10:00| | |||
</pre> | |||
=Changing Timezones= | |||
<pre> | |||
from pytz import timezone | |||
from datetime import datetime | |||
fmt = "%Y-%m-%d %H:%M:%S %Z%z" | |||
# Current datetime in UTC | |||
dt = datetime.now(timezone('UTC')) | |||
print(dt.strftime(fmt)) | |||
# Convert to US/Pacific time zone | |||
dt = dt.astimezone(timezone('Asia/Tokyo')) | |||
print(dt.strftime(fmt)) | |||
# Convert to Europe/Paris time zone | |||
dt = dt.astimezone(timezone('Europe/Paris')) | |||
print dt.strftime(fmt) | |||
</pre> | |||
==Output== | |||
<pre> | |||
./tst_ft.py | |||
2022-06-05 09:41:02 UTC+0000 | |||
2022-06-05 18:41:02 JST+0900 | |||
2022-06-05 11:41:02 CEST+0200 | |||
</pre> | |||
=Show System Timezone= | |||
<pre> | |||
import tzlocal | |||
tzlocal.get_localzone() | |||
# <DstTzInfo 'Asia/Taipei' LMT+8:06:00 STD> | |||
tzlocal.get_localzone().zone | |||
# 'Asia/Taipei' | |||
from time import gmtime, strftime | |||
print(strftime("%z", gmtime())) | |||
# +0800 | |||
</pre> | |||
= Find Timezones Of A Certain Country = | |||
<pre> | |||
import pytz | |||
pytz.country_timezones('tw') | |||
# ['Asia/Taipei'] | |||
pytz.country_timezones('cn') | |||
# ['Asia/Shanghai', 'Asia/Urumqi'] | |||
</pre> | |||
=Other Examples= | |||
Since dateutil uses the same timezone model as the datetime lib, you can set the tzinfo property straight away. You can also use .replace(tzinfo=...) safely. | |||
<pre> | |||
import dateutil | |||
aware_datetime = datetime(2020, 1, 5, 10, 12, tzinfo=dateutil.tz.gettz('Europe/London')) | |||
print(aware_datetime) | |||
# 2020-01-05 10:12:00+00:00 | |||
</pre> | |||
By the way, the procedure is identical if you use the zoneinfo module on Python 3.9: | |||
<pre> | |||
from zoneinfo import ZoneInfo | |||
aware_datetime = datetime(2020, 1, 5, 10, 12, tzinfo=ZoneInfo('Europe/London')) | |||
</pre> | </pre> | ||
Latest revision as of 20:55, 5 June 2022
Links
Distinguishing between TZ Aware and TZ Naive Objects
from datetime import datetime now = datetime.now() now = now.replace(tzinfo=datetime.timezone.utc) if now.tzinfo == None or \ now.tzinfo.utcoffset(now) == None: # If these conditions are met the object is unaware print("Unaware") else: print("Aware") print(now.isoformat())
Binding with Timezone Info
cat !$ cat ./py_tz_example_01.py #!/usr/bin/env python3 import pytz from datetime import datetime def list_tz(): for tz in pytz.all_timezones: print(tz) def example(tz_name): specified_tz = pytz.timezone(tz_name) # transform to a time using a specific timezone tz_aware_dt = datetime.now(tz=specified_tz) print(f"TZ aware datetime value |{tz_aware_dt.isoformat()}| for timezone - '{tz_name}'") # list_tz() print(f"TZ naive datetime value |{datetime.now().isoformat()}|") example("America/New_York") example("America/Vancouver") example("Asia/Tokyo") example("Australia/Sydney") example("Europe/London") example("Europe/Paris")
Output
% ./py_tz_example_01.py TZ naive datetime value |2022-06-05T09:48:41.237251| TZ aware datetime value |2022-06-04T19:48:41.249310-04:00| for timezone - 'America/New_York' TZ aware datetime value |2022-06-04T16:48:41.249630-07:00| for timezone - 'America/Vancouver' TZ aware datetime value |2022-06-05T08:48:41.249701+09:00| for timezone - 'Asia/Tokyo' TZ aware datetime value |2022-06-05T09:48:41.249923+10:00| for timezone - 'Australia/Sydney' TZ aware datetime value |2022-06-05T00:48:41.250303+01:00| for timezone - 'Europe/London' TZ aware datetime value |2022-06-05T01:48:41.250543+02:00| for timezone - 'Europe/Paris'
Explicit Numerical Offsets from UTC
#!/usr/bin/env python3 from datetime import datetime, timezone dt = datetime.now() # This is a naive datetime value print(f" TZ naive datetime value |{dt.isoformat()}|") print(f" dt.tzinfo |{dt.tzinfo}|") # Cast this as UTC dt = dt.replace(tzinfo=timezone.utc) # Define the offset offset = "+1000" # "Australia/Melbourne" # Convert as so... tz_aware_dt = dt.astimezone(datetime.strptime(offset, "%z").tzinfo) print(f" TZ Aware datetime value |{tz_aware_dt.isoformat()}|")
Output
% ./py_tz_example_02.py TZ naive datetime value |2022-06-05T09:49:37.782118| dt.tzinfo |None| TZ Aware datetime value |2022-06-05T19:49:37.782118+10:00|
Changing Timezones
from pytz import timezone from datetime import datetime fmt = "%Y-%m-%d %H:%M:%S %Z%z" # Current datetime in UTC dt = datetime.now(timezone('UTC')) print(dt.strftime(fmt)) # Convert to US/Pacific time zone dt = dt.astimezone(timezone('Asia/Tokyo')) print(dt.strftime(fmt)) # Convert to Europe/Paris time zone dt = dt.astimezone(timezone('Europe/Paris')) print dt.strftime(fmt)
Output
./tst_ft.py 2022-06-05 09:41:02 UTC+0000 2022-06-05 18:41:02 JST+0900 2022-06-05 11:41:02 CEST+0200
Show System Timezone
import tzlocal tzlocal.get_localzone() # <DstTzInfo 'Asia/Taipei' LMT+8:06:00 STD> tzlocal.get_localzone().zone # 'Asia/Taipei' from time import gmtime, strftime print(strftime("%z", gmtime())) # +0800
Find Timezones Of A Certain Country
import pytz pytz.country_timezones('tw') # ['Asia/Taipei'] pytz.country_timezones('cn') # ['Asia/Shanghai', 'Asia/Urumqi']
Other Examples
Since dateutil uses the same timezone model as the datetime lib, you can set the tzinfo property straight away. You can also use .replace(tzinfo=...) safely.
import dateutil aware_datetime = datetime(2020, 1, 5, 10, 12, tzinfo=dateutil.tz.gettz('Europe/London')) print(aware_datetime) # 2020-01-05 10:12:00+00:00
By the way, the procedure is identical if you use the zoneinfo module on Python 3.9:
from zoneinfo import ZoneInfo aware_datetime = datetime(2020, 1, 5, 10, 12, tzinfo=ZoneInfo('Europe/London'))