From 10fce5b4ae77bb04c4f09aa1603383b7755b528e Mon Sep 17 00:00:00 2001 From: Tony Stork Date: Mon, 4 Dec 2023 12:12:21 -0500 Subject: [PATCH] Update external time macros --- custom_templates/easy_time.jinja | 368 ++++++++++++++++------ custom_templates/relative_time_plus.jinja | 187 ++++++----- 2 files changed, 384 insertions(+), 171 deletions(-) diff --git a/custom_templates/easy_time.jinja b/custom_templates/easy_time.jinja index f757594..6bea632 100644 --- a/custom_templates/easy_time.jinja +++ b/custom_templates/easy_time.jinja @@ -70,8 +70,94 @@ 'October', 'November', 'December', - ] + ], + 'time_of_hour':{ + 0: '{hour} o\'clock', + 1: 'a minute past {hour}', + 15: 'quarter past {hour}', + 30: 'half past {hour}', + 45: 'quarter to {hour}', + 59: 'a minute to {hour}', + 'past_hour': '{minute} past {hour}', + 'to_hour': '{minute} to {hour}', + }, + 'time_of_day':{ + 'midnight': 'midnight', + 'noon': 'noon', + }, }, + 'sk':{ + '_language': 'Slovak', + 'and': 'a', + 'in': 'v', + 'ago': 'pred', + 'now': 'teraz', + 'lose': 'strata', + 'gain': 'zosilnenie', + 'time':{ + 'format': '12-hr', + 'year': [ + 'rok', + 'rok', + 'roky', + ], + 'week': [ + 'týž', + 'týždeň', + 'týždne', + ], + 'day': [ + 'd', + 'deň', + 'dni', + ], + 'hour': [ + 'hod', + 'hodina', + 'hodiny', + ], + 'minute': [ + 'min', + 'minúta', + 'minúty', + ], + 'second': [ + 'sek', + 'sekunda', + 'sekundy', + ], + }, + 'delta':{ + 'today': 'dnes', + 'tomorrow': 'zajtra', + 'yesterday': 'včera', + 'next': 'ďalší', + 'last': 'predchádzajúci', + }, + 'days':[ + "Pondelok", + "Utorok", + "Streda", + "Štvrtok", + "Piatok", + "Sobota", + "Nedeľa", + ], + 'months':[ + 'Január', + 'Február', + 'Marec', + 'Apríl', + 'Máj', + 'Jún', + 'Júl', + 'August', + 'September', + 'Október', + 'November', + 'December', + ] + }, 'nl':{ '_language': 'Nederlands', 'and': 'en', @@ -959,8 +1045,32 @@ {%- endfor %} {%- endmacro %} +{%- macro translate(k1, k2=None, k3=None, k4=None, k5=None, index=None, fallback=None, language=None) %} +{#- This macro is ugly, but fast, don't change it #} +{%- set l = language or default_language %} +{%- set dflt = _bad_value if fallback is none else fallback %} +{%- if k2 is not none and k3 is not none and k4 is not none and k5 is not none %} +{%- set output = languages.get(l, {}).get(k1, {}).get(k2, {}).get(k3, {}).get(k4, {}).get(k5) %} +{%- elif k2 is not none and k3 is not none and k4 is not none and k5 is none %} +{%- set output = languages.get(l, {}).get(k1, {}).get(k2, {}).get(k3, {}).get(k4) %} +{%- elif k2 is not none and k3 is not none and k4 is none and k5 is none %} +{%- set output = languages.get(l, {}).get(k1, {}).get(k2, {}).get(k3) %} +{%- elif k2 is not none and k3 is none and k4 is none and k5 is none %} +{%- set output = languages.get(l, {}).get(k1, {}).get(k2) %} +{%- else %} +{%- set output = languages.get(l, {}).get(k1) %} +{%- endif %} +{%- if output is none %} +{{- dflt }} +{%- elif index is not none and index is integer and output is list %} +{{- output[index] }} +{%- else %} +{{- output}} +{%- endif %} +{%- endmacro %} + {%- macro _get_language_time_format(override, language) %} -{%- set lang_fmat = languages.get(language, {}).get('time', {}).get('format', _bad_value) %} +{%- set lang_fmat = translate('time', 'format', language=language) %} {%- set fmat = _time_formats.get(override, _default_time_format) if override in _time_formats.keys() else _time_formats.get(lang_fmat, _default_time_format) %} {{- fmat }} {%- endmacro %} @@ -992,7 +1102,7 @@ {%- macro _to_datetime(input, attribute=None, utc=False) -%} {#- Already a datetime -#} -{%- if input.date is defined and input.date is callable -%} +{%- if input is datetime -%} {%- if input.tzinfo is none and utc -%} {{- _toutc(input) -}} {%- elif input.tzinfo is none -%} @@ -1047,17 +1157,23 @@ {%- macro _get_period_max(id, uptime_seconds) %} {%- set duration = _durations.get(id, 1) %} -{%- set period = _periods.get(id) %} {{- uptime_seconds // duration }} {%- endmacro %} +{%- macro _get_period_round(id, uptime_seconds) %} +{%- set duration = _durations.get(id, 1) %} +{{- (uptime_seconds / duration) | round }} +{%- endmacro %} + {# macro to generate a time #} -{%- macro _phrase(id, uptime_seconds, language, max, raw) %} -{%- set lang = languages.get(language, {}).get('time', {}).get(id, [_bad_value]*3) %} -{%- set abbr, single, plural = lang %} +{%- macro _phrase(id, uptime_seconds, language, max, raw, round_value=False) %} +{%- if round_value %} +{%- set func = _get_period_round %} +{%- else %} {%- set func = _get_period_max if max else _get_period_value %} +{%- endif %} {%- set value = func(id, uptime_seconds) | int %} -{%- set name = plural if value != 1 else single %} +{%- set name = translate('time', id, index=2, language=language) if value != 1 else translate('time', id, index=1, language=language) %} {{- '{} {}'.format(value, name) if value | int > 0 or raw else '' -}} {% endmacro %} @@ -1069,56 +1185,66 @@ {{- dict.from_keys(ns.ret) | to_json }} {%- endmacro %} -{%- macro _phrases(seconds, values, language, raw) %} -{%- set ns = namespace(ret=[]) %} -{#- ensure we have a list of values #} -{%- set values = [ values ] if values is string else values %} -{#- filter values to only have items in _default_values #} -{%- set values = values | select('in', _default_values) | list %} -{#- this should be a good list of values if the previous 2 filters didn't remove anything #} -{%- set values = _default_values | select('in', values) | list if values else _default_values %} -{%- set biggest = values | first | default %} -{%- set index = values.index(biggest) %} -{%- for item in values[index:] %} - {%- set phrase = _phrase(item, seconds, language, loop.first, raw) %} - {%- if phrase %} - {%- set ns.ret = ns.ret + [phrase] %} - {%- endif %} -{%- endfor %} -{{- ns.ret | to_json }} -{%- endmacro %} - {# macro to generate a friendly phrase #} -{%- macro _just_time(seconds, language, values, biggest, raw=False) %} +{%- macro _just_time(seconds, language, values, biggest, raw=False, short=False, floor=False) %} {%- if seconds < 1 %} - {{- languages.get(language, {}).get('now', _bad_value) }} + {{- translate('now', language=language) }} {%- else %} - {%- set phrases = _phrases(seconds, values, language, raw) | from_json %} - {%- if phrases | length > 0 %} - {%- if biggest %} - {{- phrases[0] }} - {%- else %} - {%- set word_for_and = languages.get(language, {}).get('and', _bad_value) %} - {{- phrases[:-1] | join(', ') ~ ' ' ~ word_for_and ~ ' ' ~ phrases[-1] if phrases | length > 1 else phrases | first | default }} + {#- this used to be a macro, was slow because it converted to/from json #} + {%- set ns = namespace(ret=[]) %} + {#- ensure we have a list of values #} + {%- set values = [ values ] if values is string else values %} + {#- filter values to only have items in _default_values #} + {%- set values = values | select('in', _default_values) | list %} + {#- this should be a good list of values if the previous 2 filters didn't remove anything #} + {%- set values = _default_values | select('in', values) | list if values else _default_values %} + {%- set index = values.index(values | first | default) %} + {%- for item in values[index:] %} + {%- set duration = _durations.get(item, 1) %} + {%- set period = _periods.get(item, 1) %} + {%- set value = ((seconds // duration) % (period if period else duration)) | int %} + {%- if value > 0 or raw %} + {%- if ns.ret | length == 0 %} + {%- set chosen = (seconds / duration) | round if biggest and not floor else seconds // duration %} + {%- else %} + {%- set chosen = value %} + {%- endif %} + {%- set chosen = chosen | int %} + {%- if short %} + {%- set units = translate('time', item, index=0, language=language) %} + {%- else %} + {%- set units = translate('time', item, index=2, language=language) if chosen != 1 else translate('time', item, index=1, language=language) %} + {%- set units = ' %s' % units %} + {%- endif %} + {%- set ns.ret = ns.ret + [ '%s%s' % (chosen, units) ] %} + {%- if biggest and ns.ret | length == 1 %} + {%- break %} + {%- endif %} {%- endif %} + {%- endfor %} + {%- set phrases = ns.ret %} + {#- add our langauges to the phrases #} + {%- if phrases | length > 0 %} + {%- set word_for_and = ' ' if short else ' %s ' % translate('and', language=language) %} + {{- phrases[:-1] | join(', ') ~ word_for_and ~ phrases[-1] if phrases | length > 1 else phrases | first | default }} {%- else %} - {{- _just_time(seconds, language, values, biggest, True) }} + {{- _just_time(seconds, language, values, biggest, True, short, floor) }} {%- endif %} {%- endif %} {%- endmacro %} {# macro to generate a friendly time phrase #} -{%- macro _time(input, attribute, language, values, biggest, utc) %} +{%- macro _time(input, attribute, language, values, biggest, utc, short=False, floor=False) %} {%- set duration_sensor = _check_for_duration_sensor(input) %} {%- if duration_sensor %} {%- set seconds = as_timedelta(duration_sensor).total_seconds() %} - {{- _just_time(seconds, language, values, biggest) }} + {{- _just_time(seconds, language, values, biggest, short=short, floor=floor) }} {%- else %} {%- set uptime = _to_datetime(input, attribute, utc) | as_datetime %} {%- if uptime %} {%- set value = _delta_seconds(now(), uptime) | int %} {%- set seconds = value | abs %} - {{- _just_time(seconds, language, values, biggest) }} + {{- _just_time(seconds, language, values, biggest, short=short, floor=floor) }} {%- else %} {{- _bad_value }} {%- endif %} @@ -1136,52 +1262,52 @@ {%- endmacro -%} {# Returns the most significant time. e.g. 3 hours #} -{%- macro easy_time(uptime, attribute=None, language=default_language, utc=False, max_period='year') %} +{%- macro easy_time(uptime, attribute=None, language=default_language, utc=False, max_period='year', short=False, floor=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} -{{- _time(uptime, attribute, language, values, True, utc) }} +{{- _time(uptime, attribute, language, values, True, utc, short, floor) }} {%- endmacro %} {# Returns a large time phrase without missing any detail. e.g. 3 hours, 4 minutes and 1 second #} -{%- macro big_time(uptime, attribute=None, language=default_language, utc=False, max_period='year') %} +{%- macro big_time(uptime, attribute=None, language=default_language, utc=False, max_period='year', short=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} -{{- _time(uptime, attribute, language, values, False, utc) }} +{{- _time(uptime, attribute, language, values, False, utc, short) }} {%- endmacro %} {# Returns a time phrase with only the details you care about most of the time. e.g. 3 hours and 4 minutes #} -{%- macro custom_time(uptime, values='', language=default_language, utc=False) %} +{%- macro custom_time(uptime, values='', language=default_language, utc=False, short=False) %} {%- set args = values.replace(' ','').split(',') | list if values is string else [] %} {%- if args %} - {{- _time(uptime, None, language, args, False, utc) }} + {{- _time(uptime, None, language, args, False, utc, short) }} {%- else %} - {{- _time(uptime, attribute, language, _default_values, False, utc) }} + {{- _time(uptime, attribute, language, _default_values, False, utc, short) }} {%- endif %} {%- endmacro %} -{%- macro custom_time_attr(uptime, attribute, values='', language=default_language, utc=False) %} +{%- macro custom_time_attr(uptime, attribute, values='', language=default_language, utc=False, short=False) %} {%- set args = values.replace(' ','').split(',') | list if values is string else [] %} {%- if args %} - {{- _time(uptime, attribute, language, args, False, utc) }} + {{- _time(uptime, attribute, language, args, False, utc, short) }} {%- else %} - {{- _time(uptime, attribute, language, _default_values, False, utc) }} + {{- _time(uptime, attribute, language, _default_values, False, utc, short) }} {%- endif %} {%- endmacro %} -{%- macro easy_time_between(t1, t2, attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year') %} +{%- macro easy_time_between(t1, t2, attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year', short=False, floor=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} {%- set seconds = _time_between(_delta_seconds, t1, attr1, utc1, t2, attr2, utc2) | float | abs %} -{{- _just_time(seconds, language, values, True) }} +{{- _just_time(seconds, language, values, True, short=short, floor=floor) }} {%- endmacro %} -{%- macro big_time_between(t1, t2, attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year') %} +{%- macro big_time_between(t1, t2, attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year', short=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} {%- set seconds = _time_between(_delta_seconds, t1, attr1, utc1, t2, attr2, utc2) | float | abs %} -{{- _just_time(seconds, language, values, False) }} +{{- _just_time(seconds, language, values, False, short=short) }} {%- endmacro %} -{%- macro custom_time_between(t1, t2, values='', attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year') %} +{%- macro custom_time_between(t1, t2, values='', attr1=None, attr2=None, language=default_language, utc1=False, utc2=False, max_period='year', short=False) %} {%- set values = values.replace(' ','').split(',') | list if values is string else [] %} {%- set seconds = _time_between(_delta_seconds, t1, attr1, utc1, t2, attr2, utc2) | float | abs %} -{{- _just_time(seconds, language, values, False) }} +{{- _just_time(seconds, language, values, False, short=short) }} {%- endmacro %} {%- macro time_between(t1, t2, attr1=None, attr2=None, utc1=False, utc2=False) %} @@ -1189,21 +1315,21 @@ {%- endmacro %} {# macro to generate a friendly relative time phrase #} -{%- macro _relative_time(input, attribute, language, values, biggest, utc) %} +{%- macro _relative_time(input, attribute, language, values, biggest, utc, short=False, floor=False) %} {%- set uptime = _to_datetime(input, attribute, utc) | as_datetime %} {%- if uptime %} {%- set value = _delta_seconds(now(), uptime) | int %} {%- set seconds = value | abs %} {%- set future = value / seconds > 0 %} - {%- set items = _just_time(seconds, language, values, biggest) %} + {%- set items = _just_time(seconds, language, values, biggest, short=short, floor=floor) %} {%- if future %} - {{- languages.get(language, {}).get('in', _bad_value) }} {{ items }} + {{- translate('in', language=language) }} {{ items }} {%- else %} - {%- set t = languages.get(language, {}).get('ago', _bad_value) %} + {%- set t = translate('ago', language=language) %} {%- if '%s' in t %} {{ t % items }} {%- else %} - {{- items }} {{ languages.get(language, {}).get('ago', _bad_value) }} + {{- items }} {{ translate('ago', language=language) }} {%- endif %} {%- endif %} {%- else %} @@ -1212,33 +1338,33 @@ {%- endmacro %} {# Returns the most significant time. e.g. in 3 hours #} -{%- macro easy_relative_time(uptime, attribute=None, language=default_language, utc=False, max_period='year') %} +{%- macro easy_relative_time(uptime, attribute=None, language=None, utc=False, max_period='year', short=False, floor=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} -{{- _relative_time(uptime, attribute, language, values, True, utc) }} +{{- _relative_time(uptime, attribute, language, values, True, utc, short, floor) }} {%- endmacro %} {# Returns a large time phrase without missing any detail. e.g. in 3 hours, 4 minutes and 1 second #} -{%- macro big_relative_time(uptime, attribute=None, language=default_language, utc=False, max_period='year') %} +{%- macro big_relative_time(uptime, attribute=None, language=None, utc=False, max_period='year', short=False) %} {%- set values = _default_values[_default_values.index(max_period):] if max_period in _default_values else _default_values %} -{{- _relative_time(uptime, attribute, language, values, False, utc) }} +{{- _relative_time(uptime, attribute, language, values, False, utc, short) }} {%- endmacro %} {# Returns a time phrase with only the details you care about most of the time. e.g. in 3 hours and 4 minutes #} -{%- macro custom_relative_time(uptime, values='', language=default_language, utc=False) %} +{%- macro custom_relative_time(uptime, values='', language=None, utc=False, short=False) %} {%- set args = values.replace(' ','').split(',') | list if values is string else [] %} {%- if args %} - {{- _relative_time(uptime, None, language, args, False, utc) }} + {{- _relative_time(uptime, None, language, args, False, utc, short) }} {%- else %} - {{- _relative_time(uptime, attribute, language, _default_values, False, utc) }} + {{- _relative_time(uptime, attribute, language, _default_values, False, utc, short) }} {%- endif %} {%- endmacro %} -{%- macro custom_relative_time_attr(uptime, attribute, values='', language=default_language, utc=False) %} +{%- macro custom_relative_time_attr(uptime, attribute, values='', language=None, utc=False, short=False) %} {%- set args = values.replace(' ','').split(',') | list if values is string else [] %} {%- if args %} - {{- _relative_time(uptime, attribute, language, args, False, utc) }} + {{- _relative_time(uptime, attribute, language, args, False, utc, short) }} {%- else %} - {{- _relative_time(uptime, attribute, language, _default_values, False, utc) }} + {{- _relative_time(uptime, attribute, language, _default_values, False, utc, short) }} {%- endif %} {%- endmacro %} @@ -1369,13 +1495,13 @@ {%- endmacro %} {# What will happen next dst? #} -{% macro next_dst_phrase(language=default_language) %} +{% macro next_dst_phrase(language=None) %} {%- set t = now().replace(hour=0, minute=0, second=0, microsecond=0) %} {%- set delta = _find_delta(t, 'days', 365) | int %} {%- if delta > 0 %} - {{- languages.get(language, {}).get('lose', _bad_value) }} {{ easy_time(delta | abs) }} + {{- translate('lose', language=language) }} {{ easy_time_between(0, delta | abs) }} {%- else %} - {{- languages.get(language, {}).get('gain', _bad_value) }} {{ easy_time(delta | abs) }} + {{- translate('gain', language=language) }} {{ easy_time_between(0, delta | abs) }} {%- endif %} {%- endmacro %} @@ -1385,7 +1511,7 @@ {{- (next - today_at()).days if next is not none else 0 }} {%- endmacro %} -{%- macro clock(fmat=None, language=default_language) %} +{%- macro clock(fmat=None, language=None) %} {{- now().strftime(_get_language_time_format(fmat, language)) }} {%- endmacro %} @@ -1401,31 +1527,41 @@ {%- endif -%} {%- endmacro -%} -{%- macro month(month=None, language=default_language) %} -{%- set idx = (month - 1) % 12 if month is integer and month > 0 else now().month - 1 %} -{{- languages.get(language, {}).get('months', [_bad_value]*12)[idx] }} +{%- macro month(month=None, language=None) %} +{%- if month is datetime %} +{%- set idx = month.month - 1 %} +{%- elif month is integer and month > 0 %} +{%- set idx = (month - 1) % 12 %} +{%- else %} +{%- set idx = now().month - 1 %} +{%- endif %} +{{- translate('months', index=idx, language=language) }} {%- endmacro %} -{%- macro weekday(weekday=None, language=default_language) %} -{%- set idx = (weekday - 1) % 7 if weekday is integer and weekday > 0 else now().weekday() %} -{{- languages.get(language, {}).get('days', [_bad_value]*7)[idx] }} +{%- macro weekday(weekday=None, language=None) %} +{%- if weekday is datetime %} +{%- set idx = weekday.weekday() %} +{%- elif weekday is integer and weekday > 0 %} +{%- set idx = (weekday - 1) % 7 %} +{%- else %} +{%- set idx = now().weekday() %} +{%- endif %} +{{- translate('days', index=idx, language=language) }} {%- endmacro %} {%- macro count_the_days(input, attr, utc=False) %} {%- set input = _to_datetime(input, attr, utc) | as_datetime %} {%- set midnight = today_at() %} -{{ (input - midnight).days }} +{{- (input - midnight).days }} {%- endmacro %} -{%- macro speak_the_days(input, attr, language=default_language, utc=False) %} -{%- set lang_fmat = languages.get(language, {}).get('delta', {}) %} -{%- set _days = {'-1': lang_fmat.get('yesterday', _bad_value), '0': lang_fmat.get('today', _bad_value), '1': lang_fmat.get('tomorrow', _bad_value)} %} +{%- macro speak_the_days(input, attr, language=None, utc=False) %} +{%- set _days = {-1: translate('delta', 'yesterday', language=language), 0: translate('delta', 'today', language=language), 1: translate('delta', 'tomorrow', language=language)} %} {%- set midnight = today_at() %} {%- set ns = namespace(days=[]) %} {%- for i in range(-7, 14) %} - {%- set strindex = i | string %} - {%- set prefix = lang_fmat.get('last', _bad_value) ~ ' ' if i < -1 else lang_fmat.get('next', _bad_value) ~ ' ' if i > 6 else '' %} - {%- set ns.days = ns.days + [ (strindex, prefix ~ _days.get(strindex, weekday(midnight.weekday() + i + 1, language))) ] %} + {%- set prefix = translate('delta', 'last', language=language) ~ ' ' if i < -1 else translate('delta', 'next', language=language) ~ ' ' if i > 6 else '' %} + {%- set ns.days = ns.days + [ (i | string, prefix ~ _days.get(i, weekday(midnight.weekday() + i + 1, language))) ] %} {%- endfor %} {%- set collection = dict.from_keys(ns.days) %} {%- set days = count_the_days(input, attr, utc) %} @@ -1433,16 +1569,64 @@ {{- collection.get(days) }} {%- else %} {%- set days = days | int %} - {%- set ret = _phrase('day', days | abs * 86400, language, 'day', True) %} + {%- set ret = _phrase('day', days | abs * 86400, language, True, True) %} {%- if days > 0 %} - {{- languages.get(language, {}).get('in', _bad_value) }} {{ ret }} + {{- translate('in', language=language) }} {{ ret }} {%- else %} - {%- set t = languages.get(language, {}).get('ago', _bad_value) %} + {%- set t = translate('ago', language=language) %} {%- if '%s' in t %} {{- t % ret }} {%- else %} - {{- ret }} {{ languages.get(language, {}).get('ago', _bad_value) }} + {{- ret }} {{ translate('ago', language=language) }} {%- endif %} {%- endif %} {%- endif %} {%- endmacro %} + +{%- macro hour(hour, language=None) %} +{%- if hour is datetime %} + {%- set hour = hour.hour %} +{%- endif %} +{%- set _12 = not (hour % 12) %} +{%- set _24 = not (hour % 24) %} +{%- set _12hr = translate('time','format') == '12-hr' %} +{%- if _12 and _24 and _12hr %} + {{- translate('time_of_day', 'midnight', language=language) }} +{%- elif _12 and _12hr %} + {{- translate('time_of_day', 'noon', language=language) }} +{%- else %} + {{- hour % 12 if _12hr else hour }} +{%- endif %} +{%- endmacro %} + +{%- macro clock_phrase(input=None, attr=None, utc=False, language=None) %} +{%- if input is none %} + {%- set dt = now() %} +{%- elif input is datetime %} + {%- set dt = input %} +{%- else %} + {%- set dt = _to_datetime(input, attr, utc) | as_datetime %} +{%- endif %} +{%- set this_hour = dt.hour %} +{%- set this_minute = dt.minute %} +{%- if this_minute > 30 %} + {%- set hour_phrase = hour(this_hour + 1, language=language) %} + {%- set minute_calc = 60 - this_minute %} + {%- set minute_phrase = _phrase('minute', 60 * minute_calc, language, True, True) if this_minute % 5 else minute_calc | string %} +{%- else %} + {%- set hour_phrase = hour(this_hour, language=language) %} + {%- set minute_phrase = _phrase('minute', 60 * this_minute, language, True, True) if this_minute % 5 else this_minute | string %} +{%- endif %} +{%- if this_minute in [0, 1, 15, 30, 45, 59] %} + {%- if hour_phrase in ['noon', 'midnight'] and this_minute == 0 %} + {%- set fmat = '{hour}' %} + {%- else %} + {%- set fmat = translate('time_of_hour', this_minute, language=language) %} + {%- endif %} +{%- elif this_minute > 30 %} + {%- set fmat = translate('time_of_hour', 'to_hour', language=language) %} +{%- else %} + {%- set fmat = translate('time_of_hour', 'past_hour', language=language) %} +{%- endif %} +{{- fmat.format(hour=hour_phrase, minute=minute_phrase) -}} +{%- endmacro %} diff --git a/custom_templates/relative_time_plus.jinja b/custom_templates/relative_time_plus.jinja index 7262237..7f1f084 100644 --- a/custom_templates/relative_time_plus.jinja +++ b/custom_templates/relative_time_plus.jinja @@ -1,9 +1,9 @@ {# - set phrases to be used in the relative_time_period macro - one list item per language, each time fraction contains a list with the singular, plural and abbriviated phrase + set phrases to be used in the relative_time_period macro + one list item per language, each time fraction contains a list with the singular, plural and abbriviated phrase combine contains the text to combine the last time fraction, and error the text to display on wrong date input #} -{%- set time_period_phrases = [ +{%- set _time_period_phrases = [ { 'language': 'en', 'phrases': @@ -15,7 +15,8 @@ 'hour': ['hour', 'hours', 'hr'], 'minute': ['minute', 'minutes', 'min'], 'second': ['second', 'seconds', 'sec'], - 'combine': ' and ', + 'millisecond': ['millisecond', 'milliseconds', 'ms'], + 'combine': 'and', 'error': 'Invalid date' } }, @@ -30,7 +31,8 @@ 'hour': ['godzina', 'godzin', 'godz'], 'minute': ['minuta', 'minut', 'min'], 'second': ['sekunda', 'sekund', 'sek'], - 'combine': ' i ', + 'millisecond': ['milisekunda', 'milisekund', 'ms'], + 'combine': 'i', 'error': 'Niepoprawna data' } }, @@ -45,7 +47,8 @@ 'hour': ['heure', 'heures', 'h'], 'minute': ['minute', 'minutes', 'min'], 'second': ['seconde', 'secondes', 'sec'], - 'combine': ' et ', + 'millisecond': ['milliseconde', 'millisecondes', 'ms'], + 'combine': 'et', 'error': 'Date non valide' } }, @@ -60,7 +63,8 @@ 'hour': ['ora', 'ore', 'h'], 'minute': ['minuto', 'minuti', 'min'], 'second': ['secondo', 'secondi', 'sec'], - 'combine': ' e ', + 'millisecond': ['millisecondo', 'millisecondi', 'ms'], + 'combine': 'e', 'error': 'Data non valida' } }, @@ -75,7 +79,8 @@ 'hour': ['uur', 'uur', 'u'], 'minute': ['minuut', 'minuten', 'min'], 'second': ['seconde', 'seconden', 'sec'], - 'combine': ' en ', + 'millisecond': ['milliseconde', 'milliseconden', 'ms'], + 'combine': 'en', 'error': 'Ongeldige datum' } }, @@ -90,7 +95,8 @@ 'hour': ['Stunde', 'Stunden', 'Std.'], 'minute': ['Minute', 'Minuten', 'Min.'], 'second': ['Sekunde', 'Sekunden', 'Sek.'], - 'combine': ' und ', + 'millisecond': ['Milliseconde', 'Milliseconden', 'ms'], + 'combine': 'und', 'error': 'Falsches Datum' } }, @@ -105,7 +111,8 @@ 'hour': ['hora', 'horas', 'h'], 'minute': ['minuto', 'minutos', 'min'], 'second': ['segundo', 'segundos', 'seg'], - 'combine': ' e ', + 'millisecond': ['millissegundo', 'millissegundos', 'ms'], + 'combine': 'e', 'error': 'Data Inválida' } }, @@ -120,7 +127,8 @@ 'hour': ['time', 'timer', 't.'], 'minute': ['minut', 'minuter', 'min.'], 'second': ['sekund', 'sekunder', 'sek.'], - 'combine': ' og ', + 'millisecond': ['millisekund', 'millisekunder', 'ms.'], + 'combine': 'og', 'error': 'Ugyldig dato' } } @@ -131,87 +139,108 @@ macro to split a timedelta in years, months, weeks, days, hours, minutes, seconds used by the relative time plus macro, set up as a seperate macro so it can be reused #} -{%- macro time_split(date, time, compare_date) -%} +{%- macro time_split(date, compare_date=now(), time=true, not_use=[]) -%} {# set defaults for variables #} - {%- set date = date | as_local -%} - {%- set time = time | default(true) | bool(true) -%} - {%- set n = compare_date if compare_date is defined else now() -%} - {%- set n = n if time else today_at() -%} - {%- set a = [n, date] | max -%} - {%- set b = [n, date] | min -%} + {%- set date = date | as_local if time else date.date()-%} + {%- set time = time | bool(true) -%} + {%- set comp_date = compare_date if time else compare_date.date() -%} + {%- set date_max = [comp_date, date] | max -%} + {%- set date_min = [comp_date, date] | min -%} {#- set time periods in seconds #} {%- set m, h, d, w = 60, 3600, 86400, 604800 -%} - {#- set numer of years, and set n to value using this number of years #} - {%- set yrs = a.year - b.year - (1 if a.replace(year=b.year) < b else 0) -%} - {%- set a = a.replace(year=a.year - yrs) -%} - {#- set numer of months, and set n to value using this number of months #} - {%- set mth = (a.month - b.month - (1 if a.day < b.day else 0) + 12) % 12 -%} - {%- set month_new = (((a.month - mth) + 12) % 12) | default(12, true) -%} - {%- set day_max = ((a.replace(day=1, month=month_new) + timedelta(days=31)).replace(day=1) - timedelta(days=1)).day -%} - {%- set a_temp = a.replace(month=month_new, day=[a.day, day_max]|min) -%} - {%- set a = a_temp if a_temp <= a else a_temp.replace(year=a.year-1) -%} + {#- set numer of years, and set lowest date using this number of years #} + {%- set yrs = date_max.year - date_min.year - (1 if date_max.replace(year=date_min.year) < date_min else 0) -%} + {%- set date_max = date_max.replace(year=date_max.year - yrs) -%} + {#- set numer of months, and set lowest date using this number of months #} + {%- if 'month' not in not_use -%} + {%- set mth = (date_max.month - date_min.month - (1 if date_max.day < date_min.day else 0) + 12) % 12 -%} + {%- set month_new = (((date_max.month - mth) + 12) % 12) | default(12, true) -%} + {%- set day_max = ((date_max.replace(day=1, month=month_new) + timedelta(days=31)).replace(day=1) - timedelta(days=1)).day -%} + {%- set extra_days = [0, date_max.day - day_max] | max -%} + {%- set date_temp = date_max.replace(month=month_new, day=[date_max.day, day_max]|min) -%} + {%- set date_max = date_temp if date_temp <= date_max else date_temp.replace(year=date_max.year-1) -%} + {%- set mth = mth + yrs * 12 if 'year' in not_use else mth -%} + {%- endif -%} + {%- set date_max = date_max.replace(year=date_max.year + yrs) if 'year' in not_use and 'month' in not_use else date_max -%} + {%- set yrs = 0 if 'year' in not_use else yrs -%} {#- set other time period variables #} - {%- set s = (a - b).total_seconds() -%} - {%- set wks = (s // w) | int -%} - {%- set day = ((s - wks * w) // d) | int -%} - {%- set hrs = ((s - wks * w - day * d) // h) | int -%} - {%- set min = ((s - wks * w - day * d - hrs * h) // m) | int -%} - {%- set sec = (s - wks * w - day * d - hrs * h - min * m) | int -%} + {%- set s = (date_max - date_min).total_seconds() + extra_days | default(0) * 86400 -%} + {%- set wks = 0 if 'week' in not_use else (s // w) | int -%} + {%- set day = 0 if 'day' in not_use else ((s - wks * w) // d) | int -%} + {%- set hrs = 0 if 'hour' in not_use else ((s - wks * w - day * d) // h) | int -%} + {%- set min = 0 if 'minute' in not_use else ((s - wks * w - day * d - hrs * h) // m) | int -%} + {%- set sec = 0 if 'second' in not_use else (s - wks * w - day * d - hrs * h - min * m) | int -%} + {%- set ms = (s % 1 * 1000) | round | int -%} {# output result #} - {{- dict(y=yrs, mo=mth, w=wks, d=day, h=hrs, m=min, s=sec) | to_json -}} + {%- set output = dict(year=yrs, month=mth | default(0), week=wks, day=day, hour=hrs, minute=min, second=sec, millisecond=ms) %} + {{- dict(output.items() | rejectattr('0', 'in', not_use)) | to_json -}} {%- endmacro -%} {# macro to output a timedelta in a readable format #} -{%- macro relative_time_plus(date, parts, week, time, abbr, language, compare_date, verbose) -%} +{%- macro relative_time_plus(date, parts=1, abbr=false, verbose=false, language='en', compare_date=now(), month=none, week=none, millisecond=none, not_use=['millisecond'], always_show=[], time=true) -%} {#- set defaults for input if not entered #} - {%- set date = date | as_datetime if date is string or date is number else date -%} - {%- set compare_date = compare_date if compare_date is defined else now() -%} - {%- set compare_date = compare_date | as_datetime if compare_date is string or compare_date is number else compare_date -%} - {%- set phrases = time_period_phrases -%} + {%- set date = date if date is datetime else date | as_datetime -%} + {%- set compare_date = compare_date if compare_date is datetime else compare_date | as_datetime -%} {#- select correct phrases bases on language input #} - {%- set language = language | default() -%} + {%- set phrases = _time_period_phrases -%} {%- set languages = phrases | map(attribute='language') | list -%} - {%- set language = iif(language in languages, language, languages | first) -%} + {%- set language = iif(language in languages, language, 'en') -%} {%- set phr = phrases | selectattr('language', 'eq', language) | map(attribute='phrases') | list | first -%} - {#- check for valid datetime (using as_timestamp) #} - {%- if as_timestamp(date, default='error') != 'error' -%} - {%- set date = date | as_local -%} - {%- set parts = parts | default(1) | int(1) -%} - {%- set week = week | default(true) | bool(true) -%} - {%- set time = time | default(true) | bool(true) -%} - {%- set abbr = abbr | default(false) | bool(false) or verbose | default(false) | bool(false) -%} - {%- set language = language | default('first') -%} - {%- set date = date if time else today_at().replace(year=date.year, month=date.month, day=date.day) -%} - {%- set tp = time_split(date, time, compare_date) | from_json -%} - {#- create mapping #} - {%- set wk = tp.w if week else 0 -%} - {%- set dy = tp.d if week else tp.d + tp.w * 7 -%} - {%- set dur = dict( - yrs = dict(a=tp.y, d=phr.year[2] if abbr else phr.year[1] if tp.y > 1 else phr.year[0]), - mth = dict(a=tp.mo, d=phr.month[2] if abbr else phr.month[1] if tp.mo > 1 else phr.month[0]), - wks = dict(a=wk, d=phr.week[2] if abbr else phr.week[1] if wk > 1 else phr.week[0]), - day = dict(a=dy, d=phr.day[2] if abbr else phr.day[1] if dy > 1 else phr.day[0]), - hrs = dict(a=tp.h, d=phr.hour[2] if abbr else phr.hour[1] if tp.h > 1 else phr.hour[0]), - min = dict(a=tp.m, d=phr.minute[2] if abbr else phr.minute[1] if tp.m > 1 else phr.minute[0]), - sec = dict(a=tp.s, d=phr.second[2] if abbr else phr.second[1] if tp.s > 1 else phr.second[0]) - ) - -%} + {#- perform smart stuff #} + {%- if date is datetime and compare_date is datetime -%} + {# determine not_use list #} + {%- set abbr_to_full = dict(yr='year', mth='month', wk='week', hr='hour', min='minute', sec='second', ms='millisecond') -%} + {%- set add = [('month', month),('week',week),('millisecond',millisecond)] | selectattr('1', 'eq', false) | map(attribute='0') | list -%} + {%- set not_use = not_use if not_use is list else (not_use | replace(' ', '')).split(',') -%} + {%- set not_use = (not_use + add) | unique | list -%} + {%- if not_use | select('in', abbr_to_full) | list | count > 0 -%} + {%- set ns = namespace(not_use=[]) -%} + {%- for i in not_use -%} + {%- set ns.not_use = ns.not_use + [abbr_to_full[i] | default(i)] -%} + {%- endfor -%} + {%- set not_use = ns.not_use | unique | list -%} + {%- endif -%} + {# set variables #} + {%- set date, compare_date = date | as_local, compare_date | as_local -%} + {%- set parts = parts | int(1) -%} + {%- set time = time | bool(true) -%} + {%- set abbr = abbr | bool(false) or verbose | bool(false) -%} + {# split timedelta #} + {%- set time_parts = time_split(date, compare_date, time, not_use) | from_json -%} {#- find first non zero time period #} - {%- set first = dur.items() | rejectattr('1.a', 'eq', 0) | map(attribute='0') | first -%} - {#- set variable to reject weeks if set and find index of first non zero time period #} - {%- set week_reject = 'wks' if not week -%} - {%- set index = (dur.keys() | reject('eq', week_reject) | list).index(first) -%} - {#-select non zero items based on input #} - {%- set items = (dur.keys() | reject('eq', week_reject) | list)[index:index + parts] -%} - {%- set selection = dur.items() | selectattr('0', 'in', items) | rejectattr('1.a', 'eq', 0) | list -%} - {#- create list of texts per selected time period #} - {%- set ns = namespace(text = []) -%} - {%- for i in selection -%} - {%- set ns.text = ns.text + [ i[1].a ~ ' ' ~ i[1].d] -%} - {%- endfor -%} - {#- join texts in a string, using phr.combine for the last item #} - {{- ns.text[:-1] | join(', ') ~ phr.combine ~ ns.text[-1] if ns.text | count > 1 else ns.text | first -}} + {%- set time_periods = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'] -%} + {%- set do_use = time_periods | reject('in', not_use) | list -%} + {# continue if there are still time periods to use #} + {%- if do_use | count > 0 -%} + {%- set always_return = do_use | last -%} + {%- set always_show = always_show if always_show is list else (always_show | replace(' ', '')).split(',') -%} + {%- if always_show | select('in', abbr_to_full) | list | count > 0 -%} + {%- set ns = namespace(always_show=[]) -%} + {%- for i in always_show -%} + {%- set ns.always_show = ns.always_show + [abbr_to_full[i] | default(i)] -%} + {%- endfor -%} + {%- set always_show = ns.always_show | unique | list -%} + {%- endif -%} + {%- set parts = [parts, always_show | count] | max -%} + {%- set to_show = (time_parts.items() | selectattr('1') | map(attribute='0') | list + always_show) | unique | list | default([always_return], true) -%} + {%- set first = do_use | select('in', to_show) | first -%} + {#-select itemw to show based on input #} + {%- set index_first = (time_parts.keys() | list).index(first) -%} + {%- set items = (time_parts.keys() | list)[index_first:index_first + parts] -%} + {# convert to phrases #} + {%- set ns = namespace(phrases=[]) -%} + {%- for i in items if i in to_show or i == first -%} + {%- set phr_abbr = phr[i][2] -%} + {%- set phr_verb = phr[i][1] if time_parts[i] != 1 else phr[i][0] -%} + {%- set phrase = '{} {}'.format(time_parts[i], phr_abbr if abbr else phr_verb) -%} + {%- set ns.phrases = ns.phrases + [phrase] -%} + {%- endfor -%} + {#- join phrases in a string, using phr.combine for the last item #} + {{- '{} {} {}'.format(ns.phrases[:-1] | join(', '), phr.combine, ns.phrases[-1]) if ns.phrases | count > 1 else ns.phrases | first -}} + {%- else -%} + All time periods are excluded + {%- endif -%} {%- else -%} {{- phr.error -}} {%- endif -%} -{%- endmacro -%} +{%- endmacro -%} \ No newline at end of file