Класс Trunc

Класс Trunc из модуля django.db.models.functions применяется для усечения значений даты и времени до заданной точности. Он позволяет округлить дату до года, месяца, дня, часа, минуты или секунды. Класс особенно полезен при группировке записей по временным интервалам в аннотациях и агрегациях.

Основные аргументы конструктора Trunc:

Синтаксис

pythonfrom django.db.models.functions import Trunc

Model.objects.annotate(
  truncated_field=Trunc('field_name', kind='day')
)

Пример

Рассмотрим модель Article с полем created_at типа DateTimeField. Сгруппируем статьи по дням и подсчитаем количество записей за каждый день:

pythonfrom django.db.models import Count
from django.db.models.functions import Trunc
from myapp.models import Article

# Группировка по дням
articles_by_day = (
  Article.objects
  .annotate(day=Trunc('created_at', kind='day'))
  .values('day')
  .annotate(count=Count('id'))
  .order_by('day')
)

for entry in articles_by_day:
  print(f"{entry['day']}: {entry['count']} articles")

Результат выполнения кода:

python"2025-01-01 00:00:00+00:00: 5 articles"
"2025-01-02 00:00:00+00:00: 3 articles"
"2025-01-03 00:00:00+00:00: 8 articles"

Пример

Сгруппируем записи по месяцам и подсчитаем общее количество комментариев за каждый месяц:

pythonfrom django.db.models import Sum
from django.db.models.functions import Trunc
from myapp.models import Comment

# Группировка по месяцам
comments_by_month = (
  Comment.objects
  .annotate(month=Trunc('created_at', kind='month'))
  .values('month')
  .annotate(total=Sum('count'))
  .order_by('month')
)

for entry in comments_by_month:
  print(f"{entry['month']}: {entry['total']} comments")

Результат выполнения кода:

python"2025-01-01 00:00:00+00:00: 150 comments"
"2025-02-01 00:00:00+00:00: 210 comments"
"2025-03-01 00:00:00+00:00: 180 comments"

Пример

Используем усечение до часа для анализа активности пользователей в течение дня:

pythonfrom django.db.models import Count
from django.db.models.functions import Trunc
from myapp.models import UserAction

# Группировка по часам
actions_by_hour = (
  UserAction.objects
  .annotate(hour=Trunc('timestamp', kind='hour'))
  .values('hour')
  .annotate(actions=Count('id'))
  .order_by('hour')
)

for entry in actions_by_hour:
  print(f"{entry['hour']}: {entry['actions']} actions")

Результат выполнения кода:

python"2025-01-15 08:00:00+00:00: 45 actions"
"2025-01-15 09:00:00+00:00: 67 actions"
"2025-01-15 10:00:00+00:00: 89 actions"

Смотрите также

  • класс Trunc,
    который усекает дату до указанной точности
  • класс Extract,
    который извлекает отдельную часть даты
  • метод dates,
    который возвращает список уникальных дат
  • метод datetimes,
    который возвращает список уникальных дат и времени