Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port/MycroftAI/lingua-franca/pull/232 #27

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion lingua_franca/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@
is_supported_full_lang, _raise_unsupported_language, \
UnsupportedLanguageError, NoneLangWarning, InvalidLangWarning, \
FunctionNotLocalizedError, resolve_resource_file, FunctionNotLocalizedError
from lingua_franca.time import now_local, to_local


_REGISTERED_FUNCTIONS = ("nice_number",
"nice_time",
"pronounce_number",
"pronounce_lang",
"nice_response",
"nice_duration")
"nice_duration",
"nice_relative_time")

populate_localized_function_dict("format", langs=get_active_langs())

Expand Down Expand Up @@ -578,3 +580,53 @@ def nice_response(text, lang=''):
assertEqual(nice_response_de("10 ^ 2"),
"10 hoch 2")
"""

@localized_function(run_own_code_on=[FunctionNotLocalizedError])
def nice_relative_time(when, relative_to=None, lang=None):
"""Create a relative phrase to roughly describe the period between two
datetimes.

Examples are "25 seconds", "tomorrow", "7 days".

Note: The reported period is currently limited to a number of days. Longer
periods such as multiple weeks or months will be reported in days.

Args:
when (datetime): Local timezone
relative_to (datetime): Baseline for relative time, default is now()
lang (str, optional): Defaults to "en-us".
Returns:
str: Relative description of the given time
"""
now = relative_to if relative_to else now_local()
delta = to_local(when) - now

if delta.total_seconds() < 1:
return "now"

if delta.total_seconds() < 90:
if delta.total_seconds() == 1:
return "one second"
else:
return f"{int(delta.total_seconds())} seconds"

minutes = int((delta.total_seconds() + 30) // 60) # +30 to round minutes
if minutes < 90:
if minutes == 1:
return "one minute"
else:
return "{} minutes".format(minutes)

hours = int((minutes + 30) // 60) # +30 to round hours
if hours < 36:
if hours == 1:
return "one hour"
else:
return "{} hours".format(hours)

# TODO: "2 weeks", "3 months", "4 years", etc
days = int((hours + 12) // 24) # +12 to round days
if days == 1:
return "1 day"
else:
return "{} days".format(days)
4 changes: 4 additions & 0 deletions lingua_franca/lang/format_eu.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,15 @@ def nice_time_eu(dt, speech=True, use_24hour=False, use_ampm=False):
# hemen dago tranpa
# return str(dt.hour) + ":" + str(dt.minute)


def nice_relative_time_eu(when, relative_to=None, lang=None):
"""Create a relative phrase to roughly describe a datetime

Examples are "25 seconds", "tomorrow", "7 days".

Note: The reported period is currently limited to a number of days. Longer
periods such as multiple weeks or months will be reported in days.

Args:
when (datetime): Local timezone
relative_to (datetime): Baseline for relative time, default is now()
Expand Down
37 changes: 37 additions & 0 deletions test/unittests/test_format_en.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from lingua_franca.format import date_time_format
from lingua_franca.format import join_list
from lingua_franca.format import pronounce_lang
from lingua_franca.format import nice_relative_time
from lingua_franca.time import default_timezone, set_default_tz, now_local, \
to_local

Expand Down Expand Up @@ -534,6 +535,42 @@ def test_join(self):
self.assertEqual(join_list([1, "b", 3, "d"], "or"), "1, b, 3 or d")


class TestNiceRelativeTime(unittest.TestCase):
def test_format_nice_relative_time(self):
base_datetime = datetime.datetime(2017, 1, 31, 13, 22, 3,
tzinfo=default_timezone())
two_hours_from_base = base_datetime + datetime.timedelta(hours=2)
self.assertEqual(
nice_relative_time(when=two_hours_from_base, relative_to=base_datetime),
"2 hours"
)
twoish_hours_from_base = base_datetime + datetime.timedelta(hours=2, minutes=27)
self.assertEqual(
nice_relative_time(when=twoish_hours_from_base, relative_to=base_datetime),
"2 hours"
)
seconds_from_base = base_datetime + datetime.timedelta(seconds=47)
self.assertEqual(
nice_relative_time(when=seconds_from_base, relative_to=base_datetime),
"47 seconds"
)
three_days_from_base = base_datetime + datetime.timedelta(days=3)
self.assertEqual(
nice_relative_time(when=three_days_from_base, relative_to=base_datetime),
"3 days"
)
almost_four_days_from_base = base_datetime + datetime.timedelta(days=3, hours=20)
self.assertEqual(
nice_relative_time(when=almost_four_days_from_base, relative_to=base_datetime),
"4 days"
)
long_time_from_base = base_datetime + datetime.timedelta(days=957, hours=2, seconds=12)
self.assertEqual(
nice_relative_time(when=long_time_from_base, relative_to=base_datetime),
"957 days"
)


class TestLangcode(unittest.TestCase):
def test_format_lang_code(self):
self.assertEqual(pronounce_lang(lang_code="en"), "English")
Expand Down