#34483: Negative result of django.utils.timesince.timesince
-------------------------------------+-------------------------------------
Reporter: Lorenzo Peña | Owner: Natalia
| Bidart
Type: Bug | Status: assigned
Component: Utilities | Version: 4.2
Severity: Release blocker | Resolution:
Keywords: timesince | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Mariusz Felisiak):
It seems that `now` must be in the same time zone (as you suggested at the
beginning), however we also have to change time zone when `now` is passed,
e.g.
{{{#!diff
diff --git a/django/utils/timesince.py b/django/utils/timesince.py
index 94ba24d48a..9b9dd45af9 100644
--- a/django/utils/timesince.py
+++ b/django/utils/timesince.py
@@ -63,7 +63,10 @@ def timesince(d, now=None, reversed=False,
time_strings=None, depth=2):
if now and not isinstance(now, datetime.datetime):
now = datetime.datetime(now.year, now.month, now.day)
- now = now or datetime.datetime.now(datetime.timezone.utc if
is_aware(d) else None)
+ if is_aware(d):
+ now = now.astimezone(d.tzinfo) if now else
datetime.datetime.now(tz=d.tzinfo)
+ else:
+ now = now or datetime.datetime.now()
if reversed:
d, now = now, d
@@ -77,8 +80,7 @@ def timesince(d, now=None, reversed=False,
time_strings=None, depth=2):
# Get years and months.
total_months = (now.year - d.year) * 12 + (now.month - d.month)
- time_delta = delta - datetime.timedelta(days=delta.days)
- if d.day > now.day or (d.day == now.day and
time_delta.total_seconds() < 0):
+ if d.day > now.day or (d.day == now.day and d.time() > now.time()):
total_months -= 1
years, months = divmod(total_months, 12)
}}}
see a regression test:
{{{#!diff
diff --git a/tests/utils_tests/test_timesince.py
b/tests/utils_tests/test_timesince.py
index d54fce2be6..e023e95148 100644
--- a/tests/utils_tests/test_timesince.py
+++ b/tests/utils_tests/test_timesince.py
@@ -258,6 +258,24 @@ class TimesinceTests(TestCase):
with self.subTest(value):
self.assertEqual(timesince(value), expected)
+ @requires_tz_support
+ def test_less_than_a_day_cross_day_with_zoneinfo(self):
+ now_with_zoneinfo = timezone.make_aware(
+ datetime.datetime(2023, 4, 14, 1, 30, 30),
+ zoneinfo.ZoneInfo(key="Asia/Kathmandu") # UTC+05:45
+ )
+ now_utc = now_with_zoneinfo.astimezone(datetime.timezone.utc)
+ tests = [
+ (now_with_zoneinfo, "0\xa0minutes"),
+ (now_with_zoneinfo - self.onemicrosecond, "0\xa0minutes"),
+ (now_with_zoneinfo - self.onesecond, "0\xa0minutes"),
+ (now_with_zoneinfo - self.oneminute, "1\xa0minute"),
+ (now_with_zoneinfo - self.onehour, "1\xa0hour"),
+ ]
+ for value, expected in tests:
+ with self.subTest(value):
+ self.assertEqual(timesince(value, now_utc), expected)
+
@requires_tz_support
@override_settings(USE_TZ=True)
}}}
What do you think?
--
Ticket URL: <https://code.djangoproject.com/ticket/34483#comment:12>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/010701877e6011b3-690bf969-fce2-46d5-887b-6ceba92beef6-000000%40eu-central-1.amazonses.com.