Skip to content

Commit

Permalink
Add tests for relative date formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalp committed Jul 27, 2024
1 parent b6913f3 commit 28833f2
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 28 deletions.
3 changes: 3 additions & 0 deletions devproject/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
# Test assertions expect english locale
LANGUAGE_CODE = "en-us"

# Test assertions expect specific TZ
TIME_ZONE = "UTC"

# Register test post validator
MISAGO_POST_VALIDATORS = ["misago.core.testproject.validators.test_post_validator"]

Expand Down
28 changes: 14 additions & 14 deletions frontend/src/formats.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export const locale = window.misago_locale || "en-us"

export const momentAgo = pgettext("time ago", "moment ago")
export const momentAgoNarrow = pgettext("time ago", "now")
export const momentAgoShort = pgettext("time ago", "now")
export const dayAt = pgettext("day at time", "%(day)s at %(time)s")
export const soonAt = pgettext("day at time", "at %(time)s")
export const soonAt = pgettext("day at time", "Today at %(time)s")
export const tomorrowAt = pgettext("day at time", "Tomorrow at %(time)s")
export const yesterdayAt = pgettext("day at time", "Yesterday at %(time)s")

export const minuteShort = pgettext("short minutes", "%(time)sm")
export const hourShort = pgettext("short hours", "%(time)sh")
export const dayShort = pgettext("short days", "%(time)sd")
export const minutesShort = pgettext("short minutes", "%(time)sm")
export const hoursShort = pgettext("short hours", "%(time)sh")
export const daysShort = pgettext("short days", "%(time)sd")
export const thisYearShort = pgettext("short month", "%(day)s %(month)s")
export const otherYearShort = pgettext("short month", "%(month)s %(year)s")

Expand Down Expand Up @@ -57,12 +57,12 @@ export function dateRelative(date) {
}

if (absDiff < 60 * 47) {
const minutes = Math.ceil(absDiff / 60) * sign
const minutes = Math.round(absDiff / 60) * sign
return relativeNumeric.format(minutes, "minute")
}

if (absDiff < 3600 * 3) {
const hours = Math.ceil(absDiff / 3600) * sign
const hours = Math.round(absDiff / 3600) * sign
return relativeNumeric.format(hours, "hour")
}

Expand Down Expand Up @@ -125,22 +125,22 @@ export function dateRelativeShort(date) {
const absDiff = Math.abs(Math.round((date - now) / 1000))

if (absDiff < 60) {
return momentAgoNarrow
return momentAgoShort
}

if (absDiff < 60 * 55) {
const minutes = Math.ceil(absDiff / 60)
return minuteShort.replace("%(time)s", minutes)
const minutes = Math.round(absDiff / 60)
return minutesShort.replace("%(time)s", minutes)
}

if (absDiff < 3600 * 24) {
const hours = Math.ceil(absDiff / 3600)
return hourShort.replace("%(time)s", hours)
const hours = Math.round(absDiff / 3600)
return hoursShort.replace("%(time)s", hours)
}

if (absDiff < 86400 * 7) {
const days = Math.ceil(absDiff / 86400)
return dayShort.replace("%(time)s", days)
const days = Math.round(absDiff / 86400)
return daysShort.replace("%(time)s", days)
}

const parts = {}
Expand Down
33 changes: 21 additions & 12 deletions misago/formats/daterelative.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from datetime import datetime, timedelta
from math import ceil

from django.utils import timezone
from django.utils.formats import date_format, time_format
from django.utils.formats import date_format
from django.utils.translation import npgettext, pgettext


Expand All @@ -15,7 +14,7 @@ def date_relative(value: datetime) -> str:
return pgettext("time ago", "moment ago")

if delta < 60 * 47:
minutes = ceil(delta / 60)
minutes = round(delta / 60)
if past:
return npgettext(
"minutes ago",
Expand All @@ -32,7 +31,7 @@ def date_relative(value: datetime) -> str:
) % {"time": minutes}

if delta < 3600 * 3:
hours = ceil(delta / 3600)
hours = round(delta / 3600)
if past:
return npgettext(
"hours ago",
Expand All @@ -50,24 +49,26 @@ def date_relative(value: datetime) -> str:

if is_same_day(now, value):
if past:
return time_format(value)
return time_short(value)

return pgettext("day at time", "at %(time)s") % {"time": time_format(value)}
return pgettext("day at time", "Today at %(time)s") % {
"time": time_short(value)
}

if is_yesterday(now, value):
return pgettext("day at time", "Yesterday at %(time)s") % {
"time": time_format(value)
"time": time_short(value)
}

if is_tomorrow(now, value):
return pgettext("day at time", "Tomorrow at %(time)s") % {
"time": time_format(value)
"time": time_short(value)
}

if past and delta < 3600 * 24 * 6:
return pgettext("day at time", "%(day)s at %(time)s") % {
"day": date_format(value, "l"),
"time": time_format(value),
"time": time_short(value),
}

if is_same_year(now, value):
Expand Down Expand Up @@ -102,18 +103,26 @@ def date_relative_short(value: datetime) -> str:
return pgettext("time ago", "now")

if delta < 60 * 55:
minutes = ceil(delta / 60)
minutes = round(delta / 60)
return pgettext("short minutes", "%(time)sm") % {"time": minutes}

if delta < 3600 * 24:
hours = ceil(delta / 3600)
hours = round(delta / 3600)
return pgettext("short hours", "%(time)sh") % {"time": hours}

if delta < 86400 * 7:
days = ceil(delta / 86400)
days = round(delta / 86400)
return pgettext("short days", "%(time)sd") % {"time": days}

if now.year == value.year:
return date_format(value, pgettext("short this year", "j M"))

return date_format(value, pgettext("short other year", "M y"))


def time_short(value: datetime) -> str:
return date_format(
value,
pgettext("time short", "g:i A"),
use_l10n=False,
)
99 changes: 99 additions & 0 deletions misago/formats/tests/test_date_relative.py
Original file line number Diff line number Diff line change
@@ -1 +1,100 @@
from datetime import timedelta

from django.utils import timezone
from freezegun import freeze_time

from ..daterelative import date_relative


def test_date_relative_formats_recent_date():
assert date_relative(timezone.now()) == "moment ago"


def test_date_relative_formats_date_few_seconds_ago():
timestamp = timezone.now() - timedelta(seconds=5)
assert date_relative(timestamp) == "moment ago"


def test_date_relative_formats_date_few_seconds_in_future():
timestamp = timezone.now() + timedelta(seconds=5)
assert date_relative(timestamp) == "moment ago"


def test_date_relative_formats_date_few_minutes_ago():
timestamp = timezone.now() - timedelta(minutes=5)
assert date_relative(timestamp) == "5 minutes ago"


def test_date_relative_formats_date_few_minutes_in_future():
timestamp = timezone.now() + timedelta(minutes=5)
assert date_relative(timestamp) == "In 5 minutes"


def test_date_relative_formats_date_few_hours_ago():
timestamp = timezone.now() - timedelta(hours=2)
assert date_relative(timestamp) == "2 hours ago"


def test_date_relative_formats_date_few_hours_in_future():
timestamp = timezone.now() + timedelta(hours=2)
assert date_relative(timestamp) == "In 2 hours"


@freeze_time("2024-07-27 21:37")
def test_date_relative_formats_date_today():
timestamp = timezone.now() - timedelta(hours=7)
assert date_relative(timestamp) == "2:37 PM"


@freeze_time("2024-07-27 11:37")
def test_date_relative_formats_date_today_in_future():
timestamp = timezone.now() + timedelta(hours=7)
assert date_relative(timestamp) == "Today at 6:37 PM"


@freeze_time("2024-07-27 15:12")
def test_date_relative_formats_date_yesterday():
timestamp = timezone.now() - timedelta(hours=24)
assert date_relative(timestamp) == "Yesterday at 3:12 PM"


@freeze_time("2024-07-27 15:12")
def test_date_relative_formats_date_tomorrow():
timestamp = timezone.now() + timedelta(hours=24)
assert date_relative(timestamp) == "Tomorrow at 3:12 PM"


@freeze_time("2024-07-27 15:12")
def test_date_relative_formats_date_few_days_ago():
timestamp = timezone.now() - timedelta(hours=72)
assert date_relative(timestamp) == "Wednesday at 3:12 PM"


@freeze_time("2024-07-23 00:00")
def test_date_relative_uses_hours_instead_of_midnight():
timestamp = timezone.now() - timedelta(hours=24)
assert date_relative(timestamp) == "Yesterday at 12:00 AM"


@freeze_time("2024-07-23 00:00")
def test_date_relative_uses_day_and_month_for_past_date_this_year():
timestamp = timezone.now() - timedelta(days=100)
assert date_relative(timestamp) == "April 14"


@freeze_time("2024-07-23 00:00")
def test_date_relative_uses_day_and_month_for_future_date_this_year():
timestamp = timezone.now() + timedelta(days=100)
assert date_relative(timestamp) == "October 31"


@freeze_time("2024-07-23 00:00")
def test_date_relative_uses_day_and_month_for_date_previous_year():
timestamp = timezone.now() - timedelta(days=400)
assert date_relative(timestamp) == "June 19, 2023"


@freeze_time("2024-07-23 00:00")
def test_date_relative_uses_day_and_month_for_date_next_year():
timestamp = timezone.now() + timedelta(days=400)
assert date_relative(timestamp) == "August 27, 2025"
37 changes: 37 additions & 0 deletions misago/formats/tests/test_date_relative_short.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from datetime import timedelta

from django.utils import timezone
from freezegun import freeze_time

from ..daterelative import date_relative_short


def test_date_relative_short_formats_recent_date():
assert date_relative_short(timezone.now()) == "now"


def test_date_relative_short_formats_date_few_minutes_ago():
timestamp = timezone.now() - timedelta(minutes=5)
assert date_relative_short(timestamp) == "5m"


def test_date_relative_short_formats_date_few_hours_ago():
timestamp = timezone.now() - timedelta(hours=5)
assert date_relative_short(timestamp) == "5h"


def test_date_relative_short_formats_date_few_days_ago():
timestamp = timezone.now() - timedelta(hours=5 * 24)
assert date_relative_short(timestamp) == "5d"


@freeze_time("2024-07-27 15:12")
def test_date_relative_short_formats_date_from_this_year():
timestamp = timezone.now() - timedelta(days=100)
assert date_relative_short(timestamp) == "18 Apr"


@freeze_time("2024-07-27 15:12")
def test_date_relative_short_formats_date_from_other_year():
timestamp = timezone.now() - timedelta(days=400)
assert date_relative_short(timestamp) == "Jun 23"
2 changes: 1 addition & 1 deletion misago/static/misago/js/misago.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion misago/static/misago/js/misago.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ django-debug-toolbar
django-mptt
django-simple-sso
Faker
freezegun
html5lib
markdown
social-auth-app-django
Expand Down
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ docopt==0.6.2
# via coveralls
faker==23.1.0
# via -r requirements.in
freezegun==1.5.1
# via -r requirements.in
graphql-core==3.2.3
# via ariadne
html5lib==1.1
Expand Down Expand Up @@ -144,6 +146,7 @@ python-dateutil==2.8.2
# via
# celery
# faker
# freezegun
python3-openid==3.2.0
# via social-auth-core
pytz==2024.1
Expand Down

0 comments on commit 28833f2

Please sign in to comment.