[Django]-Django query for all items from today

3đź‘Ť

âś…

This is what I ended up doing. I am not trying to deal with timezones or anything so this works fine.

today = datetime.date.today()
yesterday = today - datetime.timedelta(days=1)

todays_pages = Page.objects.filter(date_created__gt = today)[:25]
yesterdays_pages = Page.objects.filter(date_created__gt = yesterday, date_created__lt = today)[:25]
👤Chase Roberts

7đź‘Ť

You can try like this:

todays_pages = Page.objects.filter(date_created__gte = datetime.date.now().replace(hour=0,minute=0,second=0))
👤ruddra

3đź‘Ť

from datetime import datetime

today = datetime.now()
current_day = Page.objects.filter(date_created__date=datetime.date(today))\
    .values('category','name')

this worked for me

got idea from https://docs.djangoproject.com/en/1.11/ref/models/querysets/#week

👤Immanuel

1đź‘Ť

datetime.datetime.now() is time zone unaware. You may want to use django.utils.timezone to convert.

👤Kracekumar

0đź‘Ť

You could filter the objects based on a time. The way that I would do it is something like this…

today = datetime.date.today()
todays_pages = Page.objects.filter(date_created__range=[today,])

I have not tried this code specifically but this is my best guess on how to get all posts that have the current calendar day.

👤Anthony Dito

0đź‘Ť

This seems like it should be easy, but it is in fact a non-trivial problem, due primarily to timezones. Your DateTimeField stores a particular point in time. Which date that point in time occurred on could be different in different timezones – the exact same point in time could be Wednesday morning in Berlin but Tuesday night in San Francisco.

Given a date you want to query for and a timezone, the strategy is this:

1) Construct a datetime for “start of that day in that timezone” and a datetime for “end of that day in that timezone”.

2) Query for pages with a date_created between your start and end datetimes.

In some code I wrote recently, I have a combine function for combining a date, a time, and a timezone into a datetime:

from django.utils import timezone
import pytz

def combine(adate, atime, tz=None, is_dst=None):
    """Turn a date and a time into a datetime in given timezone (or default).

    The ``is_dst`` argument controls the handling of ambiguous datetimes
    (e.g. during fall DST changeover), and nonexistent datetimes (e.g. during
    spring DST changeover). If it is ``None`` (the default), these cases will
    return ``None`` instead of a datetime. If it is ``True``, these cases will
    be resolved by always assuming DST, and if ``False`` by assuming no-DST.

    """
    tz = tz or timezone.get_current_timezone()
    naive = dt(adate.year, adate.month, adate.day, atime.hour, atime.minute)
    try:
        return tz.normalize(tz.localize(naive, is_dst=is_dst))
    except pytz.InvalidTimeError:
        return None

Then your query looks like this:

def get_pages_created_on_date(for_date):
    start = combine(for_date, time(0))
    end = combine(for_date + datetime.timedelta(days=1), time(0))
    return Page.objects.filter(date_created__gte=start, date_created__lt=end)

That version just uses the currently activated timezone (which is probably the timezone configured in your Django settings file, unless you’ve done some additional work to activate a local timezone for the current request’s user).

I’m not aware of any timezone in which the DST transition occurs at midnight, which should make this code safe against DST changeover issues. But if there is such a timezone, and you may need to handle datetimes in it, then your query function would need to pass an is_dst flag to combine.

If you’re passing today to this query, you have to also think about how you generate your date value for today. Calling datetime.date.today() will always give you today’s date in your server operating system’s local timezone. This may not correspond with your Django-settings timezone, or with the currently-activated Django timezone, which will cause the query to not give correct results. For correct timezone handling, you should use a today function like this instead:

from django.utils import timezone

def today():
    return timezone.localtime(timezone.now()).date()

TL;DR: correct handling of dates and times is hard. Hope this helps; good luck!

👤Carl Meyer

Leave a comment