1

Can anyone explain the difference between 'django.db.models.functions.Now' and 'django.utils.timezone.now'?

For example, am I correct that functions.Now() returns the system time without timezone stamp, and timezone.now() would return UTC timestamp?

When I use print(timezone.now()) I get the expected timestamp however when I print(functions.Now()) I get a blank string. Why is this?

In what circumstances is it appropriate to use one method over the other?

alias51
  • 8,178
  • 22
  • 94
  • 166

1 Answers1

2

The timezone.now(…) function [Django-doc] returns a datetime object with the timezone, given the USE_TZ setting [Django-doc] is used.

Now [Django-doc] on the other hand, is a database expression. Indeed, it does not determine a datetime. It will use NOW() at the database side where you query. It will thus work with the clock of the database. If the database thus runs on the same server, it is the server time, whereas if it runs on a different server, it can be a few seconds/minutes earlier/later if the clocks of the two systems are not completely in sync.

If you thus query with:

from django.utils import timezone

Post.objects.filter(published_at__lte=timezone.now())

Then it will make a query that looks like:

SELECT post.*
FROM post
WHERE published_at <= 2022-07-27 15:40:00  -- time from Django/Python

whereas if we use:

from django.db.models.functions import Now

Post.objects.filter(published_at__lte=Now())

it will query with:

SELECT post.*
FROM post
WHERE published_at <= NOW()  -- databae timestamp
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Thanks, so if I am using timezone aware fields in django I am best to use `timezone.now()` to compare dates? – alias51 Jul 27 '22 at 17:08
  • 1
    @alias51: normally `NOW()` is the timestamp of the database. On a reasonable server, that should be (close) to the real time. Usually the main advantage is that you can use a `queryset = Post.objects.filter(published_at__lte=Now())` to obtain all posts that are published for example in a `ListView`, whereas for `timezone.now()` you will need to work with `get_queryset`, since you each time have to fetch the current datetime: using it at `queryset = ...` would mean that you always take the `datetime` at the moment that file was interpreted for the first time. – Willem Van Onsem Jul 27 '22 at 17:58