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

1from __future__ import annotations 

2 

3import typing as t 

4 

5from pendulum.locales.locale import Locale 

6 

7 

8if t.TYPE_CHECKING: 

9 from pendulum import Duration 

10 

11 

12class DifferenceFormatter: 

13 """ 

14 Handles formatting differences in text. 

15 """ 

16 

17 def __init__(self, locale: str = "en") -> None: 

18 self._locale = Locale.load(locale) 

19 

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. 

29 

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) 

36 

37 if diff.years > 0: 

38 unit = "year" 

39 count = diff.years 

40 

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 

49 

50 if (diff.weeks * 7 + diff.remaining_days) >= 27: 

51 count += 1 

52 elif diff.weeks > 0: 

53 unit = "week" 

54 count = diff.weeks 

55 

56 if diff.remaining_days > 3: 

57 count += 1 

58 elif diff.remaining_days > 0: 

59 unit = "day" 

60 count = diff.remaining_days 

61 

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) 

79 

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" 

92 

93 return t.cast(str, locale.get(key).format(time)) 

94 else: 

95 unit = "second" 

96 count = diff.remaining_seconds 

97 

98 if count == 0: 

99 count = 1 

100 

101 if absolute: 

102 key = f"translations.units.{unit}" 

103 else: 

104 is_future = diff.invert 

105 

106 if is_now: 

107 # Relative to now, so we can use 

108 # the CLDR data 

109 key = f"translations.relative.{unit}" 

110 

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 

118 

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" 

125 

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) 

133 

134 key = "custom" 

135 if is_future: 

136 key += ".after" 

137 else: 

138 key += ".before" 

139 

140 return t.cast(str, locale.get(key).format(time)) 

141 

142 key += f".{locale.plural(count)}" 

143 

144 return t.cast(str, locale.get(key).format(count))