summaryrefslogtreecommitdiffstats
path: root/pendulum/formatting/difference_formatter.py
diff options
context:
space:
mode:
Diffstat (limited to 'pendulum/formatting/difference_formatter.py')
-rw-r--r--pendulum/formatting/difference_formatter.py299
1 files changed, 146 insertions, 153 deletions
diff --git a/pendulum/formatting/difference_formatter.py b/pendulum/formatting/difference_formatter.py
index 3243089..dad219d 100644
--- a/pendulum/formatting/difference_formatter.py
+++ b/pendulum/formatting/difference_formatter.py
@@ -1,153 +1,146 @@
-import typing
-
-import pendulum
-
-from pendulum.utils._compat import decode
-
-from ..locales.locale import Locale
-
-
-class DifferenceFormatter(object):
- """
- Handles formatting differences in text.
- """
-
- def __init__(self, locale="en"):
- self._locale = Locale.load(locale)
-
- def format(
- self, diff, is_now=True, absolute=False, locale=None
- ): # type: (pendulum.Period, bool, bool, typing.Optional[str]) -> str
- """
- Formats a difference.
-
- :param diff: The difference to format
- :type diff: pendulum.period.Period
-
- :param is_now: Whether the difference includes now
- :type is_now: bool
-
- :param absolute: Whether it's an absolute difference or not
- :type absolute: bool
-
- :param locale: The locale to use
- :type locale: str or None
-
- :rtype: str
- """
- if locale is None:
- locale = self._locale
- else:
- locale = Locale.load(locale)
-
- count = diff.remaining_seconds
-
- if diff.years > 0:
- unit = "year"
- count = diff.years
-
- if diff.months > 6:
- count += 1
- elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
- unit = "year"
- count = 1
- elif diff.months > 0:
- unit = "month"
- count = diff.months
-
- if (diff.weeks * 7 + diff.remaining_days) >= 27:
- count += 1
- elif diff.weeks > 0:
- unit = "week"
- count = diff.weeks
-
- if diff.remaining_days > 3:
- count += 1
- elif diff.remaining_days > 0:
- unit = "day"
- count = diff.remaining_days
-
- if diff.hours >= 22:
- count += 1
- elif diff.hours > 0:
- unit = "hour"
- count = diff.hours
- elif diff.minutes > 0:
- unit = "minute"
- count = diff.minutes
- elif 10 < diff.remaining_seconds <= 59:
- unit = "second"
- count = diff.remaining_seconds
- else:
- # We check if the "a few seconds" unit exists
- time = locale.get("custom.units.few_second")
- if time is not None:
- if absolute:
- return time
-
- key = "custom"
- is_future = diff.invert
- if is_now:
- if is_future:
- key += ".from_now"
- else:
- key += ".ago"
- else:
- if is_future:
- key += ".after"
- else:
- key += ".before"
-
- return locale.get(key).format(time)
- else:
- unit = "second"
- count = diff.remaining_seconds
-
- if count == 0:
- count = 1
-
- if absolute:
- key = "translations.units.{}".format(unit)
- else:
- is_future = diff.invert
-
- if is_now:
- # Relative to now, so we can use
- # the CLDR data
- key = "translations.relative.{}".format(unit)
-
- if is_future:
- key += ".future"
- else:
- key += ".past"
- else:
- # Absolute comparison
- # So we have to use the custom locale data
-
- # Checking for special pluralization rules
- key = "custom.units_relative"
- if is_future:
- key += ".{}.future".format(unit)
- else:
- key += ".{}.past".format(unit)
-
- trans = locale.get(key)
- if not trans:
- # No special rule
- time = locale.get(
- "translations.units.{}.{}".format(unit, locale.plural(count))
- ).format(count)
- else:
- time = trans[locale.plural(count)].format(count)
-
- key = "custom"
- if is_future:
- key += ".after"
- else:
- key += ".before"
-
- return locale.get(key).format(decode(time))
-
- key += ".{}".format(locale.plural(count))
-
- return decode(locale.get(key).format(count))
+from __future__ import annotations
+
+import typing as t
+
+from pendulum.locales.locale import Locale
+
+if t.TYPE_CHECKING:
+ from pendulum import Duration
+
+
+class DifferenceFormatter:
+ """
+ Handles formatting differences in text.
+ """
+
+ def __init__(self, locale: str = "en") -> None:
+ self._locale = Locale.load(locale)
+
+ def format(
+ self,
+ diff: Duration,
+ is_now: bool = True,
+ absolute: bool = False,
+ locale: str | Locale | None = None,
+ ) -> str:
+ """
+ Formats a difference.
+
+ :param diff: The difference to format
+ :param is_now: Whether the difference includes now
+ :param absolute: Whether it's an absolute difference or not
+ :param locale: The locale to use
+ """
+ if locale is None:
+ locale = self._locale
+ else:
+ locale = Locale.load(locale)
+
+ if diff.years > 0:
+ unit = "year"
+ count = diff.years
+
+ if diff.months > 6:
+ count += 1
+ elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
+ unit = "year"
+ count = 1
+ elif diff.months > 0:
+ unit = "month"
+ count = diff.months
+
+ if (diff.weeks * 7 + diff.remaining_days) >= 27:
+ count += 1
+ elif diff.weeks > 0:
+ unit = "week"
+ count = diff.weeks
+
+ if diff.remaining_days > 3:
+ count += 1
+ elif diff.remaining_days > 0:
+ unit = "day"
+ count = diff.remaining_days
+
+ if diff.hours >= 22:
+ count += 1
+ elif diff.hours > 0:
+ unit = "hour"
+ count = diff.hours
+ elif diff.minutes > 0:
+ unit = "minute"
+ count = diff.minutes
+ elif 10 < diff.remaining_seconds <= 59:
+ unit = "second"
+ count = diff.remaining_seconds
+ else:
+ # We check if the "a few seconds" unit exists
+ time = locale.get("custom.units.few_second")
+ if time is not None:
+ if absolute:
+ return t.cast(str, time)
+
+ key = "custom"
+ is_future = diff.invert
+ if is_now:
+ if is_future:
+ key += ".from_now"
+ else:
+ key += ".ago"
+ else:
+ if is_future:
+ key += ".after"
+ else:
+ key += ".before"
+
+ return t.cast(str, locale.get(key).format(time))
+ else:
+ unit = "second"
+ count = diff.remaining_seconds
+
+ if count == 0:
+ count = 1
+
+ if absolute:
+ key = f"translations.units.{unit}"
+ else:
+ is_future = diff.invert
+
+ if is_now:
+ # Relative to now, so we can use
+ # the CLDR data
+ key = f"translations.relative.{unit}"
+
+ if is_future:
+ key += ".future"
+ else:
+ key += ".past"
+ else:
+ # Absolute comparison
+ # So we have to use the custom locale data
+
+ # Checking for special pluralization rules
+ key = "custom.units_relative"
+ if is_future:
+ key += f".{unit}.future"
+ else:
+ key += f".{unit}.past"
+
+ trans = locale.get(key)
+ if not trans:
+ # No special rule
+ key = f"translations.units.{unit}.{locale.plural(count)}"
+ time = locale.get(key).format(count)
+ else:
+ time = trans[locale.plural(count)].format(count)
+
+ key = "custom"
+ if is_future:
+ key += ".after"
+ else:
+ key += ".before"
+
+ return t.cast(str, locale.get(key).format(time))
+
+ key += f".{locale.plural(count)}"
+
+ return t.cast(str, locale.get(key).format(count))