Как отфильтровать запрос в 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
Это дает то, что мне нужно, но кажется, что это должно быть возможно сделать полностью в запросе, что может быть более элегантным решением.