Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #20246 -- Added non-breaking spaces between values an units

  • Loading branch information...
commit 7d77e9786a118dd95a268872dd9d36664066b96a 1 parent caf56ad
Emil Stenström EmilStenstrom authored claudep committed
1  AUTHORS
View
@@ -536,6 +536,7 @@ answer newbie questions, and generally made Django that much better:
starrynight <cmorgh@gmail.com>
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/>
+ Emil Stenström <em@kth.se>
Johan C. Stöver <johan@nilling.nl>
Nowell Strite <http://nowell.strite.org/>
Thomas Stromberg <tstromberg@google.com>
18 django/contrib/humanize/templatetags/humanize.py
View
@@ -194,17 +194,20 @@ def naturaltime(value):
return _('now')
elif delta.seconds < 60:
return ungettext(
- 'a second ago', '%(count)s seconds ago', delta.seconds
+ # Translators: \\u00a0 is non-breaking space
+ 'a second ago', '%(count)s\u00a0seconds ago', delta.seconds
) % {'count': delta.seconds}
elif delta.seconds // 60 < 60:
count = delta.seconds // 60
return ungettext(
- 'a minute ago', '%(count)s minutes ago', count
+ # Translators: \\u00a0 is non-breaking space
+ 'a minute ago', '%(count)s\u00a0minutes ago', count
) % {'count': count}
else:
count = delta.seconds // 60 // 60
return ungettext(
- 'an hour ago', '%(count)s hours ago', count
+ # Translators: \\u00a0 is non-breaking space
+ 'an hour ago', '%(count)s\u00a0hours ago', count
) % {'count': count}
else:
delta = value - now
@@ -216,15 +219,18 @@ def naturaltime(value):
return _('now')
elif delta.seconds < 60:
return ungettext(
- 'a second from now', '%(count)s seconds from now', delta.seconds
+ # Translators: \\u00a0 is non-breaking space
+ 'a second from now', '%(count)s\u00a0seconds from now', delta.seconds
) % {'count': delta.seconds}
elif delta.seconds // 60 < 60:
count = delta.seconds // 60
return ungettext(
- 'a minute from now', '%(count)s minutes from now', count
+ # Translators: \\u00a0 is non-breaking space
+ 'a minute from now', '%(count)s\u00a0minutes from now', count
) % {'count': count}
else:
count = delta.seconds // 60 // 60
return ungettext(
- 'an hour from now', '%(count)s hours from now', count
+ # Translators: \\u00a0 is non-breaking space
+ 'an hour from now', '%(count)s\u00a0hours from now', count
) % {'count': count}
26 django/contrib/humanize/tests.py
View
@@ -195,22 +195,22 @@ def utcoffset(self, dt):
result_list = [
'now',
'a second ago',
- '30 seconds ago',
+ '30\xa0seconds ago',
'a minute ago',
- '2 minutes ago',
+ '2\xa0minutes ago',
'an hour ago',
- '23 hours ago',
- '1 day ago',
- '1 year, 4 months ago',
+ '23\xa0hours ago',
+ '1\xa0day ago',
+ '1\xa0year, 4\xa0months ago',
'a second from now',
- '30 seconds from now',
+ '30\xa0seconds from now',
'a minute from now',
- '2 minutes from now',
+ '2\xa0minutes from now',
'an hour from now',
- '23 hours from now',
- '1 day from now',
- '2 days, 6 hours from now',
- '1 year, 4 months from now',
+ '23\xa0hours from now',
+ '1\xa0day from now',
+ '2\xa0days, 6\xa0hours from now',
+ '1\xa0year, 4\xa0months from now',
'now',
'now',
]
@@ -218,8 +218,8 @@ def utcoffset(self, dt):
# 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'
+ assert result_list_with_tz_support[-4] == '2\xa0days, 6\xa0hours from now'
+ result_list_with_tz_support[-4] == '2\xa0days, 5\xa0hours from now'
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
try:
28 django/template/defaultfilters.py
View
@@ -14,7 +14,7 @@
from django.utils.dateformat import format, time_format
from django.utils.encoding import force_text, iri_to_uri
from django.utils.html import (conditional_escape, escapejs, fix_ampersands,
- escape, urlize as urlize_impl, linebreaks, strip_tags)
+ escape, urlize as urlize_impl, linebreaks, strip_tags, avoid_wrapping)
from django.utils.http import urlquote
from django.utils.text import Truncator, wrap, phone2numeric
from django.utils.safestring import mark_safe, SafeData, mark_for_escaping
@@ -810,7 +810,8 @@ def filesizeformat(bytes):
try:
bytes = float(bytes)
except (TypeError,ValueError,UnicodeDecodeError):
- return ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0}
+ value = ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0}
+ return avoid_wrapping(value)
filesize_number_format = lambda value: formats.number_format(round(value, 1), 1)
@@ -821,16 +822,19 @@ def filesizeformat(bytes):
PB = 1<<50
if bytes < KB:
- return ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes}
- if bytes < MB:
- return ugettext("%s KB") % filesize_number_format(bytes / KB)
- if bytes < GB:
- return ugettext("%s MB") % filesize_number_format(bytes / MB)
- if bytes < TB:
- return ugettext("%s GB") % filesize_number_format(bytes / GB)
- if bytes < PB:
- return ugettext("%s TB") % filesize_number_format(bytes / TB)
- return ugettext("%s PB") % filesize_number_format(bytes / PB)
+ value = ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes}
+ elif bytes < MB:
+ value = ugettext("%s KB") % filesize_number_format(bytes / KB)
+ elif bytes < GB:
+ value = ugettext("%s MB") % filesize_number_format(bytes / MB)
+ elif bytes < TB:
+ value = ugettext("%s GB") % filesize_number_format(bytes / GB)
+ elif bytes < PB:
+ value = ugettext("%s TB") % filesize_number_format(bytes / TB)
+ else:
+ value = ugettext("%s PB") % filesize_number_format(bytes / PB)
+
+ return avoid_wrapping(value)
@register.filter(is_safe=False)
def pluralize(value, arg='s'):
7 django/utils/html.py
View
@@ -281,3 +281,10 @@ def replace_p_tags(match):
text = trailing_empty_content_re.sub('', text)
return text
clean_html = allow_lazy(clean_html, six.text_type)
+
+def avoid_wrapping(value):
+ """
+ Avoid text wrapping in the middle of a phrase by adding non-breaking
+ spaces where there previously were normal spaces.
+ """
+ return value.replace(" ", "\xa0")
7 django/utils/timesince.py
View
@@ -2,6 +2,7 @@
import datetime
+from django.utils.html import avoid_wrapping
from django.utils.timezone import is_aware, utc
from django.utils.translation import ugettext, ungettext_lazy
@@ -40,18 +41,18 @@ def timesince(d, now=None, reversed=False):
since = delta.days * 24 * 60 * 60 + delta.seconds
if since <= 0:
# d is in the future compared to now, stop processing.
- return ugettext('0 minutes')
+ return avoid_wrapping(ugettext('0 minutes'))
for i, (seconds, name) in enumerate(chunks):
count = since // seconds
if count != 0:
break
- result = name % count
+ result = avoid_wrapping(name % count)
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]
count2 = (since - (seconds * count)) // seconds2
if count2 != 0:
- result += ugettext(', ') + name2 % count2
+ result += ugettext(', ') + avoid_wrapping(name2 % count2)
return result
def timeuntil(d, now=None):
68 tests/defaultfilters/tests.py
View
@@ -527,24 +527,26 @@ def test_time(self):
def test_timesince(self):
# real testing is done in timesince.py, where we can provide our own 'now'
+ # NOTE: \xa0 avoids wrapping between value and unit
self.assertEqual(
timesince_filter(datetime.datetime.now() - datetime.timedelta(1)),
- '1 day')
+ '1\xa0day')
self.assertEqual(
timesince_filter(datetime.datetime(2005, 12, 29),
datetime.datetime(2005, 12, 30)),
- '1 day')
+ '1\xa0day')
def test_timeuntil(self):
+ # NOTE: \xa0 avoids wrapping between value and unit
self.assertEqual(
timeuntil_filter(datetime.datetime.now() + datetime.timedelta(1, 1)),
- '1 day')
+ '1\xa0day')
self.assertEqual(
timeuntil_filter(datetime.datetime(2005, 12, 30),
datetime.datetime(2005, 12, 29)),
- '1 day')
+ '1\xa0day')
def test_default(self):
self.assertEqual(default("val", "default"), 'val')
@@ -574,43 +576,45 @@ def test_yesno(self):
'get out of town')
def test_filesizeformat(self):
- self.assertEqual(filesizeformat(1023), '1023 bytes')
- self.assertEqual(filesizeformat(1024), '1.0 KB')
- self.assertEqual(filesizeformat(10*1024), '10.0 KB')
- self.assertEqual(filesizeformat(1024*1024-1), '1024.0 KB')
- self.assertEqual(filesizeformat(1024*1024), '1.0 MB')
- self.assertEqual(filesizeformat(1024*1024*50), '50.0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024-1), '1024.0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024), '1.0 GB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024), '1.0 TB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024*1024), '1.0 PB')
+ # NOTE: \xa0 avoids wrapping between value and unit
+ self.assertEqual(filesizeformat(1023), '1023\xa0bytes')
+ self.assertEqual(filesizeformat(1024), '1.0\xa0KB')
+ self.assertEqual(filesizeformat(10*1024), '10.0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024-1), '1024.0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024), '1.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*50), '50.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024-1), '1024.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024), '1.0\xa0GB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024), '1.0\xa0TB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024*1024), '1.0\xa0PB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024*2000),
- '2000.0 PB')
- self.assertEqual(filesizeformat(complex(1,-1)), '0 bytes')
- self.assertEqual(filesizeformat(""), '0 bytes')
+ '2000.0\xa0PB')
+ self.assertEqual(filesizeformat(complex(1,-1)), '0\xa0bytes')
+ self.assertEqual(filesizeformat(""), '0\xa0bytes')
self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"),
- '0 bytes')
+ '0\xa0bytes')
def test_localized_filesizeformat(self):
+ # NOTE: \xa0 avoids wrapping between value and unit
with self.settings(USE_L10N=True):
with translation.override('de', deactivate=True):
- self.assertEqual(filesizeformat(1023), '1023 Bytes')
- self.assertEqual(filesizeformat(1024), '1,0 KB')
- self.assertEqual(filesizeformat(10*1024), '10,0 KB')
- self.assertEqual(filesizeformat(1024*1024-1), '1024,0 KB')
- self.assertEqual(filesizeformat(1024*1024), '1,0 MB')
- self.assertEqual(filesizeformat(1024*1024*50), '50,0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024-1), '1024,0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024), '1,0 GB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024), '1,0 TB')
+ self.assertEqual(filesizeformat(1023), '1023\xa0Bytes')
+ self.assertEqual(filesizeformat(1024), '1,0\xa0KB')
+ self.assertEqual(filesizeformat(10*1024), '10,0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024-1), '1024,0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024), '1,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*50), '50,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024-1), '1024,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024), '1,0\xa0GB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024), '1,0\xa0TB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024),
- '1,0 PB')
+ '1,0\xa0PB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024*2000),
- '2000,0 PB')
- self.assertEqual(filesizeformat(complex(1,-1)), '0 Bytes')
- self.assertEqual(filesizeformat(""), '0 Bytes')
+ '2000,0\xa0PB')
+ self.assertEqual(filesizeformat(complex(1,-1)), '0\xa0Bytes')
+ self.assertEqual(filesizeformat(""), '0\xa0Bytes')
self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"),
- '0 Bytes')
+ '0\xa0Bytes')
def test_pluralize(self):
self.assertEqual(pluralize(1), '')
59 tests/template_tests/filters.py
View
@@ -35,59 +35,60 @@ def get_filter_tests():
now_tz_i = datetime.now(FixedOffset((3 * 60) + 15)) # imaginary time zone
today = date.today()
+ # NOTE: \xa0 avoids wrapping between value and unit
return {
# Default compare with datetime.now()
- 'filter-timesince01' : ('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),
- 'filter-timesince02' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(days=1, minutes = 1)}, '1 day'),
- 'filter-timesince03' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds = 10)}, '1 hour, 25 minutes'),
+ 'filter-timesince01' : ('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1\xa0minute'),
+ 'filter-timesince02' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(days=1, minutes = 1)}, '1\xa0day'),
+ 'filter-timesince03' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds = 10)}, '1\xa0hour, 25\xa0minutes'),
# Compare to a given parameter
- 'filter-timesince04' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=1)}, '1 day'),
- 'filter-timesince05' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2, minutes=1), 'b':now - timedelta(days=2)}, '1 minute'),
+ 'filter-timesince04' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=1)}, '1\xa0day'),
+ 'filter-timesince05' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2, minutes=1), 'b':now - timedelta(days=2)}, '1\xa0minute'),
# Check that timezone is respected
- 'filter-timesince06' : ('{{ a|timesince:b }}', {'a':now_tz - timedelta(hours=8), 'b':now_tz}, '8 hours'),
+ 'filter-timesince06' : ('{{ a|timesince:b }}', {'a':now_tz - timedelta(hours=8), 'b':now_tz}, '8\xa0hours'),
# Regression for #7443
- 'filter-timesince07': ('{{ earlier|timesince }}', { 'earlier': now - timedelta(days=7) }, '1 week'),
- 'filter-timesince08': ('{{ earlier|timesince:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '1 week'),
- 'filter-timesince09': ('{{ later|timesince }}', { 'later': now + timedelta(days=7) }, '0 minutes'),
- 'filter-timesince10': ('{{ later|timesince:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '0 minutes'),
+ 'filter-timesince07': ('{{ earlier|timesince }}', { 'earlier': now - timedelta(days=7) }, '1\xa0week'),
+ 'filter-timesince08': ('{{ earlier|timesince:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '1\xa0week'),
+ 'filter-timesince09': ('{{ later|timesince }}', { 'later': now + timedelta(days=7) }, '0\xa0minutes'),
+ 'filter-timesince10': ('{{ later|timesince:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '0\xa0minutes'),
# Ensures that differing timezones are calculated correctly
- 'filter-timesince11' : ('{{ a|timesince }}', {'a': now}, '0 minutes'),
- 'filter-timesince12' : ('{{ a|timesince }}', {'a': now_tz}, '0 minutes'),
- 'filter-timesince13' : ('{{ a|timesince }}', {'a': now_tz_i}, '0 minutes'),
- 'filter-timesince14' : ('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0 minutes'),
+ 'filter-timesince11' : ('{{ a|timesince }}', {'a': now}, '0\xa0minutes'),
+ 'filter-timesince12' : ('{{ a|timesince }}', {'a': now_tz}, '0\xa0minutes'),
+ 'filter-timesince13' : ('{{ a|timesince }}', {'a': now_tz_i}, '0\xa0minutes'),
+ 'filter-timesince14' : ('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0\xa0minutes'),
'filter-timesince15' : ('{{ a|timesince:b }}', {'a': now, 'b': now_tz_i}, ''),
'filter-timesince16' : ('{{ a|timesince:b }}', {'a': now_tz_i, 'b': now}, ''),
# Regression for #9065 (two date objects).
- 'filter-timesince17' : ('{{ a|timesince:b }}', {'a': today, 'b': today}, '0 minutes'),
- 'filter-timesince18' : ('{{ a|timesince:b }}', {'a': today, 'b': today + timedelta(hours=24)}, '1 day'),
+ 'filter-timesince17' : ('{{ a|timesince:b }}', {'a': today, 'b': today}, '0\xa0minutes'),
+ 'filter-timesince18' : ('{{ a|timesince:b }}', {'a': today, 'b': today + timedelta(hours=24)}, '1\xa0day'),
# Default compare with datetime.now()
- 'filter-timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
- 'filter-timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),
- 'filter-timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'),
+ 'filter-timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2\xa0minutes'),
+ 'filter-timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1\xa0day'),
+ 'filter-timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8\xa0hours, 10\xa0minutes'),
# Compare to a given parameter
- 'filter-timeuntil04' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=1), 'b':now - timedelta(days=2)}, '1 day'),
- 'filter-timeuntil05' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=2, minutes=1)}, '1 minute'),
+ 'filter-timeuntil04' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=1), 'b':now - timedelta(days=2)}, '1\xa0day'),
+ 'filter-timeuntil05' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=2, minutes=1)}, '1\xa0minute'),
# Regression for #7443
- 'filter-timeuntil06': ('{{ earlier|timeuntil }}', { 'earlier': now - timedelta(days=7) }, '0 minutes'),
- 'filter-timeuntil07': ('{{ earlier|timeuntil:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '0 minutes'),
- 'filter-timeuntil08': ('{{ later|timeuntil }}', { 'later': now + timedelta(days=7, hours=1) }, '1 week'),
- 'filter-timeuntil09': ('{{ later|timeuntil:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '1 week'),
+ 'filter-timeuntil06': ('{{ earlier|timeuntil }}', { 'earlier': now - timedelta(days=7) }, '0\xa0minutes'),
+ 'filter-timeuntil07': ('{{ earlier|timeuntil:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '0\xa0minutes'),
+ 'filter-timeuntil08': ('{{ later|timeuntil }}', { 'later': now + timedelta(days=7, hours=1) }, '1\xa0week'),
+ 'filter-timeuntil09': ('{{ later|timeuntil:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '1\xa0week'),
# Ensures that differing timezones are calculated correctly
- 'filter-timeuntil10' : ('{{ a|timeuntil }}', {'a': now_tz_i}, '0 minutes'),
- 'filter-timeuntil11' : ('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0 minutes'),
+ 'filter-timeuntil10' : ('{{ a|timeuntil }}', {'a': now_tz_i}, '0\xa0minutes'),
+ 'filter-timeuntil11' : ('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0\xa0minutes'),
# Regression for #9065 (two date objects).
- 'filter-timeuntil12' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today}, '0 minutes'),
- 'filter-timeuntil13' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today - timedelta(hours=24)}, '1 day'),
+ 'filter-timeuntil12' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today}, '0\xa0minutes'),
+ 'filter-timeuntil13' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today - timedelta(hours=24)}, '1\xa0day'),
'filter-addslash01': ("{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}", {"a": "<a>'", "b": mark_safe("<a>'")}, r"<a>\' <a>\'"),
'filter-addslash02': ("{{ a|addslashes }} {{ b|addslashes }}", {"a": "<a>'", "b": mark_safe("<a>'")}, r"&lt;a&gt;\&#39; <a>\'"),
71 tests/utils_tests/test_timesince.py
View
@@ -21,32 +21,33 @@ def setUp(self):
def test_equal_datetimes(self):
""" equal datetimes. """
- self.assertEqual(timesince(self.t, self.t), '0 minutes')
+ # NOTE: \xa0 avoids wrapping between value and unit
+ self.assertEqual(timesince(self.t, self.t), '0\xa0minutes')
def test_ignore_microseconds_and_seconds(self):
""" Microseconds and seconds are ignored. """
self.assertEqual(timesince(self.t, self.t+self.onemicrosecond),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t+self.onesecond),
- '0 minutes')
+ '0\xa0minutes')
def test_other_units(self):
""" Test other units. """
self.assertEqual(timesince(self.t, self.t+self.oneminute),
- '1 minute')
- self.assertEqual(timesince(self.t, self.t+self.onehour), '1 hour')
- self.assertEqual(timesince(self.t, self.t+self.oneday), '1 day')
- self.assertEqual(timesince(self.t, self.t+self.oneweek), '1 week')
+ '1\xa0minute')
+ self.assertEqual(timesince(self.t, self.t+self.onehour), '1\xa0hour')
+ self.assertEqual(timesince(self.t, self.t+self.oneday), '1\xa0day')
+ self.assertEqual(timesince(self.t, self.t+self.oneweek), '1\xa0week')
self.assertEqual(timesince(self.t, self.t+self.onemonth),
- '1 month')
- self.assertEqual(timesince(self.t, self.t+self.oneyear), '1 year')
+ '1\xa0month')
+ self.assertEqual(timesince(self.t, self.t+self.oneyear), '1\xa0year')
def test_multiple_units(self):
""" Test multiple units. """
self.assertEqual(timesince(self.t,
- self.t+2*self.oneday+6*self.onehour), '2 days, 6 hours')
+ self.t+2*self.oneday+6*self.onehour), '2\xa0days, 6\xa0hours')
self.assertEqual(timesince(self.t,
- self.t+2*self.oneweek+2*self.oneday), '2 weeks, 2 days')
+ self.t+2*self.oneweek+2*self.oneday), '2\xa0weeks, 2\xa0days')
def test_display_first_unit(self):
"""
@@ -55,10 +56,10 @@ def test_display_first_unit(self):
"""
self.assertEqual(timesince(self.t,
self.t+2*self.oneweek+3*self.onehour+4*self.oneminute),
- '2 weeks')
+ '2\xa0weeks')
self.assertEqual(timesince(self.t,
- self.t+4*self.oneday+5*self.oneminute), '4 days')
+ self.t+4*self.oneday+5*self.oneminute), '4\xa0days')
def test_display_second_before_first(self):
"""
@@ -66,30 +67,30 @@ def test_display_second_before_first(self):
get 0 minutes.
"""
self.assertEqual(timesince(self.t, self.t-self.onemicrosecond),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.onesecond),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.oneminute),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.onehour),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.oneday),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.oneweek),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.onemonth),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t, self.t-self.oneyear),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t,
- self.t-2*self.oneday-6*self.onehour), '0 minutes')
+ self.t-2*self.oneday-6*self.onehour), '0\xa0minutes')
self.assertEqual(timesince(self.t,
- self.t-2*self.oneweek-2*self.oneday), '0 minutes')
+ self.t-2*self.oneweek-2*self.oneday), '0\xa0minutes')
self.assertEqual(timesince(self.t,
self.t-2*self.oneweek-3*self.onehour-4*self.oneminute),
- '0 minutes')
+ '0\xa0minutes')
self.assertEqual(timesince(self.t,
- self.t-4*self.oneday-5*self.oneminute), '0 minutes')
+ self.t-4*self.oneday-5*self.oneminute), '0\xa0minutes')
def test_different_timezones(self):
""" When using two different timezones. """
@@ -97,28 +98,28 @@ def test_different_timezones(self):
now_tz = datetime.datetime.now(LocalTimezone(now))
now_tz_i = datetime.datetime.now(FixedOffset((3 * 60) + 15))
- self.assertEqual(timesince(now), '0 minutes')
- self.assertEqual(timesince(now_tz), '0 minutes')
- self.assertEqual(timeuntil(now_tz, now_tz_i), '0 minutes')
+ self.assertEqual(timesince(now), '0\xa0minutes')
+ self.assertEqual(timesince(now_tz), '0\xa0minutes')
+ self.assertEqual(timeuntil(now_tz, now_tz_i), '0\xa0minutes')
def test_date_objects(self):
""" Both timesince and timeuntil should work on date objects (#17937). """
today = datetime.date.today()
- self.assertEqual(timesince(today + self.oneday), '0 minutes')
- self.assertEqual(timeuntil(today - self.oneday), '0 minutes')
+ self.assertEqual(timesince(today + self.oneday), '0\xa0minutes')
+ self.assertEqual(timeuntil(today - self.oneday), '0\xa0minutes')
def test_both_date_objects(self):
""" Timesince should work with both date objects (#9672) """
today = datetime.date.today()
- self.assertEqual(timeuntil(today + self.oneday, today), '1 day')
- self.assertEqual(timeuntil(today - self.oneday, today), '0 minutes')
- self.assertEqual(timeuntil(today + self.oneweek, today), '1 week')
+ self.assertEqual(timeuntil(today + self.oneday, today), '1\xa0day')
+ self.assertEqual(timeuntil(today - self.oneday, today), '0\xa0minutes')
+ self.assertEqual(timeuntil(today + self.oneweek, today), '1\xa0week')
def test_naive_datetime_with_tzinfo_attribute(self):
class naive(datetime.tzinfo):
def utcoffset(self, dt):
return None
future = datetime.datetime(2080, 1, 1, tzinfo=naive())
- self.assertEqual(timesince(future), '0 minutes')
+ self.assertEqual(timesince(future), '0\xa0minutes')
past = datetime.datetime(1980, 1, 1, tzinfo=naive())
- self.assertEqual(timeuntil(past), '0 minutes')
+ self.assertEqual(timeuntil(past), '0\xa0minutes')
Please sign in to comment.
Something went wrong with that request. Please try again.