Skip to main content

ga-tictoc

ga-tictoc helps you measure elapsed time in Python programs, estimate how long a loop or job still needs, inspect processing speed, and log progress messages with readable timing information.

The distribution is named ga-tictoc; the Python import remains tictoc.

The main class is TicToc. It starts counting as soon as you create it.

from tictoc import TicToc

timer = TicToc()

# Code you want to measure

print(timer.toc())

Example output:

00:01:12

For a complete guide to all classes, methods, placeholders, parsing formats, casts, comparisons, and arithmetic operations, see docs/usage.md.

Release maintainers can find the PyPI publishing setup in docs/publishing.md.

Installation

Install or upgrade to the latest stable release from PyPI:

python -m pip install --upgrade ga-tictoc

Install from a GitHub release:

python -m pip install "https://github.com/andreagemma/tictoc/releases/download/v0.2.1/ga_tictoc-0.2.1-py3-none-any.whl"

Install from a local source checkout:

python -m pip install -e .

For more flexible date string parsing, install the optional parser support:

python -m pip install "ga-tictoc[dateutil]"

Quick Start

Measure Elapsed Time

from tictoc import TicToc

tt = TicToc()

# Work...

elapsed = tt.toc()
print(elapsed)  # Human-readable value
print(elapsed.seconds)  # Total seconds

toc() is an alias for elapsed_time().

tt.elapsed_time()
tt.elapsed_origin_time()

elapsed_time() measures from the most recent tic().
elapsed_origin_time() measures from the moment the timer was created.

Reset the Timer

tic() resets the start time and returns the same object, so it works well with method chaining.

tt = TicToc()

tt.tic().info("starting again")

Named Timers

One TicToc object can manage multiple independent named timers.

tt = TicToc()

tt.tic("download")
# Download...

tt.tic("parse")
# Parse...

print(tt.toc("download"))
print(tt.toc("parse"))

You can also access a named timer directly:

download_timer = tt["download"]
print(download_timer.elapsed_time())

Progress, ETA, and Speed

When you know the total number of steps, TicToc can estimate remaining time, total time, end time, and processing speed.

from tictoc import TicToc

tt = TicToc(total=100)

for i in range(1, 101):
    # Process one step
    if i % 10 == 0:
        print(
            i,
            tt.elapsed_time(),
            tt.remaining_time(i=i),
            tt.total_time(i=i),
            tt.end_time(i=i),
            tt.speed(i=i),
        )

Useful methods:

  • remaining_time(i=..., total=...): estimate time left.
  • total_time(i=..., total=...): estimate total execution time.
  • end_time(i=..., total=...): estimate when the job will finish.
  • speed(i=...): return a TicTocSpeed object.
  • percent(i=..., total=...): return completion percentage.

Estimation Methods

Choose how remaining time should be estimated with method.

tt.remaining_time(i=i, total=100, method="origin")
tt.remaining_time(i=i, total=100, method="last")
tt.remaining_time(i=i, total=100, method="moving", n=5)
tt.remaining_time(i=i, total=100, method="ema", n=5)
  • origin: average speed since the latest tic().
  • last: speed from the latest interval between two updates.
  • moving: average speed over the latest n updates.
  • ema: exponential moving average over the latest updates.

Built-In Logging

TicToc can also log progress. If you do not pass a logger, it uses an internal logger named tictoc.

import logging
from tictoc import TicToc

logging.basicConfig(level=logging.INFO)

tt = TicToc(total=50)

for i in range(1, 51):
    # Work...
    tt.info("{i}/{tot} elapsed={et} eta={rt} speed={v}", i=i, each=10)

each=10 logs only every 10 steps.

Available logging methods:

tt.debug("...")
tt.info("...")
tt.warning("...")
tt.error("...")
tt.exception("...")

You can also pass your own logger:

import logging
from tictoc import TicToc

logger = logging.getLogger("my-job")
tt = TicToc(logger=logger)

Log Placeholders

Progress messages support quick placeholders.

Placeholder Meaning
{i} or {counter} current step
{tot} or {total} total steps
{percent_str} formatted percentage
{et} elapsed time
{eot} elapsed origin time
{rt} remaining time
{tt} estimated total time
{v} speed
{start} start time
{origin} object creation time
{end} estimated end time

Use suffixes when you want numeric values:

tt.info("elapsed={et_s:.2f}s eta={rt_m:.1f}min speed={v_h:.0f}/h", i=i)

Common suffixes:

  • _s, _sec, _seconds
  • _m, _min, _minutes
  • _h, _hours
  • _d, _days
  • _str

Intervals: TicTocInterval

TicTocInterval represents a duration.

from datetime import timedelta
from tictoc import TicTocInterval

a = TicTocInterval("1 day 2 hours")
b = TicTocInterval(timedelta(minutes=30))
c = TicTocInterval(10)  # Seconds

print(a + b)
print(c * 3)
print(float(a))  # Total seconds
print(a.total_hours)
print(a.component_days)

Accepted formats include:

TicTocInterval("1 day 2 seconds")
TicTocInterval("1d 2h 3m 4s")
TicTocInterval("01:02:03")
TicTocInterval("1.02:00:53")
TicTocInterval("PT1H30M")

Timestamps: TicTocTime

TicTocTime represents a point in time.

from datetime import datetime, timedelta
from tictoc import TicTocTime

now = TicTocTime.now()
start = TicTocTime.from_string("2026-06-16 12:00:00")
later = start + timedelta(minutes=10)

print(now)
print(later - start)  # TicTocInterval
print(start.year, start.month, start.day)
print(float(start))  # Unix timestamp

You can create a TicTocTime from:

TicTocTime.now()
TicTocTime.from_timestamp(1_781_600_000)
TicTocTime.from_datetime(datetime.now())
TicTocTime.from_string("2026-06-16 12:00:00")

Speed: TicTocSpeed

TicTocSpeed represents steps per second and gives you ready-to-use conversions.

from tictoc import TicTocSpeed, TicTocInterval

speed = TicTocSpeed.from_steps(120, TicTocInterval.from_minutes(2))

print(speed)  # 1 step/s
print(speed.steps_per_second)
print(speed.steps_per_minute)
print(speed.steps_per_hour)

Complete Example

import logging
import time

from tictoc import TicToc

logging.basicConfig(level=logging.INFO, format="%(message)s")

tt = TicToc(total=20)

for i in range(1, 21):
    time.sleep(0.1)
    tt.info(
        "{i}/{tot} ({percent_str}) elapsed={et} eta={rt} end={end} speed={v}",
        i=i,
        each=5,
    )

print("finished in", tt.elapsed_time())

Example output:

5/20 (25.0%) elapsed=0.501 s eta=1.5 s end=2026-06-16 12:00:03 speed=10 steps/s
10/20 (50.0%) elapsed=1 s eta=1 s end=2026-06-16 12:00:03 speed=10 steps/s
15/20 (75.0%) elapsed=1.5 s eta=0.5 s end=2026-06-16 12:00:03 speed=10 steps/s
20/20 (100.0%) elapsed=2 s eta=0 s end=2026-06-16 12:00:03 speed=10 steps/s
finished in 2 s

License

Distributed under the MIT License. See LICENSE.

Third-party dependency notices and archived license files are available in:

Release files for ga-tictoc 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ga-tictoc 0.2.5
File Size Uploaded
ga_tictoc-0.2.5.tar.gz 34.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ga-tictoc 0.2.5
File Interpreter ABI Platform
ga_tictoc-0.2.5-py3-none-any.whl Python 3 none any Details

Total release size: 57.0 kB

Release files / ga_tictoc-0.2.5.tar.gz

Download URL ga_tictoc-0.2.5.tar.gz
Size 34.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ca733b676753bf3f92659dba2b7e2fc228382f88ff5cf28c366363744fdcb55c
BLAKE2b-256 checksum
How to use checksums
ffdcd987a1558267389dc1304b84d62e2a04b07d5d2b272201b1474e46f1a4f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / ga_tictoc-0.2.5-py3-none-any.whl

Download URL ga_tictoc-0.2.5-py3-none-any.whl
Size 22.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e047db072ee379c2ef93408d9f7f853fc73ea135bfeb18b1f518c7ecdb499c0
BLAKE2b-256 checksum
How to use checksums
cb13e308ed2bfc060653fe4b5d571d80c6d7b9c6fbdde21400967d90d0c20108
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 release files

0.2.4

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page