@@ -123,6 +123,7 @@ class Arrow:
123123 ]
124124 _ATTRS_PLURAL : Final [List [str ]] = [f"{ a } s" for a in _ATTRS ]
125125 _MONTHS_PER_QUARTER : Final [int ] = 3
126+ _MONTHS_PER_YEAR : Final [int ] = 12
126127 _SECS_PER_MINUTE : Final [int ] = 60
127128 _SECS_PER_HOUR : Final [int ] = 60 * 60
128129 _SECS_PER_DAY : Final [int ] = 60 * 60 * 24
@@ -1189,6 +1190,7 @@ def humanize(
11891190
11901191 elif diff < self ._SECS_PER_MINUTE * 2 :
11911192 return locale .describe ("minute" , sign , only_distance = only_distance )
1193+
11921194 elif diff < self ._SECS_PER_HOUR :
11931195 minutes = sign * max (delta_second // self ._SECS_PER_MINUTE , 2 )
11941196 return locale .describe (
@@ -1197,36 +1199,54 @@ def humanize(
11971199
11981200 elif diff < self ._SECS_PER_HOUR * 2 :
11991201 return locale .describe ("hour" , sign , only_distance = only_distance )
1202+
12001203 elif diff < self ._SECS_PER_DAY :
12011204 hours = sign * max (delta_second // self ._SECS_PER_HOUR , 2 )
12021205 return locale .describe ("hours" , hours , only_distance = only_distance )
1203- elif diff < self ._SECS_PER_DAY * 2 :
1206+
1207+ calendar_diff = (
1208+ relativedelta (dt , self ._datetime )
1209+ if self ._datetime < dt
1210+ else relativedelta (self ._datetime , dt )
1211+ )
1212+ calendar_months = (
1213+ calendar_diff .years * self ._MONTHS_PER_YEAR + calendar_diff .months
1214+ )
1215+
1216+ # For months, if more than 2 weeks, count as a full month
1217+ if calendar_diff .days > 14 :
1218+ calendar_months += 1
1219+
1220+ calendar_months = min (calendar_months , self ._MONTHS_PER_YEAR )
1221+
1222+ if diff < self ._SECS_PER_DAY * 2 :
12041223 return locale .describe ("day" , sign , only_distance = only_distance )
1224+
12051225 elif diff < self ._SECS_PER_WEEK :
12061226 days = sign * max (delta_second // self ._SECS_PER_DAY , 2 )
12071227 return locale .describe ("days" , days , only_distance = only_distance )
12081228
1229+ elif calendar_months >= 1 and diff < self ._SECS_PER_YEAR :
1230+ if calendar_months == 1 :
1231+ return locale .describe (
1232+ "month" , sign , only_distance = only_distance
1233+ )
1234+ else :
1235+ months = sign * calendar_months
1236+ return locale .describe (
1237+ "months" , months , only_distance = only_distance
1238+ )
1239+
12091240 elif diff < self ._SECS_PER_WEEK * 2 :
12101241 return locale .describe ("week" , sign , only_distance = only_distance )
1242+
12111243 elif diff < self ._SECS_PER_MONTH :
12121244 weeks = sign * max (delta_second // self ._SECS_PER_WEEK , 2 )
12131245 return locale .describe ("weeks" , weeks , only_distance = only_distance )
12141246
1215- elif diff < self ._SECS_PER_MONTH * 2 :
1216- return locale .describe ("month" , sign , only_distance = only_distance )
1217- elif diff < self ._SECS_PER_YEAR :
1218- # TODO revisit for humanization during leap years
1219- self_months = self ._datetime .year * 12 + self ._datetime .month
1220- other_months = dt .year * 12 + dt .month
1221-
1222- months = sign * max (abs (other_months - self_months ), 2 )
1223-
1224- return locale .describe (
1225- "months" , months , only_distance = only_distance
1226- )
1227-
12281247 elif diff < self ._SECS_PER_YEAR * 2 :
12291248 return locale .describe ("year" , sign , only_distance = only_distance )
1249+
12301250 else :
12311251 years = sign * max (delta_second // self ._SECS_PER_YEAR , 2 )
12321252 return locale .describe ("years" , years , only_distance = only_distance )
0 commit comments