Hyppää sisältöön

Ei vielä käännetty

Tätä sivua ei ole vielä käännetty suomeksi, joten se näytetään englanniksi. Auta kääntämään

time Module Complexity

The time module reads the system's clocks, sleeps, and converts between timestamps, struct_time tuples and strings. It is a thin layer over the C library: a clock read is one call into the operating system, and a conversion fills or reads one fixed-size record.

f is the characters in a format string and n is the characters in the string strptime() parses. Every other operation takes a fixed-size input - a clock id, a timestamp, or a struct_time - and is O(1), with one exception: on Linux, reading the process's CPU time sums the CPU time of all t threads in the process. The C library's own work is priced O(1) otherwise: reading any other clock, and consulting the timezone rules that localtime(), mktime() and tzset() rely on.

Complexity Reference

Clocks

Operation Time Space Notes
time.time(), time.time_ns() O(1) O(1) Seconds since the epoch; the system clock can be set back, so two readings can go backwards. The _ns form returns an int and keeps the nanoseconds a float rounds away
time.monotonic(), time.monotonic_ns() O(1) O(1) Never goes backwards; the clock for timeouts and durations
time.perf_counter(), time.perf_counter_ns() O(1) O(1) The highest-resolution clock for short durations; counts time spent in sleep()
time.process_time(), time.process_time_ns() O(t) O(1) CPU time of the whole process; time spent in sleep() does not count. Linux sums the CPU time of all t threads, unless a process-wide CPU timer such as setitimer(ITIMER_PROF, ...) is armed
time.thread_time(), time.thread_time_ns() O(1) O(1) CPU time of the calling thread only; availability is platform-dependent
time.get_clock_info(name) O(1); O(t) for 'process_time' on Linux O(1) A namespace of implementation, monotonic, adjustable and resolution

POSIX clocks

Operation Time Space Notes
time.clock_gettime(clk_id), time.clock_gettime_ns(clk_id) O(1); O(t) for CLOCK_PROCESS_CPUTIME_ID on Linux O(1) Unix only; reads the clock a CLOCK_* id names
time.clock_settime(clk_id, t), time.clock_settime_ns(clk_id, t) O(1) O(1) Unix only, and needs privileges
time.clock_getres(clk_id) O(1) O(1) Unix only; the clock's resolution, not the cost of reading it
time.pthread_getcpuclockid(thread_id) O(1) O(1) Unix only; the id of a thread's CPU-time clock, for clock_gettime()
time.CLOCK_REALTIME, time.CLOCK_MONOTONIC, time.CLOCK_MONOTONIC_RAW, time.CLOCK_BOOTTIME, time.CLOCK_PROCESS_CPUTIME_ID, time.CLOCK_THREAD_CPUTIME_ID, time.CLOCK_TAI, time.CLOCK_HIGHRES, time.CLOCK_PROF, time.CLOCK_UPTIME, time.CLOCK_UPTIME_RAW O(1) O(1) Integer clock ids; which of them exist is platform-dependent
time.CLOCK_MONOTONIC_RAW_APPROX, time.CLOCK_UPTIME_RAW_APPROX O(1) O(1) Python 3.13+; platform-dependent integer clock ids

Sleeping

Operation Time Space Notes
time.sleep(secs) O(1) O(1) Blocks the calling thread for at least secs; the wait costs no CPU time, whatever secs is

Conversions

Operation Time Space Notes
time.gmtime([secs]), time.localtime([secs]) O(1) O(1) A timestamp to a struct_time, in UTC or local time; the current time when secs is omitted
time.mktime(t) O(1) O(1) A local struct_time back to a timestamp
time.asctime([t]), time.ctime([secs]) O(1) O(1) 24 characters for any four-digit year
time.strftime(format[, t]) O(f) O(f) Output grows with the format: each directive expands to a bounded number of characters
time.strptime(string[, format]) O(n) O(n) Each format is compiled once and cached; the cache is small and is cleared wholesale when full

struct_time

Operation Time Space Notes
time.struct_time(sequence) O(1) O(1) Nine to eleven items; the tenth and eleventh fill tm_zone and tm_gmtoff
struct_time.tm_year, struct_time.tm_mon, struct_time.tm_mday, struct_time.tm_hour, struct_time.tm_min, struct_time.tm_sec, struct_time.tm_wday, struct_time.tm_yday, struct_time.tm_isdst O(1) O(1) The nine fields that indexing and unpacking reach
struct_time.tm_zone, struct_time.tm_gmtoff O(1) O(1) Attributes only: not part of the nine-item tuple

Timezone attributes

Operation Time Space Notes
time.timezone, time.altzone, time.daylight, time.tzname O(1) O(1) Module attributes, set at import and again by tzset()
time.tzset() O(1) O(1) Unix only; re-reads TZ and refreshes the four attributes above

Reading Clocks

Choosing a Clock

time() follows the system clock, which can be set back, so a duration measured with it can come out negative. Measure durations with monotonic() or perf_counter(), and use the _ns forms where the nanoseconds matter: a float timestamp near the present cannot hold them.

import math
import time

now = time.time()  # O(1)
now_ns = time.time_ns()  # O(1)
assert isinstance(now_ns, int)
assert math.ulp(now) > 1e-9  # a float this large cannot resolve one nanosecond

start = time.monotonic()  # O(1)
elapsed = time.monotonic() - start
assert elapsed >= 0

info = time.get_clock_info("monotonic")  # O(1)
assert info.monotonic is True
assert info.resolution > 0

CPU Time

process_time() and thread_time() count CPU time, so a thread that is blocked adds nothing to them. perf_counter() counts wall-clock time, sleep included.

import time

cpu_before = time.process_time()  # O(t) on Linux - sums every thread
wall_before = time.perf_counter()  # O(1)
time.sleep(0.05)  # O(1) - the thread waits, it does not work
cpu_spent = time.process_time() - cpu_before
wall_spent = time.perf_counter() - wall_before

assert wall_spent >= 0.05
assert cpu_spent < wall_spent

POSIX Clocks

On Unix, clock_gettime() reads a clock by id. Which ids exist depends on the platform, so check before reaching for one.

import time

if hasattr(time, "clock_gettime") and hasattr(time, "CLOCK_MONOTONIC"):
    seconds = time.clock_gettime(time.CLOCK_MONOTONIC)  # O(1)
    nanoseconds = time.clock_gettime_ns(time.CLOCK_MONOTONIC)  # O(1)
    assert isinstance(seconds, float) and isinstance(nanoseconds, int)
    assert 0 < time.clock_getres(time.CLOCK_MONOTONIC) <= 1  # O(1)

Converting Timestamps

A struct_time has a fixed shape whatever the timestamp, so converting either way is O(1). Its nine fields are reachable by index and by name; tm_zone and tm_gmtoff only by name.

import time

utc = time.gmtime(0)  # O(1)
assert (utc.tm_year, utc.tm_mon, utc.tm_mday) == (1970, 1, 1)
assert utc[0] == utc.tm_year  # O(1) either way
assert len(utc) == 9
assert utc.tm_gmtoff == 0 and utc.tm_zone not in utc  # O(1) - by name only

local = time.localtime(1_000_000_000)  # O(1)
assert time.mktime(local) == 1_000_000_000  # O(1)

rebuilt = time.struct_time(tuple(utc))  # O(1)
assert rebuilt == utc

Formatting and Parsing

These are the only operations on this page whose cost follows an input: strftime() the format it is given, and strptime() the string it parses. asctime() and ctime() have a fixed layout instead.

import time

moment = time.gmtime(0)

stamp = time.strftime("%Y-%m-%d %H:%M:%S", moment)  # O(f)
assert stamp == "1970-01-01 00:00:00"

parsed = time.strptime("2026-01-30 12:34:56", "%Y-%m-%d %H:%M:%S")  # O(n)
assert (parsed.tm_year, parsed.tm_hour) == (2026, 12)

assert time.asctime(moment) == "Thu Jan  1 00:00:00 1970"  # O(1)

The strptime Format Cache

strptime() compiles its format to a regular expression and caches it, so a format reused in a loop is compiled once and each later call is only the O(n) match. The cache holds a few formats and is emptied all at once when it is full, so a program rotating through more formats than that compiles on almost every call. datetime.strptime() shares the same cache.

import time

lines = ["2026-01-30 08:00", "2026-01-30 09:15", "2026-01-31 17:45"]
fmt = "%Y-%m-%d %H:%M"

hours = [time.strptime(line, fmt).tm_hour for line in lines]  # compiled once, then O(n) each
assert hours == [8, 9, 17]

try:
    time.strptime("2026-01-30", fmt)
except ValueError as error:
    assert "does not match format" in str(error)
else:
    raise AssertionError("a string missing its time parsed")

Timezone Attributes

import time

offset = time.timezone  # O(1) - seconds west of UTC, outside DST
dst_offset = time.altzone  # O(1) - the same with DST in effect
has_dst = time.daylight  # O(1)
standard, summer = time.tzname  # O(1) - a two-string tuple
assert isinstance(offset, int) and isinstance(dst_offset, int)

if hasattr(time, "tzset"):
    time.tzset()  # O(1) - re-reads TZ and refreshes the four above
    assert len(time.tzname) == 2

Common Patterns

Timing a Block of Code

import time

start = time.perf_counter_ns()  # O(1)
total = sum(range(100_000))
elapsed_ns = time.perf_counter_ns() - start  # O(1)

assert total == 4_999_950_000
assert elapsed_ns >= 0

Waiting With a Deadline

import time

deadline = time.monotonic() + 0.05  # O(1) - unaffected if the system clock is set
while time.monotonic() < deadline:
    time.sleep(0.01)  # O(1) CPU per wait

assert time.monotonic() >= deadline

Performance Best Practices

✅ Do:

  • Measure durations and deadlines with monotonic() or perf_counter(), which never go backwards
  • Use process_time() or thread_time() to separate CPU work from time spent waiting
  • Reuse one strptime() format across a loop, so it is compiled once
  • Use the _ns clock forms when nanoseconds matter

❌ Avoid:

  • Timing with time() - a clock adjustment can make the result wrong or negative
  • Rotating through many strptime() formats - past the cache's size, most calls recompile
  • A busy loop polling a clock where sleep() would wait without spending CPU

Version Notes

  • Python 3.13+: strptime() issues a DeprecationWarning for a format with a day of the month but no year
  • Python 3.15+: strptime() raises ValueError for a format with a day of the month but no year, instead of warning
  • All Python 3: time() follows the system clock and can go backwards when it is set
  • datetime - date and time objects with arithmetic; datetime.strptime() shares the format cache
  • zoneinfo - IANA timezones for datetime, beyond the process-wide TZ
  • calendar - calendar.timegm(), the inverse of time.gmtime()
  • timeit - repeated timing of small snippets, built on perf_counter()