Module noiftimer.noiftimer

Expand source code
from datetime import datetime


class Timer:
    """Simple timer class that tracks total elapsed time
    and average time between calls to 'start' and 'stop'."""

    def __init__(self, averaging_window_length: int = 10):
        """:param averaging_window_length: Number of start/stop cycles
        to calculate the average elapsed time with."""
        self.start_time: datetime = datetime.now()
        self.stop_time: datetime = datetime.now()
        self.average_elapsed_time: float = 0
        self.history: list[float] = []
        self.elapsed_time: float = 0
        self.averaging_window_length: int = averaging_window_length
        self.started: bool = False

    def start(self):
        """Start timer."""
        self.start_time = datetime.now()
        self.started = True

    def stop(self):
        """Stop timer.

        Calculates elapsed time and average elapsed time."""
        self.stop_time = datetime.now()
        self.started = False
        self.elapsed_time = (self.stop_time - self.start_time).total_seconds()
        self._save_elapsed_time()
        self.average_elapsed_time = sum(self.history) / (len(self.history))

    def _save_elapsed_time(self):
        """Saves current elapsed time to the history buffer
        in a FIFO manner."""
        if len(self.history) >= self.averaging_window_length:
            self.history.pop(0)
        self.history.append(self.elapsed_time)

    def current_elapsed_time(self, format: bool = True) -> float | str:
        """Returns current elapsed without stopping the timer.

        :param format: If True, elapsed time is returned as a string.
        If False, elapsed time is returned as a float."""
        self.elapsed_time = (datetime.now() - self.start_time).total_seconds()
        return self.format_time(self.elapsed_time) if format else self.elapsed_time

    def _get_time_unit(
        self, num_seconds: float, seconds_per_unit: float, unit_suffix: str
    ) -> tuple[float, str]:
        """Determines the number of units in a given number of seconds
        by integer division.

        Returns a tuple containing the remaining number of seconds after division
        as well as the number of units as a string with 'unit_suffix' appended to the string.

        e.g. _get_time_unit(124, 60, 'm') will return (4, '2m')"""
        num_units = int(num_seconds / seconds_per_unit)
        if num_units > 0:
            remainder = num_seconds - (num_units * seconds_per_unit)
            return (remainder, f"{num_units}{unit_suffix}")
        else:
            return (num_seconds, "")

    def format_time(
        self, num_seconds: float, subsecond_resolution: bool = False
    ) -> str:
        """Returns num_seconds as a string with units.

        :param subsecond_resolution: Include milliseconds
        and microseconds with the output."""
        microsecond = 0.000001
        millisecond = 0.001
        second = 1
        seconds_per_minute = 60
        seconds_per_hour = 3600
        seconds_per_day = 86400
        seconds_per_week = 604800
        seconds_per_month = 2419200
        seconds_per_year = 29030400
        time_units = [
            (seconds_per_year, "y"),
            (seconds_per_month, "mn"),
            (seconds_per_week, "w"),
            (seconds_per_day, "d"),
            (seconds_per_hour, "h"),
            (seconds_per_minute, "m"),
            (second, "s"),
            (millisecond, "ms"),
            (microsecond, "us"),
        ]
        if not subsecond_resolution:
            time_units = time_units[:-2]
        time_string = ""
        for time_unit in time_units:
            num_seconds, unit_string = self._get_time_unit(
                num_seconds, time_unit[0], time_unit[1]
            )
            if unit_string != "":
                time_string += f"{unit_string} "
        return time_string.strip()

    def get_stats(self, format: bool = True, subsecond_resolution: bool = False) -> str:
        """Returns string for elapsed time and average elapsed time.

        :param format: Times are returned as strings if True,
        otherwise they're raw floats.

        :param subsecond_resolution: Include milliseconds
        and microseconds with the output."""
        if format:
            return f"elapsed time: {self.format_time(self.elapsed_time, subsecond_resolution)}\naverage elapsed time: {self.format_time(self.average_elapsed_time, subsecond_resolution)}"
        else:
            return f"elapsed time: {self.elapsed_time}s\naverage elapsed time: {self.average_elapsed_time}s"

Classes

class Timer (averaging_window_length: int = 10)

Simple timer class that tracks total elapsed time and average time between calls to 'start' and 'stop'.

:param averaging_window_length: Number of start/stop cycles to calculate the average elapsed time with.

Expand source code
class Timer:
    """Simple timer class that tracks total elapsed time
    and average time between calls to 'start' and 'stop'."""

    def __init__(self, averaging_window_length: int = 10):
        """:param averaging_window_length: Number of start/stop cycles
        to calculate the average elapsed time with."""
        self.start_time: datetime = datetime.now()
        self.stop_time: datetime = datetime.now()
        self.average_elapsed_time: float = 0
        self.history: list[float] = []
        self.elapsed_time: float = 0
        self.averaging_window_length: int = averaging_window_length
        self.started: bool = False

    def start(self):
        """Start timer."""
        self.start_time = datetime.now()
        self.started = True

    def stop(self):
        """Stop timer.

        Calculates elapsed time and average elapsed time."""
        self.stop_time = datetime.now()
        self.started = False
        self.elapsed_time = (self.stop_time - self.start_time).total_seconds()
        self._save_elapsed_time()
        self.average_elapsed_time = sum(self.history) / (len(self.history))

    def _save_elapsed_time(self):
        """Saves current elapsed time to the history buffer
        in a FIFO manner."""
        if len(self.history) >= self.averaging_window_length:
            self.history.pop(0)
        self.history.append(self.elapsed_time)

    def current_elapsed_time(self, format: bool = True) -> float | str:
        """Returns current elapsed without stopping the timer.

        :param format: If True, elapsed time is returned as a string.
        If False, elapsed time is returned as a float."""
        self.elapsed_time = (datetime.now() - self.start_time).total_seconds()
        return self.format_time(self.elapsed_time) if format else self.elapsed_time

    def _get_time_unit(
        self, num_seconds: float, seconds_per_unit: float, unit_suffix: str
    ) -> tuple[float, str]:
        """Determines the number of units in a given number of seconds
        by integer division.

        Returns a tuple containing the remaining number of seconds after division
        as well as the number of units as a string with 'unit_suffix' appended to the string.

        e.g. _get_time_unit(124, 60, 'm') will return (4, '2m')"""
        num_units = int(num_seconds / seconds_per_unit)
        if num_units > 0:
            remainder = num_seconds - (num_units * seconds_per_unit)
            return (remainder, f"{num_units}{unit_suffix}")
        else:
            return (num_seconds, "")

    def format_time(
        self, num_seconds: float, subsecond_resolution: bool = False
    ) -> str:
        """Returns num_seconds as a string with units.

        :param subsecond_resolution: Include milliseconds
        and microseconds with the output."""
        microsecond = 0.000001
        millisecond = 0.001
        second = 1
        seconds_per_minute = 60
        seconds_per_hour = 3600
        seconds_per_day = 86400
        seconds_per_week = 604800
        seconds_per_month = 2419200
        seconds_per_year = 29030400
        time_units = [
            (seconds_per_year, "y"),
            (seconds_per_month, "mn"),
            (seconds_per_week, "w"),
            (seconds_per_day, "d"),
            (seconds_per_hour, "h"),
            (seconds_per_minute, "m"),
            (second, "s"),
            (millisecond, "ms"),
            (microsecond, "us"),
        ]
        if not subsecond_resolution:
            time_units = time_units[:-2]
        time_string = ""
        for time_unit in time_units:
            num_seconds, unit_string = self._get_time_unit(
                num_seconds, time_unit[0], time_unit[1]
            )
            if unit_string != "":
                time_string += f"{unit_string} "
        return time_string.strip()

    def get_stats(self, format: bool = True, subsecond_resolution: bool = False) -> str:
        """Returns string for elapsed time and average elapsed time.

        :param format: Times are returned as strings if True,
        otherwise they're raw floats.

        :param subsecond_resolution: Include milliseconds
        and microseconds with the output."""
        if format:
            return f"elapsed time: {self.format_time(self.elapsed_time, subsecond_resolution)}\naverage elapsed time: {self.format_time(self.average_elapsed_time, subsecond_resolution)}"
        else:
            return f"elapsed time: {self.elapsed_time}s\naverage elapsed time: {self.average_elapsed_time}s"

Methods

def current_elapsed_time(self, format: bool = True) ‑> float | str

Returns current elapsed without stopping the timer.

:param format: If True, elapsed time is returned as a string. If False, elapsed time is returned as a float.

Expand source code
def current_elapsed_time(self, format: bool = True) -> float | str:
    """Returns current elapsed without stopping the timer.

    :param format: If True, elapsed time is returned as a string.
    If False, elapsed time is returned as a float."""
    self.elapsed_time = (datetime.now() - self.start_time).total_seconds()
    return self.format_time(self.elapsed_time) if format else self.elapsed_time
def format_time(self, num_seconds: float, subsecond_resolution: bool = False) ‑> str

Returns num_seconds as a string with units.

:param subsecond_resolution: Include milliseconds and microseconds with the output.

Expand source code
def format_time(
    self, num_seconds: float, subsecond_resolution: bool = False
) -> str:
    """Returns num_seconds as a string with units.

    :param subsecond_resolution: Include milliseconds
    and microseconds with the output."""
    microsecond = 0.000001
    millisecond = 0.001
    second = 1
    seconds_per_minute = 60
    seconds_per_hour = 3600
    seconds_per_day = 86400
    seconds_per_week = 604800
    seconds_per_month = 2419200
    seconds_per_year = 29030400
    time_units = [
        (seconds_per_year, "y"),
        (seconds_per_month, "mn"),
        (seconds_per_week, "w"),
        (seconds_per_day, "d"),
        (seconds_per_hour, "h"),
        (seconds_per_minute, "m"),
        (second, "s"),
        (millisecond, "ms"),
        (microsecond, "us"),
    ]
    if not subsecond_resolution:
        time_units = time_units[:-2]
    time_string = ""
    for time_unit in time_units:
        num_seconds, unit_string = self._get_time_unit(
            num_seconds, time_unit[0], time_unit[1]
        )
        if unit_string != "":
            time_string += f"{unit_string} "
    return time_string.strip()
def get_stats(self, format: bool = True, subsecond_resolution: bool = False) ‑> str

Returns string for elapsed time and average elapsed time.

:param format: Times are returned as strings if True, otherwise they're raw floats.

:param subsecond_resolution: Include milliseconds and microseconds with the output.

Expand source code
def get_stats(self, format: bool = True, subsecond_resolution: bool = False) -> str:
    """Returns string for elapsed time and average elapsed time.

    :param format: Times are returned as strings if True,
    otherwise they're raw floats.

    :param subsecond_resolution: Include milliseconds
    and microseconds with the output."""
    if format:
        return f"elapsed time: {self.format_time(self.elapsed_time, subsecond_resolution)}\naverage elapsed time: {self.format_time(self.average_elapsed_time, subsecond_resolution)}"
    else:
        return f"elapsed time: {self.elapsed_time}s\naverage elapsed time: {self.average_elapsed_time}s"
def start(self)

Start timer.

Expand source code
def start(self):
    """Start timer."""
    self.start_time = datetime.now()
    self.started = True
def stop(self)

Stop timer.

Calculates elapsed time and average elapsed time.

Expand source code
def stop(self):
    """Stop timer.

    Calculates elapsed time and average elapsed time."""
    self.stop_time = datetime.now()
    self.started = False
    self.elapsed_time = (self.stop_time - self.start_time).total_seconds()
    self._save_elapsed_time()
    self.average_elapsed_time = sum(self.history) / (len(self.history))