У нас есть таблица, которая содержит несколько событий и когда они были добавлены. Часовой пояс по умолчанию, используемый для хранения событий: UT C. Например:
class Events:
type = models.CharField(max_length=45, null=False)
date_added = models.DateTimeField(auto_now_add=True)
Теперь мы хотим получить количество различных типов событий в день между двумя датами - start_date и end_date. Например: for start_date = "2020-03-1" и end_date = "2020-03-31", вывод должен быть -
[{
"date" : "2020-03-1",
"event1" : 200,
"event2" : 606,
"event3" : 595
},
{
"date" : "2020-03-2",
"event1" : 357,
"event2" : 71,
"event3" : 634
},
{
"date" : "2020-03-3",
"event1" : 106,
"event2" : 943,
"event3" : 315
},
{
"date" : "2020-03-4",
"event1" : 187,
"event2" : 912,
"event3" : 743
},
.
.
.
.
{
"date" : "2020-03-31",
"event1" : 879,
"event2" : 292,
"event3" : 438
}]
Поскольку пользователи находятся в разных часовых поясах (Америка, Европа, Азия, et c), мы хотим преобразовать часовой пояс в соответствии с пользователем перед подсчетом событий. Подсчет в UT C будет иметь неправильный счет в день в часовом поясе пользователя. Например, событие, созданное 3 марта в 1:30 по IST, будет показано 2 марта, в 20:00 в UT C и подсчитано соответственно.
Это будет очень дорого, если мы сделаем это с использованием для l oop. Поэтому мы хотим сделать это на уровне БД, используя Django ORM. Если невозможно полностью зависеть от Django ORM, мы хотим сделать его максимально эффективным.
Лучший запрос, который мы могли бы сформулировать, был:
Events.objects.filter(
pk = user_pk, date__range = (
(end_date - time_delta).strftime("%Y-%m-%d"),
end_date.strftime("%Y-%m-%d")
)
).extra({
"date_added" : "date(date_added)"
}).values(
"date_added",
"type"
).annotate(
models.Count("type")
)
Где мы получаем результаты, такие как:
<QuerySet [{'date_added': datetime.date(2020, 3, 6), 'type': 'event1', 'type__count': 30},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event2', 'type__count': 189},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event3', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 6), 'type': 'event4', 'type__count': 3},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event2', 'type__count': 57},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event1', 'type__count': 23},
{'date_added': datetime.date(2020, 3, 9), 'type': 'event4', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 10), 'type': 'event1', 'type__count': 5},
{'date_added': datetime.date(2020, 3, 10), 'type': 'event2', 'type__count': 21},
{'date_added': datetime.date(2020, 3, 11), 'type': 'event2', 'type__count': 9},
{'date_added': datetime.date(2020, 3, 11), 'type': 'event1', 'type__count': 15},
{'date_added': datetime.date(2020, 3, 12), 'type': 'event2', 'type__count': 49},
{'date_added': datetime.date(2020, 3, 13), 'type': 'event2', 'type__count': 8},
{'date_added': datetime.date(2020, 3, 13), 'type': 'event1', 'type__count': 3},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event1', 'type__count': 16},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event2', 'type__count': 26},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event4', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 17), 'type': 'event3', 'type__count': 1},
{'date_added': datetime.date(2020, 3, 18), 'type': 'event2', 'type__count': 64},
{'date_added': datetime.date(2020, 3, 18), 'type': 'event1', 'type__count': 11},
'...(remaining elements truncated)...']>
Для этого все равно потребуется для l oop, чтобы все события с одинаковой датой были добавлены в один диктовку, но проблема с часовым поясом все еще сохраняется.
Как это решить?