93π
In general, to convert an arbitrary timezone-aware datetime to a naive (local) datetime, Iβd use the pytz
module and astimezone
to convert to local time, and replace
to make the datetime naive:
In [76]: import pytz
In [77]: est=pytz.timezone('US/Eastern')
In [78]: d.astimezone(est)
Out[78]: datetime.datetime(2010, 10, 30, 13, 21, 12, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
In [79]: d.astimezone(est).replace(tzinfo=None)
Out[79]: datetime.datetime(2010, 10, 30, 13, 21, 12)
But since your particular datetime seems to be in the UTC timezone, you could do this instead:
In [65]: d
Out[65]: datetime.datetime(2010, 10, 30, 17, 21, 12, tzinfo=tzutc())
In [66]: import datetime
In [67]: import calendar
In [68]: datetime.datetime.fromtimestamp(calendar.timegm(d.timetuple()))
Out[68]: datetime.datetime(2010, 10, 30, 13, 21, 12)
By the way, you might be better off storing the datetimes as naive UTC datetimes instead of naive local datetimes. That way, your data is local-time agnostic, and you only convert to local-time or any other timezone when necessary. Sort of analogous to working in unicode as much as possible, and encoding only when necessary.
So if you agree that storing the datetimes in naive UTC is the best way, then all youβd need to do is define:
local_d = d.replace(tzinfo=None)
74π
In recent versions of Django (at least 1.4.1):
from django.utils.timezone import localtime
result = localtime(some_time_object)
- [Django]-Coverage.py warning: No data was collected. (no-data-collected)
- [Django]-Django form fails validation on a unique field
- [Django]-Error: Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>
3π
A portable robust solution should use the tz database. To get local timezone as pytz
tzinfo
object, use tzlocal
module:
#!/usr/bin/env python
import iso8601
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone()
aware_dt = iso8601.parse_date("2010-10-30T17:21:12Z") # some aware datetime object
naive_local_dt = aware_dt.astimezone(local_timezone).replace(tzinfo=None)
Note: it might be tempting to use something like:
#!/usr/bin/env python3
# ...
naive_local_dt = aware_dt.astimezone().replace(tzinfo=None)
but it may fail if the local timezone has a variable utc offset but python does not use a historical timezone database on a given platform.
- [Django]-URL-parameters and logic in Django class-based views (TemplateView)
- [Django]-Feedback on using Google App Engine?
- [Django]-What is the difference render() and redirect() in Django?
1π
Using python-dateutil
you can parse the date in iso-8561 format with dateutil.parsrser.parse()
that will give you an aware datetime
in UTC/Zulu timezone.
Using .astimezone()
you can convert it to an aware datetime in another timezone.
Using .replace(tzinfo=None)
will convert the aware datetime into a naive datetime.
from datetime import datetime
from dateutil import parser as datetime_parser
from dateutil.tz import tzutc,gettz
aware = datetime_parser.parse('2015-05-20T19:51:35.998931Z').astimezone(gettz("CET"))
naive = aware.replace(tzinfo=None)
In general the best idea is to convert all dates to UTC and store them that way, and convert them back to local as needed. I use aware.astimezone(tzutc()).replace(tzinfo=None)
to make sure is in UTC and convert to naive.
- [Django]-Get class name of django model
- [Django]-Django.contrib.auth.logout in Django
- [Django]-VueJS + Django Channels
1π
I use this helper function all the time.
from datetime import datetime
import pytz
def tz_convert(t: datetime, tz=pytz.utc):
'''
Convert a timestamp to the target timezone.
If the timestamp is naive, the timezone is set to the target timezone.
'''
if not t.tzinfo:
tc = t.replace(tzinfo=tz)
else:
tc = t.astimezone(tz)
return tc
Demo
# tz-aware timestamp
>>> t = datetime.now(tz=pytz.utc)
>>> t.isoformat()
'2022-09-15T08:24:38.093312+00:00'
>>> tc = tz_convert(t, pytz.timezone('est'))
>>> tc.isoformat()
'2022-09-15T03:24:38.093312-05:00'
# tz-naive timestamp
>>> t = datetime.now()
>>> t.isoformat()
'2022-09-15T10:22:41.464200'
>>> tc = tz_convert(t, pytz.timezone('est'))
>>> tc.isoformat()
'2022-09-15T10:22:41.464200-05:00'
- [Django]-Running Django with FastCGI or with mod_python
- [Django]-User Registration with error: no such table: auth_user
- [Django]-Django REST framework post array of objects