1. import datetime
    
  2. 
    
  3. from django.test import TestCase
    
  4. from django.test.utils import requires_tz_support
    
  5. from django.utils import timezone, translation
    
  6. from django.utils.timesince import timesince, timeuntil
    
  7. from django.utils.translation import npgettext_lazy
    
  8. 
    
  9. 
    
  10. class TimesinceTests(TestCase):
    
  11.     def setUp(self):
    
  12.         self.t = datetime.datetime(2007, 8, 14, 13, 46, 0)
    
  13.         self.onemicrosecond = datetime.timedelta(microseconds=1)
    
  14.         self.onesecond = datetime.timedelta(seconds=1)
    
  15.         self.oneminute = datetime.timedelta(minutes=1)
    
  16.         self.onehour = datetime.timedelta(hours=1)
    
  17.         self.oneday = datetime.timedelta(days=1)
    
  18.         self.oneweek = datetime.timedelta(days=7)
    
  19.         self.onemonth = datetime.timedelta(days=30)
    
  20.         self.oneyear = datetime.timedelta(days=365)
    
  21. 
    
  22.     def test_equal_datetimes(self):
    
  23.         """equal datetimes."""
    
  24.         # NOTE: \xa0 avoids wrapping between value and unit
    
  25.         self.assertEqual(timesince(self.t, self.t), "0\xa0minutes")
    
  26. 
    
  27.     def test_ignore_microseconds_and_seconds(self):
    
  28.         """Microseconds and seconds are ignored."""
    
  29.         self.assertEqual(
    
  30.             timesince(self.t, self.t + self.onemicrosecond), "0\xa0minutes"
    
  31.         )
    
  32.         self.assertEqual(timesince(self.t, self.t + self.onesecond), "0\xa0minutes")
    
  33. 
    
  34.     def test_other_units(self):
    
  35.         """Test other units."""
    
  36.         self.assertEqual(timesince(self.t, self.t + self.oneminute), "1\xa0minute")
    
  37.         self.assertEqual(timesince(self.t, self.t + self.onehour), "1\xa0hour")
    
  38.         self.assertEqual(timesince(self.t, self.t + self.oneday), "1\xa0day")
    
  39.         self.assertEqual(timesince(self.t, self.t + self.oneweek), "1\xa0week")
    
  40.         self.assertEqual(timesince(self.t, self.t + self.onemonth), "1\xa0month")
    
  41.         self.assertEqual(timesince(self.t, self.t + self.oneyear), "1\xa0year")
    
  42. 
    
  43.     def test_multiple_units(self):
    
  44.         """Test multiple units."""
    
  45.         self.assertEqual(
    
  46.             timesince(self.t, self.t + 2 * self.oneday + 6 * self.onehour),
    
  47.             "2\xa0days, 6\xa0hours",
    
  48.         )
    
  49.         self.assertEqual(
    
  50.             timesince(self.t, self.t + 2 * self.oneweek + 2 * self.oneday),
    
  51.             "2\xa0weeks, 2\xa0days",
    
  52.         )
    
  53. 
    
  54.     def test_display_first_unit(self):
    
  55.         """
    
  56.         If the two differing units aren't adjacent, only the first unit is
    
  57.         displayed.
    
  58.         """
    
  59.         self.assertEqual(
    
  60.             timesince(
    
  61.                 self.t,
    
  62.                 self.t + 2 * self.oneweek + 3 * self.onehour + 4 * self.oneminute,
    
  63.             ),
    
  64.             "2\xa0weeks",
    
  65.         )
    
  66.         self.assertEqual(
    
  67.             timesince(self.t, self.t + 4 * self.oneday + 5 * self.oneminute),
    
  68.             "4\xa0days",
    
  69.         )
    
  70. 
    
  71.     def test_display_second_before_first(self):
    
  72.         """
    
  73.         When the second date occurs before the first, we should always
    
  74.         get 0 minutes.
    
  75.         """
    
  76.         self.assertEqual(
    
  77.             timesince(self.t, self.t - self.onemicrosecond), "0\xa0minutes"
    
  78.         )
    
  79.         self.assertEqual(timesince(self.t, self.t - self.onesecond), "0\xa0minutes")
    
  80.         self.assertEqual(timesince(self.t, self.t - self.oneminute), "0\xa0minutes")
    
  81.         self.assertEqual(timesince(self.t, self.t - self.onehour), "0\xa0minutes")
    
  82.         self.assertEqual(timesince(self.t, self.t - self.oneday), "0\xa0minutes")
    
  83.         self.assertEqual(timesince(self.t, self.t - self.oneweek), "0\xa0minutes")
    
  84.         self.assertEqual(timesince(self.t, self.t - self.onemonth), "0\xa0minutes")
    
  85.         self.assertEqual(timesince(self.t, self.t - self.oneyear), "0\xa0minutes")
    
  86.         self.assertEqual(
    
  87.             timesince(self.t, self.t - 2 * self.oneday - 6 * self.onehour),
    
  88.             "0\xa0minutes",
    
  89.         )
    
  90.         self.assertEqual(
    
  91.             timesince(self.t, self.t - 2 * self.oneweek - 2 * self.oneday),
    
  92.             "0\xa0minutes",
    
  93.         )
    
  94.         self.assertEqual(
    
  95.             timesince(
    
  96.                 self.t,
    
  97.                 self.t - 2 * self.oneweek - 3 * self.onehour - 4 * self.oneminute,
    
  98.             ),
    
  99.             "0\xa0minutes",
    
  100.         )
    
  101.         self.assertEqual(
    
  102.             timesince(self.t, self.t - 4 * self.oneday - 5 * self.oneminute),
    
  103.             "0\xa0minutes",
    
  104.         )
    
  105. 
    
  106.     def test_second_before_equal_first_humanize_time_strings(self):
    
  107.         time_strings = {
    
  108.             "minute": npgettext_lazy(
    
  109.                 "naturaltime-future",
    
  110.                 "%(num)d minute",
    
  111.                 "%(num)d minutes",
    
  112.                 "num",
    
  113.             ),
    
  114.         }
    
  115.         with translation.override("cs"):
    
  116.             for now in [self.t, self.t - self.onemicrosecond, self.t - self.oneday]:
    
  117.                 with self.subTest(now):
    
  118.                     self.assertEqual(
    
  119.                         timesince(self.t, now, time_strings=time_strings),
    
  120.                         "0\xa0minut",
    
  121.                     )
    
  122. 
    
  123.     @requires_tz_support
    
  124.     def test_different_timezones(self):
    
  125.         """When using two different timezones."""
    
  126.         now = datetime.datetime.now()
    
  127.         now_tz = timezone.make_aware(now, timezone.get_default_timezone())
    
  128.         now_tz_i = timezone.localtime(now_tz, timezone.get_fixed_timezone(195))
    
  129. 
    
  130.         self.assertEqual(timesince(now), "0\xa0minutes")
    
  131.         self.assertEqual(timesince(now_tz), "0\xa0minutes")
    
  132.         self.assertEqual(timesince(now_tz_i), "0\xa0minutes")
    
  133.         self.assertEqual(timesince(now_tz, now_tz_i), "0\xa0minutes")
    
  134.         self.assertEqual(timeuntil(now), "0\xa0minutes")
    
  135.         self.assertEqual(timeuntil(now_tz), "0\xa0minutes")
    
  136.         self.assertEqual(timeuntil(now_tz_i), "0\xa0minutes")
    
  137.         self.assertEqual(timeuntil(now_tz, now_tz_i), "0\xa0minutes")
    
  138. 
    
  139.     def test_date_objects(self):
    
  140.         """Both timesince and timeuntil should work on date objects (#17937)."""
    
  141.         today = datetime.date.today()
    
  142.         self.assertEqual(timesince(today + self.oneday), "0\xa0minutes")
    
  143.         self.assertEqual(timeuntil(today - self.oneday), "0\xa0minutes")
    
  144. 
    
  145.     def test_both_date_objects(self):
    
  146.         """Timesince should work with both date objects (#9672)"""
    
  147.         today = datetime.date.today()
    
  148.         self.assertEqual(timeuntil(today + self.oneday, today), "1\xa0day")
    
  149.         self.assertEqual(timeuntil(today - self.oneday, today), "0\xa0minutes")
    
  150.         self.assertEqual(timeuntil(today + self.oneweek, today), "1\xa0week")
    
  151. 
    
  152.     def test_leap_year(self):
    
  153.         start_date = datetime.date(2016, 12, 25)
    
  154.         self.assertEqual(timeuntil(start_date + self.oneweek, start_date), "1\xa0week")
    
  155.         self.assertEqual(timesince(start_date, start_date + self.oneweek), "1\xa0week")
    
  156. 
    
  157.     def test_leap_year_new_years_eve(self):
    
  158.         t = datetime.date(2016, 12, 31)
    
  159.         now = datetime.datetime(2016, 12, 31, 18, 0, 0)
    
  160.         self.assertEqual(timesince(t + self.oneday, now), "0\xa0minutes")
    
  161.         self.assertEqual(timeuntil(t - self.oneday, now), "0\xa0minutes")
    
  162. 
    
  163.     def test_naive_datetime_with_tzinfo_attribute(self):
    
  164.         class naive(datetime.tzinfo):
    
  165.             def utcoffset(self, dt):
    
  166.                 return None
    
  167. 
    
  168.         future = datetime.datetime(2080, 1, 1, tzinfo=naive())
    
  169.         self.assertEqual(timesince(future), "0\xa0minutes")
    
  170.         past = datetime.datetime(1980, 1, 1, tzinfo=naive())
    
  171.         self.assertEqual(timeuntil(past), "0\xa0minutes")
    
  172. 
    
  173.     def test_thousand_years_ago(self):
    
  174.         t = datetime.datetime(1007, 8, 14, 13, 46, 0)
    
  175.         self.assertEqual(timesince(t, self.t), "1000\xa0years")
    
  176.         self.assertEqual(timeuntil(self.t, t), "1000\xa0years")
    
  177. 
    
  178.     def test_depth(self):
    
  179.         t = (
    
  180.             self.t
    
  181.             + self.oneyear
    
  182.             + self.onemonth
    
  183.             + self.oneweek
    
  184.             + self.oneday
    
  185.             + self.onehour
    
  186.         )
    
  187.         tests = [
    
  188.             (t, 1, "1\xa0year"),
    
  189.             (t, 2, "1\xa0year, 1\xa0month"),
    
  190.             (t, 3, "1\xa0year, 1\xa0month, 1\xa0week"),
    
  191.             (t, 4, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day"),
    
  192.             (t, 5, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour"),
    
  193.             (t, 6, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour"),
    
  194.             (self.t + self.onehour, 5, "1\xa0hour"),
    
  195.             (self.t + (4 * self.oneminute), 3, "4\xa0minutes"),
    
  196.             (self.t + self.onehour + self.oneminute, 1, "1\xa0hour"),
    
  197.             (self.t + self.oneday + self.onehour, 1, "1\xa0day"),
    
  198.             (self.t + self.oneweek + self.oneday, 1, "1\xa0week"),
    
  199.             (self.t + self.onemonth + self.oneweek, 1, "1\xa0month"),
    
  200.             (self.t + self.oneyear + self.onemonth, 1, "1\xa0year"),
    
  201.             (self.t + self.oneyear + self.oneweek + self.oneday, 3, "1\xa0year"),
    
  202.         ]
    
  203.         for value, depth, expected in tests:
    
  204.             with self.subTest():
    
  205.                 self.assertEqual(timesince(self.t, value, depth=depth), expected)
    
  206.                 self.assertEqual(timeuntil(value, self.t, depth=depth), expected)
    
  207. 
    
  208.     def test_depth_invalid(self):
    
  209.         msg = "depth must be greater than 0."
    
  210.         with self.assertRaisesMessage(ValueError, msg):
    
  211.             timesince(self.t, self.t, depth=0)