From a142afd76dfb18dc134fd11caedc790b18c6a2aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Setni=C4=8Dka?= <setnicka@seznam.cz>
Date: Sat, 9 Jan 2021 03:53:45 +0100
Subject: [PATCH] =?UTF-8?q?Pomocn=C3=A9=20form=C3=A1tovac=C3=AD=20funkce?=
 =?UTF-8?q?=20v=20mo.util=5Fformat=20a=20jejich=20registrace=20jako=20jinj?=
 =?UTF-8?q?a=20filtery?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Funkce timedelta pro vyrábění řetězců styl "za 3 minuty"
* Funkce time_and_timedelta vyrábějící řetězce
  "2020-01-09 12:00 (za 2 hodiny)"
* Přesun funkcí timeformat a inflect_number z mo.web
---
 mo/util_format.py  | 80 ++++++++++++++++++++++++++++++++++++++++++++++
 mo/web/__init__.py | 24 +++-----------
 2 files changed, 85 insertions(+), 19 deletions(-)
 create mode 100644 mo/util_format.py

diff --git a/mo/util_format.py b/mo/util_format.py
new file mode 100644
index 00000000..18e01ee0
--- /dev/null
+++ b/mo/util_format.py
@@ -0,0 +1,80 @@
+# Utils that do not depend on any other in mo (to avoid circular dependency)
+
+from datetime import datetime
+from typing import Optional
+
+import mo
+
+
+def inflect_number(n: int, w1: str, w234: str, wother: str, unitprefix: str = '') -> str:
+    if n == 1:
+        return f'{n} {unitprefix}{w1}'
+    elif 2 <= n <= 4:
+        return f'{n} {unitprefix}{w234}'
+    else:
+        return f'{n} {unitprefix}{wother}'
+
+
+def timeformat(dt: datetime) -> str:
+    if dt is None:
+        return '–'
+    else:
+        return dt.astimezone().strftime("%Y-%m-%d %H:%M")
+
+
+def timedelta(d: datetime, ref: Optional[datetime] = None, descriptive: bool = False) -> str:
+    """Vyrábí česky formátované řetězece 'za 3 minuty', 'před 27 dny' a podobně
+    z rozdílu daného datetime a referenčního času (například now).
+    Pokud se předá `descriptive=True`, tak vyrábí "deskriptivní" popis
+    ve stylu '3 minuty po', '27 dní před' a podobně.
+    """
+    if ref is None:
+        ref = mo.now
+    (prefix, suffix) = ("", "")
+    if ref > d:
+        delta = ref - d
+        if descriptive:
+            suffix = " před"
+        else:
+            prefix = "před "
+        before = True
+    else:
+        delta = d - ref
+        if descriptive:
+            suffix = " po"
+        else:
+            prefix = "za "
+        before = False
+
+    if delta.days > 0:
+        unitprefix = ''
+        if before:
+            value = inflect_number(delta.days, 'den' if descriptive else 'dnem', 'dny', 'dny')
+        else:
+            value = inflect_number(delta.days, 'den', 'dny', 'dní')
+    else:
+        if delta.seconds > 3600:
+            unitprefix = 'hodin'
+            number = delta.seconds // 3600
+        elif delta.seconds > 60:
+            unitprefix = 'minut'
+            number = delta.seconds // 60
+        else:
+            unitprefix = 'sekund'
+            number = delta.seconds
+
+        if before:
+            # 1 minuta před, 3 minuty před, 5 minut před / před 1 minutou, před 3 minutami, před 5 minutami
+            if descriptive:
+                value = inflect_number(number, 'a', 'y', '', unitprefix=unitprefix)
+            else:
+                value = inflect_number(number, 'ou', 'ami', 'ami', unitprefix=unitprefix),
+        else:
+            # 1 minuta po, 3 minuty po, 5 minut po / za 1 minutu, za 3 minuty, za 5 minut
+            value = inflect_number(number, 'a' if descriptive else 'u', 'y', '', unitprefix=unitprefix)
+
+    return f"{prefix}{value}{suffix}"
+
+
+def time_and_timedelta(d: datetime, ref: Optional[datetime] = None):
+    return f"{timeformat(d)} ({timedelta(d, ref)})"
diff --git a/mo/web/__init__.py b/mo/web/__init__.py
index df78cc1e..549991a5 100644
--- a/mo/web/__init__.py
+++ b/mo/web/__init__.py
@@ -1,4 +1,5 @@
 import datetime
+from mo import util_format
 import dateutil.tz
 from flask import Flask, request, g, session
 import flask.logging
@@ -32,27 +33,12 @@ logger.addHandler(flask.logging.default_handler)
 # Budeme používat české locale
 locale.setlocale(locale.LC_COLLATE, 'cs_CZ.UTF-8')
 
-
 # Naše filtry pro Jinju
 
-def filter_timeformat(dt: datetime.datetime) -> str:
-    if dt is None:
-        return '–'
-    else:
-        return dt.astimezone().strftime("%Y-%m-%d %H:%M")
-
-
-def filter_inflected(n: int, w1: str, w234: str, wother: str) -> str:
-    if n == 1:
-        return f'{n} {w1}'
-    elif 2 <= n <= 4:
-        return f'{n} {w234}'
-    else:
-        return f'{n} {wother}'
-
-
-app.jinja_env.filters['timeformat'] = filter_timeformat
-app.jinja_env.filters['inflected'] = filter_inflected
+app.jinja_env.filters.update(timeformat=util_format.timeformat)
+app.jinja_env.filters.update(inflected=util_format.inflect_number)
+app.jinja_env.filters.update(timedelta=util_format.timedelta)
+app.jinja_env.filters.update(time_and_timedelta=util_format.time_and_timedelta)
 
 
 # Inicializace požadavků a nucená autorizace
-- 
GitLab