@@ -81,7 +81,7 @@ def date_and_delta(value, *, now=None):
8181 return date , abs_timedelta (delta )
8282
8383
84- def naturaldelta (value , months = True , minimum_unit = "seconds" ):
84+ def naturaldelta (value , months = True , minimum_unit = "seconds" , when = None ):
8585 """Return a natural representation of a timedelta or number of seconds.
8686
8787 This is similar to `naturaltime`, but does not add tense to the result.
@@ -91,16 +91,30 @@ def naturaldelta(value, months=True, minimum_unit="seconds"):
9191 months (bool): If `True`, then a number of months (based on 30.5 days) will be
9292 used for fuzziness between years.
9393 minimum_unit (str): The lowest unit that can be used.
94+ when (datetime.timedelta): Point in time relative to which _value_ is
95+ interpreted. Defaults to the current time in the local timezone.
9496
9597 Returns:
9698 str: A natural representation of the amount of time elapsed.
99+
100+ Examples
101+ Compare two timestamps in a custom local timezone::
102+
103+ import datetime as dt
104+ from dateutil.tz import gettz
105+
106+ berlin = gettz("Europe/Berlin")
107+ now = dt.datetime.now(tz=berlin)
108+ later = now + dt.timedelta(minutes=30)
109+
110+ assert naturaldelta(later, when=now) == "30 minutes"
97111 """
98112 tmp = Unit [minimum_unit .upper ()]
99113 if tmp not in (Unit .SECONDS , Unit .MILLISECONDS , Unit .MICROSECONDS ):
100114 raise ValueError (f"Minimum unit '{ minimum_unit } ' not supported" )
101115 minimum_unit = tmp
102116
103- date , delta = date_and_delta (value )
117+ date , delta = date_and_delta (value , now = when )
104118 if date is None :
105119 return value
106120
@@ -173,7 +187,7 @@ def naturaldelta(value, months=True, minimum_unit="seconds"):
173187 return ngettext ("%d year" , "%d years" , years ) % years
174188
175189
176- def naturaltime (value , future = False , months = True , minimum_unit = "seconds" ):
190+ def naturaltime (value , future = False , months = True , minimum_unit = "seconds" , when = None ):
177191 """Return a natural representation of a time in a resolution that makes sense.
178192
179193 This is more or less compatible with Django's `naturaltime` filter.
@@ -186,11 +200,13 @@ def naturaltime(value, future=False, months=True, minimum_unit="seconds"):
186200 months (bool): If `True`, then a number of months (based on 30.5 days) will be
187201 used for fuzziness between years.
188202 minimum_unit (str): The lowest unit that can be used.
203+ when (datetime.datetime): Point in time relative to which _value_ is
204+ interpreted. Defaults to the current time in the local timezone.
189205
190206 Returns:
191207 str: A natural representation of the input in a resolution that makes sense.
192208 """
193- now = _now ()
209+ now = when or _now ()
194210 date , delta = date_and_delta (value , now = now )
195211 if date is None :
196212 return value
@@ -199,7 +215,7 @@ def naturaltime(value, future=False, months=True, minimum_unit="seconds"):
199215 future = date > now
200216
201217 ago = _ ("%s from now" ) if future else _ ("%s ago" )
202- delta = naturaldelta (delta , months , minimum_unit )
218+ delta = naturaldelta (delta , months , minimum_unit , when = when )
203219
204220 if delta == _ ("a moment" ):
205221 return _ ("now" )
0 commit comments