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 aTicTocSpeedobject.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 latesttic().last: speed from the latest interval between two updates.moving: average speed over the latestnupdates.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)
| File | Size | Uploaded | |
|---|---|---|---|
| ga_tictoc-0.2.5.tar.gz | 34.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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