@@ -481,18 +481,20 @@ async def get_next_period(
481481 self ,
482482 interval : TimeDeltaLike ,
483483 start : time | datetime | str | None = None ,
484- buffer : TimeDeltaLike = 0.01 ,
485484 ) -> datetime :
486485 interval = utils .parse_timedelta (interval )
487486 start = "now" if start is None else start
488- aware_start = await self .parse_datetime (start , aware = True )
487+
488+ # Get "now" once and use it consistently to avoid timing races
489+ now = await self .get_now ()
490+ aware_start = await self .parse_datetime (start , aware = True , now = now )
489491 assert isinstance (aware_start , datetime ) and aware_start .tzinfo is not None
490- buffer = utils . parse_timedelta ( buffer )
491- while True :
492- if aware_start >= ( await self . get_now () - buffer ) :
493- return aware_start
494- else :
495- aware_start += interval
492+
493+ # Skip forward to the next period if start is in the past
494+ while aware_start < now :
495+ aware_start += interval
496+
497+ return aware_start
496498
497499 async def terminate_app (self , name : str ):
498500 if app_sched := self .schedule .pop (name , False ):
@@ -875,7 +877,9 @@ async def parse_datetime(
875877 input_ : str | time | datetime ,
876878 aware : bool = False ,
877879 today : bool | None = None ,
878- days_offset : int = 0
880+ days_offset : int = 0 ,
881+ * ,
882+ now : datetime | None = None ,
879883 ) -> datetime : # fmt: skip
880884 """Parse a variety of inputs into a datetime object.
881885
@@ -890,9 +894,12 @@ async def parse_datetime(
890894 of the next one.
891895 days_offset (int, optional): Number of days to offset from the current date for sunrise/sunset parsing. If
892896 this is negative, this will unset the `today` argument, which allows the result to be in the past.
897+ now (datetime, optional): The current time to use as reference. If not provided, will call get_now().
893898 """
894899 # Need to force timezone during time-travel mode
895- now = (await self .get_now ()).astimezone (self .AD .tz )
900+ if now is None :
901+ now = await self .get_now ()
902+ now = now .astimezone (self .AD .tz )
896903 return parse .parse_datetime (
897904 input_ = input_ ,
898905 now = now ,
0 commit comments