mirror of https://github.com/django/django.git
Fixed #18504 -- Computed |naturalday in local time.
This commit is contained in:
parent
123362dd37
commit
5d560dcb98
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import re
|
import re
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -143,7 +143,9 @@ def apnumber(value):
|
||||||
return value
|
return value
|
||||||
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
||||||
|
|
||||||
@register.filter
|
# Perform the comparison in the default time zone when USE_TZ = True
|
||||||
|
# (unless a specific time zone has been applied with the |timezone filter).
|
||||||
|
@register.filter(expects_localtime=True)
|
||||||
def naturalday(value, arg=None):
|
def naturalday(value, arg=None):
|
||||||
"""
|
"""
|
||||||
For date values that are tomorrow, today or yesterday compared to
|
For date values that are tomorrow, today or yesterday compared to
|
||||||
|
@ -169,6 +171,8 @@ def naturalday(value, arg=None):
|
||||||
return _('yesterday')
|
return _('yesterday')
|
||||||
return defaultfilters.date(value, arg)
|
return defaultfilters.date(value, arg)
|
||||||
|
|
||||||
|
# This filter doesn't require expects_localtime=True because it deals properly
|
||||||
|
# with both naive and aware datetimes. Therefore avoid the cost of conversion.
|
||||||
@register.filter
|
@register.filter
|
||||||
def naturaltime(value):
|
def naturaltime(value):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,13 +1,31 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import datetime
|
import datetime
|
||||||
import new
|
|
||||||
|
|
||||||
|
from django.contrib.humanize.templatetags import humanize
|
||||||
from django.template import Template, Context, defaultfilters
|
from django.template import Template, Context, defaultfilters
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import translation, tzinfo
|
from django.test.utils import override_settings
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.timezone import utc
|
from django.utils.timezone import utc
|
||||||
|
from django.utils import translation
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.utils import tzinfo
|
||||||
|
|
||||||
|
|
||||||
|
# Mock out datetime in some tests so they don't fail occasionally when they
|
||||||
|
# run too slow. Use a fixed datetime for datetime.now(). DST change in
|
||||||
|
# America/Chicago (the default time zone) happened on March 11th in 2012.
|
||||||
|
|
||||||
|
now = datetime.datetime(2012, 3, 9, 22, 30)
|
||||||
|
|
||||||
|
class MockDateTime(datetime.datetime):
|
||||||
|
@classmethod
|
||||||
|
def now(self, tz=None):
|
||||||
|
if tz is None or tz.utcoffset(now) is None:
|
||||||
|
return now
|
||||||
|
else:
|
||||||
|
# equals now.replace(tzinfo=utc)
|
||||||
|
return now.replace(tzinfo=tz) + tz.utcoffset(now)
|
||||||
|
|
||||||
|
|
||||||
class HumanizeTests(TestCase):
|
class HumanizeTests(TestCase):
|
||||||
|
@ -109,28 +127,36 @@ class HumanizeTests(TestCase):
|
||||||
self.humanize_tester(test_list, result_list, 'naturalday')
|
self.humanize_tester(test_list, result_list, 'naturalday')
|
||||||
|
|
||||||
def test_naturalday_tz(self):
|
def test_naturalday_tz(self):
|
||||||
from django.contrib.humanize.templatetags.humanize import naturalday
|
|
||||||
|
|
||||||
today = datetime.date.today()
|
today = datetime.date.today()
|
||||||
tz_one = tzinfo.FixedOffset(datetime.timedelta(hours=-12))
|
tz_one = tzinfo.FixedOffset(datetime.timedelta(hours=-12))
|
||||||
tz_two = tzinfo.FixedOffset(datetime.timedelta(hours=12))
|
tz_two = tzinfo.FixedOffset(datetime.timedelta(hours=12))
|
||||||
|
|
||||||
# Can be today or yesterday
|
# Can be today or yesterday
|
||||||
date_one = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_one)
|
date_one = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_one)
|
||||||
naturalday_one = naturalday(date_one)
|
naturalday_one = humanize.naturalday(date_one)
|
||||||
# Can be today or tomorrow
|
# Can be today or tomorrow
|
||||||
date_two = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_two)
|
date_two = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_two)
|
||||||
naturalday_two = naturalday(date_two)
|
naturalday_two = humanize.naturalday(date_two)
|
||||||
|
|
||||||
# As 24h of difference they will never be the same
|
# As 24h of difference they will never be the same
|
||||||
self.assertNotEqual(naturalday_one, naturalday_two)
|
self.assertNotEqual(naturalday_one, naturalday_two)
|
||||||
|
|
||||||
|
def test_naturalday_uses_localtime(self):
|
||||||
|
# Regression for #18504
|
||||||
|
# This is 2012-03-08HT19:30:00-06:00 in Ameria/Chicago
|
||||||
|
dt = datetime.datetime(2012, 3, 9, 1, 30, tzinfo=utc)
|
||||||
|
|
||||||
|
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
|
||||||
|
try:
|
||||||
|
with override_settings(USE_TZ=True):
|
||||||
|
self.humanize_tester([dt], ['yesterday'], 'naturalday')
|
||||||
|
finally:
|
||||||
|
humanize.datetime = orig_humanize_datetime
|
||||||
|
|
||||||
def test_naturaltime(self):
|
def test_naturaltime(self):
|
||||||
class naive(datetime.tzinfo):
|
class naive(datetime.tzinfo):
|
||||||
def utcoffset(self, dt):
|
def utcoffset(self, dt):
|
||||||
return None
|
return None
|
||||||
# we're going to mock datetime.datetime, so use a fixed datetime
|
|
||||||
now = datetime.datetime(2011, 8, 15, 1, 23)
|
|
||||||
test_list = [
|
test_list = [
|
||||||
now,
|
now,
|
||||||
now - datetime.timedelta(seconds=1),
|
now - datetime.timedelta(seconds=1),
|
||||||
|
@ -148,6 +174,7 @@ class HumanizeTests(TestCase):
|
||||||
now + datetime.timedelta(hours=1, minutes=30, seconds=30),
|
now + datetime.timedelta(hours=1, minutes=30, seconds=30),
|
||||||
now + datetime.timedelta(hours=23, minutes=50, seconds=50),
|
now + datetime.timedelta(hours=23, minutes=50, seconds=50),
|
||||||
now + datetime.timedelta(days=1),
|
now + datetime.timedelta(days=1),
|
||||||
|
now + datetime.timedelta(days=2, hours=6),
|
||||||
now + datetime.timedelta(days=500),
|
now + datetime.timedelta(days=500),
|
||||||
now.replace(tzinfo=naive()),
|
now.replace(tzinfo=naive()),
|
||||||
now.replace(tzinfo=utc),
|
now.replace(tzinfo=utc),
|
||||||
|
@ -169,27 +196,22 @@ class HumanizeTests(TestCase):
|
||||||
'an hour from now',
|
'an hour from now',
|
||||||
'23 hours from now',
|
'23 hours from now',
|
||||||
'1 day from now',
|
'1 day from now',
|
||||||
|
'2 days, 6 hours from now',
|
||||||
'1 year, 4 months from now',
|
'1 year, 4 months from now',
|
||||||
'now',
|
'now',
|
||||||
'now',
|
'now',
|
||||||
]
|
]
|
||||||
|
# Because of the DST change, 2 days and 6 hours after the chosen
|
||||||
|
# date in naive arithmetic is only 2 days and 5 hours after in
|
||||||
|
# aware arithmetic.
|
||||||
|
result_list_with_tz_support = result_list[:]
|
||||||
|
assert result_list_with_tz_support[-4] == '2 days, 6 hours from now'
|
||||||
|
result_list_with_tz_support[-4] == '2 days, 5 hours from now'
|
||||||
|
|
||||||
# mock out datetime so these tests don't fail occasionally when the
|
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
|
||||||
# test runs too slow
|
|
||||||
class MockDateTime(datetime.datetime):
|
|
||||||
@classmethod
|
|
||||||
def now(self, tz=None):
|
|
||||||
if tz is None or tz.utcoffset(now) is None:
|
|
||||||
return now
|
|
||||||
else:
|
|
||||||
# equals now.replace(tzinfo=utc)
|
|
||||||
return now.replace(tzinfo=tz) + tz.utcoffset(now)
|
|
||||||
|
|
||||||
from django.contrib.humanize.templatetags import humanize
|
|
||||||
orig_humanize_datetime = humanize.datetime
|
|
||||||
humanize.datetime = MockDateTime
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.humanize_tester(test_list, result_list, 'naturaltime')
|
self.humanize_tester(test_list, result_list, 'naturaltime')
|
||||||
|
with override_settings(USE_TZ=True):
|
||||||
|
self.humanize_tester(test_list, result_list_with_tz_support, 'naturaltime')
|
||||||
finally:
|
finally:
|
||||||
humanize.datetime = orig_humanize_datetime
|
humanize.datetime = orig_humanize_datetime
|
||||||
|
|
Loading…
Reference in New Issue