This might be a bit of a trivial question, but can't I get django now() to be in the time zone defined in settings.TIME_ZONE
?
This is what is actually happening:
>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2012, 5, 30, 16, 30, 0, 782087, tzinfo=<UTC>)
>>> timezone.get_default_timezone()
<DstTzInfo 'Asia/Singapore' SMT+6:55:00 STD>
Django's timezone is set to UTC by default.
The solution to this problem is to use UTC in the code and use local time only when interacting with end users. Time zone support is disabled by default. To enable it, set USE_TZ = True in your settings file. In Django 5.0, time zone support will be enabled by default.
In this scenario, you either have to (1) have users registering supply their timezone, and alter your code, or (2) import django. utils timezone, see this page: django timezone module documentation.
Django's source code (as displayed in the chosen answer) explains the concept of timezone.now()
:
datetime.now()
yields the current time (in your active timezone!) without timezone information ("naive datetime"), whereas ...timezone.now()
always yields the current time in UTC (!) with timezone information.This is irritating at first sight, yes. They could have decided to yield the current time of the active timezone, but they didn't. You can still use timezone.localtime(timezone.now())
to get what you want:
from django.utils import timezone
from datetime import datetime
timezone.get_current_timezone()
# <DstTzInfo 'Antarctica/McMurdo' LMT+11:39:00 STD>
datetime.now()
# datetime.datetime(2014, 8, 19, 20, 8, 8, 440959)
timezone.localtime(timezone.now())
# datetime.datetime(2014, 8, 19, 20, 8, 14, 889429, tzinfo=<DstTzInfo 'Antarctica/McMurdo' NZST+12:00:00 STD>)
timezone.now()
# datetime.datetime(2014, 8, 19, 8, 8, 22, 273529, tzinfo=<UTC>)
datetime.utcnow()
# datetime.datetime(2014, 8, 19, 8, 8, 29, 769312)
For newcomers and ordinary users timezone.localtime(timezone.now())
is probably the most intuitive. A local time which still retains timezone information.
EDIT: The standard library equivalent for a timezone-aware local time is datetime.now().astimezone()
. astimezone applies the system local timezone by default, which allows you to correctly convert any timezone-aware datetime to your local time. To set an arbitrary timezone using timezone names you need the pytz package.
from datetime import datetime, timezone
import pytz
datetime.now()
# datetime.datetime(2022, 9, 14, 5, 26, 35, 146551)
datetime.now().astimezone()
# datetime.datetime(2022, 9, 14, 5, 26, 44, 19645, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200), 'CEST'))
datetime.now(tz=timezone.utc)
# datetime.datetime(2022, 9, 14, 3, 26, 51, 203917, tzinfo=datetime.timezone.utc)
datetime.now(tz=timezone.utc).astimezone()
# datetime.datetime(2022, 9, 14, 5, 26, 58, 546724, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200), 'CEST'))
datetime.now(tz=pytz.timezone('Europe/Kiev'))
# datetime.datetime(2022, 9, 14, 6, 27, 38, 714633, tzinfo=<DstTzInfo 'Europe/Kiev' EEST+3:00:00 DST>)
Or I could just read the source:
def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
"""
if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower
return datetime.utcnow().replace(tzinfo=utc)
else:
return datetime.now()
Answer is nope, I have to adjust it myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With