database-functions.txt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. ==================
  2. Database Functions
  3. ==================
  4. .. module:: django.db.models.functions
  5. :synopsis: Database Functions
  6. The classes documented below provide a way for users to use functions provided
  7. by the underlying database as annotations, aggregations, or filters in Django.
  8. Functions are also :doc:`expressions <expressions>`, so they can be used and
  9. combined with other expressions like :ref:`aggregate functions
  10. <aggregation-functions>`.
  11. We'll be using the following model in examples of each function::
  12. class Author(models.Model):
  13. name = models.CharField(max_length=50)
  14. age = models.PositiveIntegerField(null=True, blank=True)
  15. alias = models.CharField(max_length=50, null=True, blank=True)
  16. goes_by = models.CharField(max_length=50, null=True, blank=True)
  17. We don't usually recommend allowing ``null=True`` for ``CharField`` since this
  18. allows the field to have two "empty values", but it's important for the
  19. ``Coalesce`` example below.
  20. ``Cast``
  21. ========
  22. .. class:: Cast(expression, output_field)
  23. .. versionadded:: 1.10
  24. Forces the result type of ``expression`` to be the one from ``output_field``.
  25. Usage example::
  26. >>> from django.db.models import FloatField
  27. >>> from django.db.models.functions import Cast
  28. >>> Value.objects.create(integer=4)
  29. >>> value = Value.objects.annotate(as_float=Cast('integer', FloatField)).get()
  30. >>> print(value.as_float)
  31. 4.0
  32. ``Coalesce``
  33. ============
  34. .. class:: Coalesce(*expressions, **extra)
  35. Accepts a list of at least two field names or expressions and returns the
  36. first non-null value (note that an empty string is not considered a null
  37. value). Each argument must be of a similar type, so mixing text and numbers
  38. will result in a database error.
  39. Usage examples::
  40. >>> # Get a screen name from least to most public
  41. >>> from django.db.models import Sum, Value as V
  42. >>> from django.db.models.functions import Coalesce
  43. >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
  44. >>> author = Author.objects.annotate(
  45. ... screen_name=Coalesce('alias', 'goes_by', 'name')).get()
  46. >>> print(author.screen_name)
  47. Maggie
  48. >>> # Prevent an aggregate Sum() from returning None
  49. >>> aggregated = Author.objects.aggregate(
  50. ... combined_age=Coalesce(Sum('age'), V(0)),
  51. ... combined_age_default=Sum('age'))
  52. >>> print(aggregated['combined_age'])
  53. 0
  54. >>> print(aggregated['combined_age_default'])
  55. None
  56. .. warning::
  57. A Python value passed to ``Coalesce`` on MySQL may be converted to an
  58. incorrect type unless explicitly cast to the correct database type:
  59. >>> from django.db.models.expressions import RawSQL
  60. >>> from django.utils import timezone
  61. >>> now = timezone.now()
  62. >>> now_sql = RawSQL("cast(%s as datetime)", (now,))
  63. >>> Coalesce('updated', now_sql)
  64. ``Concat``
  65. ==========
  66. .. class:: Concat(*expressions, **extra)
  67. Accepts a list of at least two text fields or expressions and returns the
  68. concatenated text. Each argument must be of a text or char type. If you want
  69. to concatenate a ``TextField()`` with a ``CharField()``, then be sure to tell
  70. Django that the ``output_field`` should be a ``TextField()``. This is also
  71. required when concatenating a ``Value`` as in the example below.
  72. This function will never have a null result. On backends where a null argument
  73. results in the entire expression being null, Django will ensure that each null
  74. part is converted to an empty string first.
  75. Usage example::
  76. >>> # Get the display name as "name (goes_by)"
  77. >>> from django.db.models import CharField, Value as V
  78. >>> from django.db.models.functions import Concat
  79. >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
  80. >>> author = Author.objects.annotate(
  81. ... screen_name=Concat('name', V(' ('), 'goes_by', V(')'),
  82. ... output_field=CharField())).get()
  83. >>> print(author.screen_name)
  84. Margaret Smith (Maggie)
  85. ``Greatest``
  86. ============
  87. .. class:: Greatest(*expressions, **extra)
  88. .. versionadded:: 1.9
  89. Accepts a list of at least two field names or expressions and returns the
  90. greatest value. Each argument must be of a similar type, so mixing text and
  91. numbers will result in a database error.
  92. Usage example::
  93. class Blog(models.Model):
  94. body = models.TextField()
  95. modified = models.DateTimeField(auto_now=True)
  96. class Comment(models.Model):
  97. body = models.TextField()
  98. modified = models.DateTimeField(auto_now=True)
  99. blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
  100. >>> from django.db.models.functions import Greatest
  101. >>> blog = Blog.objects.create(body='Greatest is the best.')
  102. >>> comment = Comment.objects.create(body='No, Least is better.', blog=blog)
  103. >>> comments = Comment.objects.annotate(last_updated=Greatest('modified', 'blog__modified'))
  104. >>> annotated_comment = comments.get()
  105. ``annotated_comment.last_updated`` will be the most recent of ``blog.modified``
  106. and ``comment.modified``.
  107. .. warning::
  108. The behavior of ``Greatest`` when one or more expression may be ``null``
  109. varies between databases:
  110. - PostgreSQL: ``Greatest`` will return the largest non-null expression,
  111. or ``null`` if all expressions are ``null``.
  112. - SQLite, Oracle, and MySQL: If any expression is ``null``, ``Greatest``
  113. will return ``null``.
  114. The PostgreSQL behavior can be emulated using ``Coalesce`` if you know
  115. a sensible minimum value to provide as a default.
  116. ``Least``
  117. =========
  118. .. class:: Least(*expressions, **extra)
  119. .. versionadded:: 1.9
  120. Accepts a list of at least two field names or expressions and returns the
  121. least value. Each argument must be of a similar type, so mixing text and numbers
  122. will result in a database error.
  123. .. warning::
  124. The behavior of ``Least`` when one or more expression may be ``null``
  125. varies between databases:
  126. - PostgreSQL: ``Least`` will return the smallest non-null expression,
  127. or ``null`` if all expressions are ``null``.
  128. - SQLite, Oracle, and MySQL: If any expression is ``null``, ``Least``
  129. will return ``null``.
  130. The PostgreSQL behavior can be emulated using ``Coalesce`` if you know
  131. a sensible maximum value to provide as a default.
  132. ``Length``
  133. ==========
  134. .. class:: Length(expression, **extra)
  135. Accepts a single text field or expression and returns the number of characters
  136. the value has. If the expression is null, then the length will also be null.
  137. Usage example::
  138. >>> # Get the length of the name and goes_by fields
  139. >>> from django.db.models.functions import Length
  140. >>> Author.objects.create(name='Margaret Smith')
  141. >>> author = Author.objects.annotate(
  142. ... name_length=Length('name'),
  143. ... goes_by_length=Length('goes_by')).get()
  144. >>> print(author.name_length, author.goes_by_length)
  145. (14, None)
  146. It can also be registered as a transform. For example::
  147. >>> from django.db.models import CharField
  148. >>> from django.db.models.functions import Length
  149. >>> CharField.register_lookup(Length, 'length')
  150. >>> # Get authors whose name is longer than 7 characters
  151. >>> authors = Author.objects.filter(name__length__gt=7)
  152. .. versionchanged:: 1.9
  153. The ability to register the function as a transform was added.
  154. ``Lower``
  155. =========
  156. .. class:: Lower(expression, **extra)
  157. Accepts a single text field or expression and returns the lowercase
  158. representation.
  159. It can also be registered as a transform as described in :class:`Length`.
  160. Usage example::
  161. >>> from django.db.models.functions import Lower
  162. >>> Author.objects.create(name='Margaret Smith')
  163. >>> author = Author.objects.annotate(name_lower=Lower('name')).get()
  164. >>> print(author.name_lower)
  165. margaret smith
  166. .. versionchanged:: 1.9
  167. The ability to register the function as a transform was added.
  168. ``Now``
  169. =======
  170. .. class:: Now()
  171. .. versionadded:: 1.9
  172. Returns the database server's current date and time when the query is executed,
  173. typically using the SQL ``CURRENT_TIMESTAMP``.
  174. Usage example::
  175. >>> from django.db.models.functions import Now
  176. >>> Article.objects.filter(published__lte=Now())
  177. <QuerySet [<Article: How to Django>]>
  178. .. admonition:: PostgreSQL considerations
  179. On PostgreSQL, the SQL ``CURRENT_TIMESTAMP`` returns the time that the
  180. current transaction started. Therefore for cross-database compatibility,
  181. ``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
  182. timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
  183. ``Substr``
  184. ==========
  185. .. class:: Substr(expression, pos, length=None, **extra)
  186. Returns a substring of length ``length`` from the field or expression starting
  187. at position ``pos``. The position is 1-indexed, so the position must be greater
  188. than 0. If ``length`` is ``None``, then the rest of the string will be returned.
  189. Usage example::
  190. >>> # Set the alias to the first 5 characters of the name as lowercase
  191. >>> from django.db.models.functions import Substr, Lower
  192. >>> Author.objects.create(name='Margaret Smith')
  193. >>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
  194. 1
  195. >>> print(Author.objects.get(name='Margaret Smith').alias)
  196. marga
  197. ``Upper``
  198. =========
  199. .. class:: Upper(expression, **extra)
  200. Accepts a single text field or expression and returns the uppercase
  201. representation.
  202. It can also be registered as a transform as described in :class:`Length`.
  203. Usage example::
  204. >>> from django.db.models.functions import Upper
  205. >>> Author.objects.create(name='Margaret Smith')
  206. >>> author = Author.objects.annotate(name_upper=Upper('name')).get()
  207. >>> print(author.name_upper)
  208. MARGARET SMITH
  209. .. versionchanged:: 1.9
  210. The ability to register the function as a transform was added.
  211. Date Functions
  212. ==============
  213. .. module:: django.db.models.functions.datetime
  214. .. versionadded:: 1.10
  215. We'll be using the following model in examples of each function::
  216. class Experiment(models.Model):
  217. start_time = models.DateTimeField()
  218. start_date = models.DateField(null=True, blank=True)
  219. end_time = models.DateTimeField(null=True, blank=True)
  220. end_date = models.DateField(null=True, blank=True)
  221. ``Extract``
  222. -----------
  223. .. class:: Extract(expression, lookup_name=None, tzinfo=None, **extra)
  224. Extracts a component of a date as a number.
  225. Takes an ``expression`` representing a ``DateField`` or ``DateTimeField`` and a
  226. ``lookup_name``, and returns the part of the date referenced by ``lookup_name``
  227. as an ``IntegerField``. Django usually uses the databases' extract function, so
  228. you may use any ``lookup_name`` that your database supports. A ``tzinfo``
  229. subclass, usually provided by ``pytz``, can be passed to extract a value in a
  230. specific timezone.
  231. Given the datetime ``2015-06-15 23:30:01.000321+00:00``, the built-in
  232. ``lookup_name``\s return:
  233. * "year": 2015
  234. * "month": 6
  235. * "day": 15
  236. * "week_day": 2
  237. * "hour": 23
  238. * "minute": 30
  239. * "second": 1
  240. If a different timezone like ``Australia/Melbourne`` is active in Django, then
  241. the datetime is converted to the timezone before the value is extracted. The
  242. timezone offset for Melbourne in the example date above is +10:00. The values
  243. returned when this timezone is active will be the same as above except for:
  244. * "day": 16
  245. * "week_day": 3
  246. * "hour": 9
  247. .. admonition:: ``week_day`` values
  248. The ``week_day`` ``lookup_type`` is calculated differently from most
  249. databases and from Python's standard functions. This function will return
  250. ``1`` for Sunday, ``2`` for Monday, through ``7`` for Saturday.
  251. The equivalent calculation in Python is::
  252. >>> from datetime import datetime
  253. >>> dt = datetime(2015, 6, 15)
  254. >>> (dt.isoweekday() % 7) + 1
  255. 2
  256. Each ``lookup_name`` above has a corresponding ``Extract`` subclass (listed
  257. below) that should typically be used instead of the more verbose equivalent,
  258. e.g. use ``ExtractYear(...)`` rather than ``Extract(..., lookup_name='year')``.
  259. Usage example::
  260. >>> from datetime import datetime
  261. >>> from django.db.models.functions import Extract
  262. >>> start = datetime(2015, 6, 15)
  263. >>> end = datetime(2015, 7, 2)
  264. >>> Experiment.objects.create(
  265. ... start_time=start, start_date=start.date(),
  266. ... end_time=end, end_date=end.date())
  267. >>> # Add the experiment start year as a field in the QuerySet.
  268. >>> experiment = Experiment.objects.annotate(
  269. ... start_year=Extract('start_time', 'year')).get()
  270. >>> experiment.start_year
  271. 2015
  272. >>> # How many experiments completed in the same year in which they started?
  273. >>> Experiment.objects.filter(
  274. ... start_time__year=Extract('end_time', 'year')).count()
  275. 1
  276. ``DateField`` extracts
  277. ~~~~~~~~~~~~~~~~~~~~~~
  278. .. class:: ExtractYear(expression, tzinfo=None, **extra)
  279. .. attribute:: lookup_name = 'year'
  280. .. class:: ExtractMonth(expression, tzinfo=None, **extra)
  281. .. attribute:: lookup_name = 'month'
  282. .. class:: ExtractDay(expression, tzinfo=None, **extra)
  283. .. attribute:: lookup_name = 'day'
  284. .. class:: ExtractWeekDay(expression, tzinfo=None, **extra)
  285. .. attribute:: lookup_name = 'week_day'
  286. These are logically equivalent to ``Extract('date_field', lookup_name)``. Each
  287. class is also a ``Transform`` registered on ``DateField`` and ``DateTimeField``
  288. as ``__(lookup_name)``, e.g. ``__year``.
  289. Since ``DateField``\s don't have a time component, only ``Extract`` subclasses
  290. that deal with date-parts can be used with ``DateField``::
  291. >>> from datetime import datetime
  292. >>> from django.utils import timezone
  293. >>> from django.db.models.functions import (
  294. ... ExtractYear, ExtractMonth, ExtractDay, ExtractWeekDay
  295. ... )
  296. >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
  297. >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
  298. >>> Experiment.objects.create(
  299. ... start_time=start_2015, start_date=start_2015.date(),
  300. ... end_time=end_2015, end_date=end_2015.date())
  301. >>> Experiment.objects.annotate(
  302. ... year=ExtractYear('start_date'),
  303. ... month=ExtractMonth('start_date'),
  304. ... day=ExtractDay('start_date'),
  305. ... weekday=ExtractWeekDay('start_date'),
  306. ... ).values('year', 'month', 'day', 'weekday').get(
  307. ... end_date__year=ExtractYear('start_date'),
  308. ... )
  309. {'year': 2015, 'month': 6, 'day': 15, 'weekday': 2}
  310. ``DateTimeField`` extracts
  311. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  312. In addition to the following, all extracts for ``DateField`` listed above may
  313. also be used on ``DateTimeField``\s .
  314. .. class:: ExtractHour(expression, tzinfo=None, **extra)
  315. .. attribute:: lookup_name = 'hour'
  316. .. class:: ExtractMinute(expression, tzinfo=None, **extra)
  317. .. attribute:: lookup_name = 'minute'
  318. .. class:: ExtractSecond(expression, tzinfo=None, **extra)
  319. .. attribute:: lookup_name = 'second'
  320. These are logically equivalent to ``Extract('datetime_field', lookup_name)``.
  321. Each class is also a ``Transform`` registered on ``DateTimeField`` as
  322. ``__(lookup_name)``, e.g. ``__minute``.
  323. ``DateTimeField`` examples::
  324. >>> from datetime import datetime
  325. >>> from django.utils import timezone
  326. >>> from django.db.models.functions import (
  327. ... ExtractYear, ExtractMonth, ExtractDay, ExtractWeekDay,
  328. ... ExtractHour, ExtractMinute, ExtractSecond,
  329. ... )
  330. >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
  331. >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
  332. >>> Experiment.objects.create(
  333. ... start_time=start_2015, start_date=start_2015.date(),
  334. ... end_time=end_2015, end_date=end_2015.date())
  335. >>> Experiment.objects.annotate(
  336. ... year=ExtractYear('start_time'),
  337. ... month=ExtractMonth('start_time'),
  338. ... day=ExtractDay('start_time'),
  339. ... weekday=ExtractWeekDay('start_time'),
  340. ... hour=ExtractHour('start_time'),
  341. ... minute=ExtractMinute('start_time'),
  342. ... second=ExtractSecond('start_time'),
  343. ... ).values(
  344. ... 'year', 'month', 'day', 'weekday', 'hour', 'minute', 'second',
  345. ... ).get(end_time__year=ExtractYear('start_time'))
  346. {'year': 2015, 'month': 6, 'day': 15, 'weekday': 2, 'hour': 23, 'minute': 30, 'second': 1}
  347. When :setting:`USE_TZ` is ``True`` then datetimes are stored in the database
  348. in UTC. If a different timezone is active in Django, the datetime is converted
  349. to that timezone before the value is extracted. The example below converts to
  350. the Melbourne timezone (UTC +10:00), which changes the day, weekday, and hour
  351. values that are returned::
  352. >>> import pytz
  353. >>> tzinfo = pytz.timezone('Australia/Melbourne') # UTC+10:00
  354. >>> with timezone.override(tzinfo):
  355. ... Experiment.objects.annotate(
  356. ... day=ExtractDay('start_time'),
  357. ... weekday=ExtractWeekDay('start_time'),
  358. ... hour=ExtractHour('start_time'),
  359. ... ).values('day', 'weekday', 'hour').get(
  360. ... end_time__year=ExtractYear('start_time'),
  361. ... )
  362. {'day': 16, 'weekday': 3, 'hour': 9}
  363. Explicitly passing the timezone to the ``Extract`` function behaves in the same
  364. way, and takes priority over an active timezone::
  365. >>> import pytz
  366. >>> tzinfo = pytz.timezone('Australia/Melbourne')
  367. >>> Experiment.objects.annotate(
  368. ... day=ExtractDay('start_time', tzinfo=melb),
  369. ... weekday=ExtractWeekDay('start_time', tzinfo=melb),
  370. ... hour=ExtractHour('start_time', tzinfo=melb),
  371. ... ).values('day', 'weekday', 'hour').get(
  372. ... end_time__year=ExtractYear('start_time'),
  373. ... )
  374. {'day': 16, 'weekday': 3, 'hour': 9}
  375. ``Trunc``
  376. ---------
  377. .. class:: Trunc(expression, kind, output_field=None, tzinfo=None, **extra)
  378. Truncates a date up to a significant component.
  379. When you only care if something happened in a particular year, hour, or day,
  380. but not the exact second, then ``Trunc`` (and its subclasses) can be useful to
  381. filter or aggregate your data. For example, you can use ``Trunc`` to calculate
  382. the number of sales per day.
  383. ``Trunc`` takes a single ``expression``, representing a ``DateField`` or
  384. ``DateTimeField``, a ``kind`` representing a date part, and an ``output_field``
  385. that's either ``DateTimeField()`` or ``DateField()``. It returns a datetime or
  386. date, depending on ``output_field``, with fields up to ``kind`` set to their
  387. minimum value. If ``output_field`` is omitted, it will default to the
  388. ``output_field`` of ``expression``. A ``tzinfo`` subclass, usually provided by
  389. ``pytz``, can be passed to truncate a value in a specific timezone.
  390. Given the datetime ``2015-06-15 14:30:50.000321+00:00``, the built-in ``kind``\s
  391. return:
  392. * "year": 2015-01-01 00:00:00+00:00
  393. * "month": 2015-06-01 00:00:00+00:00
  394. * "day": 2015-06-15 00:00:00+00:00
  395. * "hour": 2015-06-15 14:00:00+00:00
  396. * "minute": 2015-06-15 14:30:00+00:00
  397. * "second": 2015-06-15 14:30:50+00:00
  398. If a different timezone like ``Australia/Melbourne`` is active in Django, then
  399. the datetime is converted to the new timezone before the value is truncated.
  400. The timezone offset for Melbourne in the example date above is +10:00. The
  401. values returned when this timezone is active will be:
  402. * "year": 2015-01-01 00:00:00+11:00
  403. * "month": 2015-06-01 00:00:00+10:00
  404. * "day": 2015-06-16 00:00:00+10:00
  405. * "hour": 2015-06-16 00:00:00+10:00
  406. * "minute": 2015-06-16 00:30:00+10:00
  407. * "second": 2015-06-16 00:30:50+10:00
  408. The year has an offset of +11:00 because the result transitioned into daylight
  409. saving time.
  410. Each ``kind`` above has a corresponding ``Trunc`` subclass (listed below) that
  411. should typically be used instead of the more verbose equivalent,
  412. e.g. use ``TruncYear(...)`` rather than ``Trunc(..., kind='year')``.
  413. The subclasses are all defined as transforms, but they aren't registered with
  414. any fields, because the obvious lookup names are already reserved by the
  415. ``Extract`` subclasses.
  416. Usage example::
  417. >>> from datetime import datetime
  418. >>> from django.db.models import Count, DateTimeField
  419. >>> from django.db.models.functions import Trunc
  420. >>> Experiment.objects.create(start_time=datetime(2015, 6, 15, 14, 30, 50, 321))
  421. >>> Experiment.objects.create(start_time=datetime(2015, 6, 15, 14, 40, 2, 123))
  422. >>> Experiment.objects.create(start_time=datetime(2015, 12, 25, 10, 5, 27, 999))
  423. >>> experiments_per_day = Experiment.objects.annotate(
  424. ... start_day=Trunc('start_time', 'day', output_field=DateTimeField())
  425. ... ).values('start_day').annotate(experiments=Count('id'))
  426. >>> for exp in experiments_per_day:
  427. ... print(exp['start_day'], exp['experiments'])
  428. ...
  429. 2015-06-15 00:00:00 2
  430. 2015-12-25 00:00:00 1
  431. >>> experiments = Experiment.objects.annotate(
  432. ... start_day=Trunc('start_time', 'day', output_field=DateTimeField())
  433. ... ).filter(start_day=datetime(2015, 6, 15))
  434. >>> for exp in experiments:
  435. ... print(exp.start_time)
  436. ...
  437. 2015-06-15 14:30:50.000321
  438. 2015-06-15 14:40:02.000123
  439. ``DateField`` truncation
  440. ~~~~~~~~~~~~~~~~~~~~~~~~
  441. .. class:: TruncYear(expression, output_field=None, tzinfo=None, **extra)
  442. .. attribute:: kind = 'year'
  443. .. class:: TruncMonth(expression, output_field=None, tzinfo=None, **extra)
  444. .. attribute:: kind = 'month'
  445. These are logically equivalent to ``Trunc('date_field', kind)``. They truncate
  446. all parts of the date up to ``kind`` which allows grouping or filtering dates
  447. with less precision. ``expression`` can have an ``output_field`` of either
  448. ``DateField`` or ``DateTimeField``.
  449. Since ``DateField``\s don't have a time component, only ``Trunc`` subclasses
  450. that deal with date-parts can be used with ``DateField``::
  451. >>> from datetime import datetime
  452. >>> from django.db.models import Count
  453. >>> from django.db.models.functions import TruncMonth, TruncYear
  454. >>> from django.utils import timezone
  455. >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
  456. >>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
  457. >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
  458. >>> Experiment.objects.create(start_time=start1, start_date=start1.date())
  459. >>> Experiment.objects.create(start_time=start2, start_date=start2.date())
  460. >>> Experiment.objects.create(start_time=start3, start_date=start3.date())
  461. >>> experiments_per_year = Experiment.objects.annotate(
  462. ... year=TruncYear('start_date')).values('year').annotate(
  463. ... experiments=Count('id'))
  464. >>> for exp in experiments_per_year:
  465. ... print(exp['year'], exp['experiments'])
  466. ...
  467. 2014-01-01 1
  468. 2015-01-01 2
  469. >>> import pytz
  470. >>> melb = pytz.timezone('Australia/Melbourne')
  471. >>> experiments_per_month = Experiment.objects.annotate(
  472. ... month=TruncMonth('start_time', tzinfo=melb)).values('month').annotate(
  473. ... experiments=Count('id'))
  474. >>> for exp in experiments_per_month:
  475. ... print(exp['month'], exp['experiments'])
  476. ...
  477. 2015-06-01 00:00:00+10:00 1
  478. 2016-01-01 00:00:00+11:00 1
  479. 2014-06-01 00:00:00+10:00 1
  480. ``DateTimeField`` truncation
  481. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  482. .. class:: TruncDate(expression, **extra)
  483. .. attribute:: lookup_name = 'date'
  484. .. attribute:: output_field = DateField()
  485. ``TruncDate`` casts ``expression`` to a date rather than using the built-in SQL
  486. truncate function. It's also registered as a transform on ``DateTimeField`` as
  487. ``__date``.
  488. .. class:: TruncDay(expression, output_field=None, tzinfo=None, **extra)
  489. .. attribute:: kind = 'day'
  490. .. class:: TruncHour(expression, output_field=None, tzinfo=None, **extra)
  491. .. attribute:: kind = 'hour'
  492. .. class:: TruncMinute(expression, output_field=None, tzinfo=None, **extra)
  493. .. attribute:: kind = 'minute'
  494. .. class:: TruncSecond(expression, output_field=None, tzinfo=None, **extra)
  495. .. attribute:: kind = 'second'
  496. These are logically equivalent to ``Trunc('datetime_field', kind)``. They
  497. truncate all parts of the date up to ``kind`` and allow grouping or filtering
  498. datetimes with less precision. ``expression`` must have an ``output_field`` of
  499. ``DateTimeField``.
  500. Usage example::
  501. >>> from datetime import date, datetime
  502. >>> from django.db.models import Count
  503. >>> from django.db.models.functions import (
  504. ... TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
  505. ... )
  506. >>> from django.utils import timezone
  507. >>> import pytz
  508. >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
  509. >>> Experiment.objects.create(start_time=start1, start_date=start1.date())
  510. >>> melb = pytz.timezone('Australia/Melbourne')
  511. >>> Experiment.objects.annotate(
  512. ... date=TruncDate('start_time'),
  513. ... day=TruncDay('start_time', tzinfo=melb),
  514. ... hour=TruncHour('start_time', tzinfo=melb),
  515. ... minute=TruncMinute('start_time'),
  516. ... second=TruncSecond('start_time'),
  517. ... ).values('date', 'day', 'hour', 'minute', 'second').get()
  518. {'date': datetime.date(2014, 6, 15),
  519. 'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
  520. 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
  521. 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>),
  522. 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>)
  523. }