Как отфильтровать запрос в Django по week_day, используя определенный часовой пояс?

Я пытаюсь отфильтровать данные по дню недели. Это достаточно легко сделать с помощью фильтра week_day. Проблема в том, что, поскольку все даты хранятся в формате UTC, именно так они и фильтруются. Как можно локализовать запрос?

Например, пытаясь подсчитать все записи, которые были созданы в определенные дни, я использую следующее:

chart_data = [
            data.filter(created__week_day=1).count(),  # Sunday
            data.filter(created__week_day=2).count(),  # Monday
            data.filter(created__week_day=3).count(),  # Tuesday
            data.filter(created__week_day=4).count(),  # Wednesday
            data.filter(created__week_day=5).count(),  # Thursday
            data.filter(created__week_day=6).count(),  # Friday
            data.filter(created__week_day=7).count(),  # Saturday
        ]

Как заставить эти запросы считать записи, локализованные, например, в часовом поясе 'America/New_York'?

Чтобы отфильтровать запрос по дням недели с учетом конкретного часового пояса, можно использовать Django's timezone utilities для локализации UTC dates before applying the filter.

from django.utils import timezone
from django.db.models import Count
from django.db.models.functions import ExtractWeekDay
import pytz

#NOTE i am  Assuming that `data` is your QuerySet and 'created' is your DateTimeField update it if required
timezone = pytz.timezone('America/New_York')

#NOTE you can annotate QuerySet to get localized weekday
localized_data = data.annotate(
    localized_weekday=ExtractWeekDay(timezone.localize(data.values('created')))
)

#NOTE you can count the occurrences of each weekday
chart_data = [
    localized_data.filter(localized_weekday=1).count(),
    localized_data.filter(localized_weekday=2).count(),
    localized_data.filter(localized_weekday=3).count(), 
    localized_data.filter(localized_weekday=4).count(), 
    localized_data.filter(localized_weekday=5).count(),  
    localized_data.filter(localized_weekday=6).count(), 
    localized_data.filter(localized_weekday=7).count(), 
]

Я нашел решение, хотя оно отличается от того, что я предполагал, и это, вероятно, не самый эффективный способ сделать это.

from .models import Track
from collections import Counter
import pytz


data = Trackers.objects.all()
days_of_week = []
for tracked in data:
    # Convert created time to US/Eastern timezone
    created_eastern = tracked.created.astimezone(tz)
    # Get the day of the week (0=Monday, 6=Sunday)
    day_of_week = created_eastern.weekday()
    # Append the day of the week to the list
    days_of_week.append(day_of_week)
# Count occurrences of each day
day_counts = Counter(days_of_week)
# Initialize a list for 7 days with zeros
chart_data = [0 for _ in range(7)]
for day_number, count in sorted(day_counts.items()):
    chart_data[day_number] = count

Это дает то, что мне нужно, но кажется, что это должно быть возможно сделать полностью в запросе, что может быть более элегантным решением.

Вернуться на верх