diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 8e039432728..41de1782a1f 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -57,6 +57,7 @@ def render(hass, template, variables=None, **kwargs): 'states': AllStates(hass), 'utcnow': utcnow, 'as_timestamp': dt_util.as_timestamp, + 'relative_time': dt_util.get_age }).render(kwargs).strip() except jinja2.TemplateError as err: raise TemplateError(err) diff --git a/homeassistant/util/dt.py b/homeassistant/util/dt.py index 16e8dfebfd1..b06b70f2cdd 100644 --- a/homeassistant/util/dt.py +++ b/homeassistant/util/dt.py @@ -152,3 +152,49 @@ def parse_time(time_str): except ValueError: # ValueError if value cannot be converted to an int or not in range return None + + +# Found in this gist: https://gist.github.com/zhangsen/1199964 +def get_age(date): + """ + Take a datetime and return its "age" as a string. + + The age can be in second, minute, hour, day, month or year. Only the + biggest unit is considered, e.g. if it's 2 days and 3 hours, "2 days" will + be returned. + Make sure date is not in the future, or else it won't work. + """ + def formatn(number, unit): + """Add "unit" if it's plural.""" + if number == 1: + return "1 %s" % unit + elif number > 1: + return "%d %ss" % (number, unit) + + def q_n_r(first, second): + """Return quotient and remaining.""" + return first // second, first % second + + # pylint: disable=too-few-public-methods + class PrettyDelta: + """A class for relative times.""" + + def __init__(self, subDt): + delta = now() - subDt + self.day = delta.days + self.second = delta.seconds + + self.year, self.day = q_n_r(self.day, 365) + self.month, self.day = q_n_r(self.day, 30) + self.hour, self.second = q_n_r(self.second, 3600) + self.minute, self.second = q_n_r(self.second, 60) + + def format(self): + """Format a datetime to relative time string.""" + for period in ['year', 'month', 'day', 'hour', 'minute', 'second']: + number = getattr(self, period) + if number > 0: + return formatn(number, period) + return "0 second" + + return PrettyDelta(date).format() diff --git a/tests/util/test_dt.py b/tests/util/test_dt.py index da5b56d42a9..1b51287384c 100644 --- a/tests/util/test_dt.py +++ b/tests/util/test_dt.py @@ -133,3 +133,8 @@ class TestDateUtil(unittest.TestCase): def test_parse_datetime_returns_none_for_incorrect_format(self): """Test parse_datetime returns None if incorrect format.""" self.assertIsNone(dt_util.parse_datetime("not a datetime string")) + + def test_get_age(self): + """Test get_age returns 5 minutes.""" + fiveminago = dt_util.now() - timedelta(minutes=5) + self.assertEqual(dt_util.get_age(fiveminago), "5 minutes")