@@ -97,6 +97,9 @@ def __init__(
9797
9898 self ._instance = None
9999
100+ self ._args : tuple | None = None
101+ self ._kwargs : dict | None = None
102+
100103 def __get__ (self , instance , owner ):
101104 if instance is None :
102105 return self
@@ -143,6 +146,8 @@ def start(self, *args, **kwargs) -> asyncio.Task:
143146 if self ._task is not None and not self ._task .done () and not self ._restarting :
144147 raise RuntimeError (f"Routine { self ._coro .__name__ !r} is already running and is not done." )
145148
149+ self ._args , self ._kwargs = args , kwargs
150+
146151 self ._restarting = False
147152 self ._task = self ._loop .create_task (self ._routine (* args , ** kwargs ))
148153
@@ -226,6 +231,70 @@ def after_routine(self, coro: Callable) -> None:
226231
227232 self ._after = coro
228233
234+ def change_interval (
235+ self ,
236+ * ,
237+ seconds : Optional [float ] = 0 ,
238+ minutes : Optional [float ] = 0 ,
239+ hours : Optional [float ] = 0 ,
240+ time : Optional [datetime .datetime ] = None ,
241+ wait_first : Optional [bool ] = False ,
242+ ) -> None :
243+ """Method which schedules the running interval of the task to change.
244+
245+ Parameters
246+ ----------
247+ seconds: Optional[float]
248+ The seconds to wait before the next iteration of the routine.
249+ minutes: Optional[float]
250+ The minutes to wait before the next iteration of the routine.
251+ hours: Optional[float]
252+ The hours to wait before the next iteration of the routine.
253+ time: Optional[datetime.datetime]
254+ A specific time to run this routine at. If a naive datetime is passed, your system local time will be used.
255+ wait_first: Optional[bool]
256+ Whether to wait the specified time before running the first iteration at the new interval.
257+ Defaults to False.
258+
259+ Raises
260+ ------
261+ RuntimeError
262+ Raised when the time argument and any hours, minutes or seconds is passed together.
263+
264+
265+ .. warning::
266+
267+ The time argument can not be passed in conjunction with hours, minutes or seconds.
268+ This behaviour is intended as it allows the time to be exact every day.
269+ """
270+ time_ = time
271+
272+ if any ((seconds , minutes , hours )) and time_ :
273+ raise RuntimeError (
274+ "Argument <time> can not be used in conjunction with any <seconds>, <minutes> or <hours> argument(s)."
275+ )
276+
277+ if not time_ :
278+ delta = compute_timedelta (
279+ datetime .datetime .now (datetime .timezone .utc )
280+ + datetime .timedelta (seconds = seconds , minutes = minutes , hours = hours )
281+ )
282+
283+ self ._delta = delta
284+ else :
285+ now = datetime .datetime .now (time_ .tzinfo )
286+ if time_ < now :
287+ time_ = datetime .datetime .combine (now .date (), time_ .time ())
288+ if time_ < now :
289+ time_ = time_ + datetime .timedelta (days = 1 )
290+
291+ self ._time = time_
292+
293+ kwargs : dict = self ._kwargs
294+ kwargs ['force' ] = not wait_first
295+
296+ self .restart (* self ._args , ** kwargs )
297+
229298 def error (self , coro : Callable ):
230299 """A decorator to assign a coroutine as the error handler for this routine.
231300
0 commit comments