Skip to content

Commit

Permalink
h.render_datetime renders datestamps now with seconds
Browse files Browse the repository at this point in the history
This is extracted from #3972

When a user drills into activity stream, each version is known by its timestamp, and
on occasions that a user makes multiple changes in the same minute, showing the
hours:minutes:seconds is really useful.

The impending #3972 has a replacement bit of HTML which calls h.render_datetime with the new
'with_seconds' option yet.
  • Loading branch information
David Read committed Dec 21, 2018
1 parent 8f0cb74 commit 4163f17
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 37 deletions.
22 changes: 17 additions & 5 deletions ckan/lib/formatters.py
Expand Up @@ -70,15 +70,21 @@ def _month_dec():
_month_sept, _month_oct, _month_nov, _month_dec]


def localised_nice_date(datetime_, show_date=False, with_hours=False):
def localised_nice_date(datetime_, show_date=False, with_hours=False,
with_seconds=False):
''' Returns a friendly localised unicode representation of a datetime.
e.g. '31 minutes ago'
'1 day ago'
'April 24, 2013' (show_date=True)
:param datetime_: The date to format
:type datetime_: datetime
:param show_date: Show date not 2 days ago etc
:param show_date: Show 'April 24, 2013' instead of '2 days ago'
:type show_date: bool
:param with_hours: should the `hours:mins` be shown for dates
:type with_hours: bool
:param with_seconds: should the `hours:mins:seconds` be shown for dates
:type with_seconds: bool
:rtype: sting
'''
Expand Down Expand Up @@ -132,6 +138,7 @@ def months_between(date1, date2):

# actual date
details = {
'sec': int(datetime_.second),
'min': datetime_.minute,
'hour': datetime_.hour,
'day': datetime_.day,
Expand All @@ -140,14 +147,19 @@ def months_between(date1, date2):
'timezone': datetime_.tzname(),
}

if with_hours:
if with_seconds:
return (
# NOTE: This is for translating dates like `April 24, 2013, 10:45 (Europe/Zurich)`
# Example output: `April 24, 2013, 10:45:21 (Europe/Zurich)`
_('{month} {day}, {year}, {hour:02}:{min:02}:{sec:02} ({timezone})') \
.format(**details))
elif with_hours:
return (
# Example output: `April 24, 2013, 10:45 (Europe/Zurich)`
_('{month} {day}, {year}, {hour:02}:{min:02} ({timezone})') \
.format(**details))
else:
return (
# NOTE: This is for translating dates like `April 24, 2013`
# Example output: `April 24, 2013`
_('{month} {day}, {year}').format(**details))


Expand Down
8 changes: 6 additions & 2 deletions ckan/lib/helpers.py
Expand Up @@ -1422,7 +1422,8 @@ def get_display_timezone():


@core_helper
def render_datetime(datetime_, date_format=None, with_hours=False):
def render_datetime(datetime_, date_format=None, with_hours=False,
with_seconds=False):
'''Render a datetime object or timestamp string as a localised date or
in the requested format.
If timestamp is badly formatted, then a blank string is returned.
Expand All @@ -1433,6 +1434,8 @@ def render_datetime(datetime_, date_format=None, with_hours=False):
:type date_format: string
:param with_hours: should the `hours:mins` be shown
:type with_hours: bool
:param with_seconds: should the `hours:mins:seconds` be shown
:type with_seconds: bool
:rtype: string
'''
Expand Down Expand Up @@ -1463,7 +1466,8 @@ def render_datetime(datetime_, date_format=None, with_hours=False):
return datetime_.strftime(date_format)
# the localised date
return formatters.localised_nice_date(datetime_, show_date=True,
with_hours=with_hours)
with_hours=with_hours,
with_seconds=with_seconds)


@core_helper
Expand Down
30 changes: 0 additions & 30 deletions ckan/tests/legacy/lib/test_helpers.py
Expand Up @@ -23,36 +23,6 @@ def test_extract_markdown(self):
assert "Data exposed" in h.markdown_extract(WITH_HTML)
assert "collects information" in h.markdown_extract(WITH_UNICODE)

def test_render_datetime(self):
res = h.render_datetime(datetime.datetime(2008, 4, 13, 20, 40, 20, 123456))
assert_equal(res, 'April 13, 2008')

def test_render_datetime_with_hours(self):
res = h.render_datetime(datetime.datetime(2008, 4, 13, 20, 40, 20, 123456), with_hours=True)
assert_equal(res, 'April 13, 2008, 20:40 (UTC)')

def test_render_datetime_but_from_string(self):
res = h.render_datetime('2008-04-13T20:40:20.123456')
assert_equal(res, 'April 13, 2008')

def test_render_datetime_blank(self):
res = h.render_datetime(None)
assert_equal(res, '')

def test_render_datetime_year_before_1900(self):
res = h.render_datetime('1875-04-13T20:40:20.123456', date_format='%Y')
assert_equal(res, '1875')

res = h.render_datetime('1875-04-13T20:40:20.123456', date_format='%y')
assert_equal(res, '75')

def test_render_datetime_year_before_1900_escape_percent(self):
res = h.render_datetime('1875-04-13', date_format='%%%y')
assert_equal(res, '%75')

res = h.render_datetime('1875-04-13', date_format='%%%Y')
assert_equal(res, '%1875')

def test_datetime_to_date_str(self):
res = datetime.datetime(2008, 4, 13, 20, 40, 20, 123456).isoformat()
assert_equal(res, '2008-04-13T20:40:20.123456')
Expand Down
37 changes: 37 additions & 0 deletions ckan/tests/lib/test_helpers.py
Expand Up @@ -521,6 +521,43 @@ def test_named_timezone(self):
eq_(h.get_display_timezone(), pytz.timezone('America/New_York'))


class TestHelpersRenderDatetime(object):

def test_date(self):
data = datetime.datetime(2008, 4, 13, 20, 40, 59, 123456)
eq_(h.render_datetime(data), 'April 13, 2008')

def test_with_hours(self):
data = datetime.datetime(2008, 4, 13, 20, 40, 59, 123456)
eq_(h.render_datetime(data, with_hours=True),
'April 13, 2008, 20:40 (UTC)')

def test_with_seconds(self):
data = datetime.datetime(2008, 4, 13, 20, 40, 59, 123456)
eq_(h.render_datetime(data, with_seconds=True),
'April 13, 2008, 20:40:59 (UTC)')

def test_from_string(self):
data = '2008-04-13T20:40:20.123456'
eq_(h.render_datetime(data), 'April 13, 2008')

def test_blank(self):
data = None
eq_(h.render_datetime(data), '')

def test_before_1900(self):
data = '1875-04-13T20:40:20.123456'
eq_(h.render_datetime(data, date_format='%Y'), '1875')

def test_before_1900_with_2_digit_year(self):
data = '1875-04-13T20:40:20.123456'
eq_(h.render_datetime(data, date_format='%y'), '75')

def test_escaped_percent(self):
data = '2008-04-13T20:40:20.123456'
eq_(h.render_datetime(data, date_format='%%%Y'), '%2008')


class TestCleanHtml(object):
def test_disallowed_tag(self):
eq_(h.clean_html('<b><bad-tag>Hello'),
Expand Down

0 comments on commit 4163f17

Please sign in to comment.