77

I'm a bit confused by the daylight savings handling

settings.py:

TIME_ZONE = 'Europe/London'
USE_TZ = True

in the django shell:

>>> from django.utils import timezone
>>> import datetime
>>> print timezone.now()
2012-05-28 11:19:42.897000+00:00
>>> print timezone.make_aware(datetime.datetime.now(),timezone.get_default_timez
one())
2012-05-28 12:20:03.224000+01:00

why are they not the same with respect to daylight savings? Both should be locale aware, no?

I've read the docs but am none the wiser.

meepmeep
  • 3,018
  • 7
  • 33
  • 47

5 Answers5

104

According to timezone.now() 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()

It's based on utc instead of your default timezone. You could achieve same value by using

now = timezone.make_aware(datetime.datetime.now(),timezone.get_default_timezone())
print now.astimezone(timezone.utc)
djvg
  • 11,722
  • 5
  • 72
  • 103
okm
  • 23,575
  • 5
  • 83
  • 90
  • 34
    that's somewhat counter-intuitive. I had assumed timezone.now() would have given me now in the default timezone! Not very pythonic in my opinion. Using .astimezone() has fixed my issue, thanks. – meepmeep May 28 '12 at 16:42
  • Why do I keep getting a error when I do the following: >>> import datetime >>> from django.utils import timezone >>> from polls.models import Question >>> # create a Question instance with pub_date 30 days in the future >>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30)) >>> # was it published recently? >>> future_question.was_published_recently() True – pitchblack408 Aug 30 '14 at 17:45
  • >>> future_question.was_published_recently() Traceback (most recent call last): File "", line 1, in File "C:\Users\michmar3\workspace\pollsite\polls\models.py", line 17, in was_p ublished_recently return self.pub_date >= datetime.datetime.now() - datetime.timedelta(days=1) File "C:\jython2.7b2\Lib\datetime.py", line 1727, in __ge__ return self.__cmp(other) >= 0 File "C:\jython2.7b2\Lib\datetime.py", line 1765, in _datetime__cmp raise TypeError("cannot compare naive and aware datetimes") TypeError: cannot compare naive and aware datetimes – pitchblack408 Aug 30 '14 at 17:45
  • @pitchblack408 Check [this](http://stackoverflow.com/a/10653144/165603). Try `timezone.now()` instead of `datetime.datetime.now()`, in `was_published_recently`. – okm Aug 31 '14 at 08:52
  • 1
    @meepmeep That's indeed counterintuitive. At first glance. At second one, you might come to realize that that happens because Django keeps time in UTC until it has to present it to the user. That's where conversion happens. Template tags such as `now` [does](https://github.com/django/django/blob/2.2.1/django/template/defaulttags.py#L1150) this [automatically](https://github.com/django/django/blob/2.2.1/django/template/defaulttags.py#L374). – x-yuri May 22 '19 at 10:48
37

Since Django 1.11 you can simply call django.utils.timezone.localtime to fetch datetime for your default timezone.

>>> from django.utils import timezone
>>> timezone.localtime()

From docs:

Converts an aware datetime to a different time zone, by default the current time zone.

When value is omitted, it defaults to now().

This function doesn’t work on naive datetimes; use make_aware() instead.

Nathan Osman
  • 71,149
  • 71
  • 256
  • 361
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
6

You can pass a param to datetime.datetime.now():

import pytz, datetime
utc = pytz.utc
utc_now = datetime.datetime.now(tz=utc)

Or use timezone, a la:

from django.utils import timezone

now = timezone.now()

https://docs.djangoproject.com/en/2.1/topics/i18n/timezones/

mecampbellsoup
  • 1,260
  • 18
  • 16
4
from datetime import datetime
from django.utils import timezone

def now():
    try:
        return timezone.localtime(timezone.now()).strftime('%Y-%m-%dT%H:%M:%S')
    except Exception as exp:
        print('TimeZone is not set - {}'.format(exp))
        return datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

If you set TIME_ZONE = 'Europe/London' and USE_TZ = True in Django setting, it runs the try section, otherwise it runs the except section.


[NOTE]:

  • .strftime() is an option
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
0
from datetime import datetime
from pytz import timezone

# one can get any time for respective timezone
current_time = datetime.now(timezone('Asia/Kolkata'))
print("time in india :", current_time)
Ashish Singh
  • 97
  • 1
  • 3