1. import datetime
    
  2. from unittest import skipUnless
    
  3. 
    
  4. from django.core.exceptions import FieldError
    
  5. from django.db import connection
    
  6. from django.test import TestCase, override_settings
    
  7. 
    
  8. from .models import Article, Category, Comment
    
  9. 
    
  10. 
    
  11. class DatesTests(TestCase):
    
  12.     def test_related_model_traverse(self):
    
  13.         a1 = Article.objects.create(
    
  14.             title="First one",
    
  15.             pub_date=datetime.date(2005, 7, 28),
    
  16.         )
    
  17.         a2 = Article.objects.create(
    
  18.             title="Another one",
    
  19.             pub_date=datetime.date(2010, 7, 28),
    
  20.         )
    
  21.         a3 = Article.objects.create(
    
  22.             title="Third one, in the first day",
    
  23.             pub_date=datetime.date(2005, 7, 28),
    
  24.         )
    
  25. 
    
  26.         a1.comments.create(
    
  27.             text="Im the HULK!",
    
  28.             pub_date=datetime.date(2005, 7, 28),
    
  29.         )
    
  30.         a1.comments.create(
    
  31.             text="HULK SMASH!",
    
  32.             pub_date=datetime.date(2005, 7, 29),
    
  33.         )
    
  34.         a2.comments.create(
    
  35.             text="LMAO",
    
  36.             pub_date=datetime.date(2010, 7, 28),
    
  37.         )
    
  38.         a3.comments.create(
    
  39.             text="+1",
    
  40.             pub_date=datetime.date(2005, 8, 29),
    
  41.         )
    
  42. 
    
  43.         c = Category.objects.create(name="serious-news")
    
  44.         c.articles.add(a1, a3)
    
  45. 
    
  46.         self.assertSequenceEqual(
    
  47.             Comment.objects.dates("article__pub_date", "year"),
    
  48.             [
    
  49.                 datetime.date(2005, 1, 1),
    
  50.                 datetime.date(2010, 1, 1),
    
  51.             ],
    
  52.         )
    
  53.         self.assertSequenceEqual(
    
  54.             Comment.objects.dates("article__pub_date", "month"),
    
  55.             [
    
  56.                 datetime.date(2005, 7, 1),
    
  57.                 datetime.date(2010, 7, 1),
    
  58.             ],
    
  59.         )
    
  60.         self.assertSequenceEqual(
    
  61.             Comment.objects.dates("article__pub_date", "week"),
    
  62.             [
    
  63.                 datetime.date(2005, 7, 25),
    
  64.                 datetime.date(2010, 7, 26),
    
  65.             ],
    
  66.         )
    
  67.         self.assertSequenceEqual(
    
  68.             Comment.objects.dates("article__pub_date", "day"),
    
  69.             [
    
  70.                 datetime.date(2005, 7, 28),
    
  71.                 datetime.date(2010, 7, 28),
    
  72.             ],
    
  73.         )
    
  74.         self.assertSequenceEqual(
    
  75.             Article.objects.dates("comments__pub_date", "day"),
    
  76.             [
    
  77.                 datetime.date(2005, 7, 28),
    
  78.                 datetime.date(2005, 7, 29),
    
  79.                 datetime.date(2005, 8, 29),
    
  80.                 datetime.date(2010, 7, 28),
    
  81.             ],
    
  82.         )
    
  83.         self.assertQuerysetEqual(
    
  84.             Article.objects.dates("comments__approval_date", "day"), []
    
  85.         )
    
  86.         self.assertSequenceEqual(
    
  87.             Category.objects.dates("articles__pub_date", "day"),
    
  88.             [
    
  89.                 datetime.date(2005, 7, 28),
    
  90.             ],
    
  91.         )
    
  92. 
    
  93.     def test_dates_fails_when_no_arguments_are_provided(self):
    
  94.         with self.assertRaises(TypeError):
    
  95.             Article.objects.dates()
    
  96. 
    
  97.     def test_dates_fails_when_given_invalid_field_argument(self):
    
  98.         with self.assertRaisesMessage(
    
  99.             FieldError,
    
  100.             "Cannot resolve keyword 'invalid_field' into field. Choices are: "
    
  101.             "categories, comments, id, pub_date, pub_datetime, title",
    
  102.         ):
    
  103.             Article.objects.dates("invalid_field", "year")
    
  104. 
    
  105.     def test_dates_fails_when_given_invalid_kind_argument(self):
    
  106.         msg = "'kind' must be one of 'year', 'month', 'week', or 'day'."
    
  107.         with self.assertRaisesMessage(ValueError, msg):
    
  108.             Article.objects.dates("pub_date", "bad_kind")
    
  109. 
    
  110.     def test_dates_fails_when_given_invalid_order_argument(self):
    
  111.         msg = "'order' must be either 'ASC' or 'DESC'."
    
  112.         with self.assertRaisesMessage(ValueError, msg):
    
  113.             Article.objects.dates("pub_date", "year", order="bad order")
    
  114. 
    
  115.     @override_settings(USE_TZ=False)
    
  116.     def test_dates_trunc_datetime_fields(self):
    
  117.         Article.objects.bulk_create(
    
  118.             Article(pub_date=pub_datetime.date(), pub_datetime=pub_datetime)
    
  119.             for pub_datetime in [
    
  120.                 datetime.datetime(2015, 10, 21, 18, 1),
    
  121.                 datetime.datetime(2015, 10, 21, 18, 2),
    
  122.                 datetime.datetime(2015, 10, 22, 18, 1),
    
  123.                 datetime.datetime(2015, 10, 22, 18, 2),
    
  124.             ]
    
  125.         )
    
  126.         self.assertSequenceEqual(
    
  127.             Article.objects.dates("pub_datetime", "day", order="ASC"),
    
  128.             [
    
  129.                 datetime.date(2015, 10, 21),
    
  130.                 datetime.date(2015, 10, 22),
    
  131.             ],
    
  132.         )
    
  133. 
    
  134.     @skipUnless(connection.vendor == "mysql", "Test checks MySQL query syntax")
    
  135.     def test_dates_avoid_datetime_cast(self):
    
  136.         Article.objects.create(pub_date=datetime.date(2015, 10, 21))
    
  137.         for kind in ["day", "month", "year"]:
    
  138.             qs = Article.objects.dates("pub_date", kind)
    
  139.             if kind == "day":
    
  140.                 self.assertIn("DATE(", str(qs.query))
    
  141.             else:
    
  142.                 self.assertIn(" AS DATE)", str(qs.query))