import time import asyncio import math class Timer(object): def __init__(self, timeout, on_done = None, on_update = None) -> None: super().__init__() self.timeout = timeout self._timemout = self.timeout self._task = None self._callback = on_done self._update = on_update self.start_time = None self.end_time = None def done(self, task): if self._callback is not None: asyncio.create_task(self._callback(self)) async def _job(self): self.start_time = int(time.time()) self.end_time = self.start_time + int(round(self._timemout, 0)) self.count = self.end_time - self.start_time try: while self.count > 0: self.count = (self.end_time - int(time.time())) if self._update is not None: await self._update(self,self.count) await asyncio.sleep(1) except asyncio.CancelledError: end = int(time.time()) duration = end - self.start_time self._timemout = self._timemout - duration async def add(self, seconds): self.end_time = self.end_time + seconds def start(self): self._task = asyncio.create_task(self._job()) self._task.add_done_callback(self.done) async def stop(self): if self._task and self._task.done() is False: self._task.cancel() await self._task def reset(self): if self.is_running is True: return self._timemout = self.timeout def is_running(self): return not self._task.done() def set_time(self,timeout): if self.is_running is True: return self.timeout = timeout def get_time(self): return self.format_time(int(round(self._timemout,0))) @classmethod def format_time(cls, time): pattern_h = '{0:02d}:{1:02d}:{2:02d}' pattern_d = '{0:02d}D {1:02d}:{2:02d}:{3:02d}' seconds = time % 60 minutes = math.floor(time / 60) % 60 hours = math.floor(time / 3600) % 24 days = math.floor(time / 86400) if days != 0: remaining_time = pattern_d.format(days, hours, minutes, seconds) else: remaining_time = pattern_h.format(hours, minutes, seconds) return remaining_time