django's timezone.now does not show the right time
DjangoDjango TimezoneDjango Problem Overview
My server is located in London.
In my settings.py
I have:
TIME_ZONE = 'Europe/Moscow'
USE_TZ = True
But when I execute this:
from django.utils import timezone
print timezone.now().hour
the code prints London's time. What am I doing wrong?
UPDATE:
>> timezone.now()
datetime.datetime(2013, 4, 16, 12, 28, 52, 797923, tzinfo=<UTC>)
Interesting... tzinfo = <UTC>
. So maybe it prints not a London time, but UTC's +0 time? Anyway, is there any way to make Django show Moscow time?
Also when I render template with now = timezone.now()
{{ now.hour }}
prints 12 (London time)
{{ now|date:"G" }}
prints 16 (Moscow time)
Django Solutions
Solution 1 - Django
See question #2 in the "Usage" section of the Django docs.
>>> from django.utils import timezone
>>> timezone.localtime(timezone.now())
Since the doc above also talks about a best practice, including an excerpt below:
> How can I obtain the local time in the current time zone? > > Well, the first question is, do you really need to? > > You should only use local time when you’re interacting with humans, > and the template layer provides filters and tags to convert datetimes > to the time zone of your choice. > > Furthermore, Python knows how to compare aware datetimes, taking into > account UTC offsets when necessary. It’s much easier (and possibly > faster) to write all your model and view code in UTC. So, in most > circumstances, the datetime in UTC returned by > django.utils.timezone.now() will be sufficient.
Solution 2 - Django
from django.utils import timezone
time = timezone.localtime()
It will give your local time that whatever your TIME_ZONE set to.
time = timezone.localtime(timezone.now()) # same result, but it is redundant.
Solution 3 - Django
The reason it works in the template but not in the view python code is somewhat in the docs: https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-TIME_ZONE
"..... this is the default time zone that Django will use to display datetimes in templates and to interpret datetimes entered in forms."
This is why {{ now|date:"G" }}
prints 16 (Moscow time) prints the Moscow time!
Another note is timezone.now()
in a normally configured Django app will pick up whatever TIME_ZONE
is set to in the settings ('America/New_York' in example below). But can be overridden as well (see below to Paris for example in a middleware or directly in a view for that request)
In [27]: timezone.localtime(timezone.now())
Out[27]: datetime.datetime(2021, 2, 23, 1, 53, 49, 793743, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
In [29]: timezone.activate(pytz.timezone("Europe/Paris"))
In [30]: timezone.localtime(timezone.now())
Out[30]: datetime.datetime(2021, 2, 23, 7, 54, 19, 21898, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
Solution 4 - Django
django's use_tz = True returns datetime object in
test1: when use_tz = true; timezone= us/eastern; system timezone: UTC+5:30
datetime.datetime.today() # returned naive datetime with locale time
timezone.now() returned # UTC
timezone.localtime() # returned us/eastern
test2: when use_tz = true; timezone= us/eastern; system timezone: UTC-5
datetime.datetime.today() # returned naive datetime in with locale time
timezone.now() # returned UTC timezone
timezone.localtime() # in US/eastern timezone
test3: when use_tz = False; timezone= us/eastern; system timezone: UTC-5
timezone.now() # returned naive datetime with system time
timezone.localtime() # returned traceback ValueError: localtime() cannot be applied to a naive datetime
test4: when use_tz = False; timezone= UTC; system timezone: UTC+5:30
datetime.datetime.today() # returned naive datetime in system timezone
timezone.now() # returned naive datetime in system timezone
timezone.localtime() # returned traceback