Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pendulum/formatting/difference_formatter.py: 10%
84 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:11 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-30 06:11 +0000
1from __future__ import annotations
3import typing as t
5from pendulum.locales.locale import Locale
8if t.TYPE_CHECKING:
9 from pendulum import Duration
12class DifferenceFormatter:
13 """
14 Handles formatting differences in text.
15 """
17 def __init__(self, locale: str = "en") -> None:
18 self._locale = Locale.load(locale)
20 def format(
21 self,
22 diff: Duration,
23 is_now: bool = True,
24 absolute: bool = False,
25 locale: str | Locale | None = None,
26 ) -> str:
27 """
28 Formats a difference.
30 :param diff: The difference to format
31 :param is_now: Whether the difference includes now
32 :param absolute: Whether it's an absolute difference or not
33 :param locale: The locale to use
34 """
35 locale = self._locale if locale is None else Locale.load(locale)
37 if diff.years > 0:
38 unit = "year"
39 count = diff.years
41 if diff.months > 6:
42 count += 1
43 elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
44 unit = "year"
45 count = 1
46 elif diff.months > 0:
47 unit = "month"
48 count = diff.months
50 if (diff.weeks * 7 + diff.remaining_days) >= 27:
51 count += 1
52 elif diff.weeks > 0:
53 unit = "week"
54 count = diff.weeks
56 if diff.remaining_days > 3:
57 count += 1
58 elif diff.remaining_days > 0:
59 unit = "day"
60 count = diff.remaining_days
62 if diff.hours >= 22:
63 count += 1
64 elif diff.hours > 0:
65 unit = "hour"
66 count = diff.hours
67 elif diff.minutes > 0:
68 unit = "minute"
69 count = diff.minutes
70 elif 10 < diff.remaining_seconds <= 59:
71 unit = "second"
72 count = diff.remaining_seconds
73 else:
74 # We check if the "a few seconds" unit exists
75 time = locale.get("custom.units.few_second")
76 if time is not None:
77 if absolute:
78 return t.cast(str, time)
80 key = "custom"
81 is_future = diff.invert
82 if is_now:
83 if is_future:
84 key += ".from_now"
85 else:
86 key += ".ago"
87 else:
88 if is_future:
89 key += ".after"
90 else:
91 key += ".before"
93 return t.cast(str, locale.get(key).format(time))
94 else:
95 unit = "second"
96 count = diff.remaining_seconds
98 if count == 0:
99 count = 1
101 if absolute:
102 key = f"translations.units.{unit}"
103 else:
104 is_future = diff.invert
106 if is_now:
107 # Relative to now, so we can use
108 # the CLDR data
109 key = f"translations.relative.{unit}"
111 if is_future:
112 key += ".future"
113 else:
114 key += ".past"
115 else:
116 # Absolute comparison
117 # So we have to use the custom locale data
119 # Checking for special pluralization rules
120 key = "custom.units_relative"
121 if is_future:
122 key += f".{unit}.future"
123 else:
124 key += f".{unit}.past"
126 trans = locale.get(key)
127 if not trans:
128 # No special rule
129 key = f"translations.units.{unit}.{locale.plural(count)}"
130 time = locale.get(key).format(count)
131 else:
132 time = trans[locale.plural(count)].format(count)
134 key = "custom"
135 if is_future:
136 key += ".after"
137 else:
138 key += ".before"
140 return t.cast(str, locale.get(key).format(time))
142 key += f".{locale.plural(count)}"
144 return t.cast(str, locale.get(key).format(count))