Skip to main content

Add and subtract HH:MM[:SS] time strings in Python — durations, aggregation, and timedelta integration.

Project description

hmscalc

PyPI version Stable Python versions CI License: MIT

Add and subtract HH:MM / HH:MM:SS time strings in Python — no manual conversion to seconds required.

v1.0.0 is the first stable release with SemVer API guarantees.

Quick Start

pip install hmscalc
from hmscalc import HMSTime

a = HMSTime("1:30:15")
b = HMSTime("2:15:45")

print(a + b)   # "3:46:00"
print(a - b)   # "-0:45:30"
print(a * 2)   # "3:00:30"
print(a / 2)   # "0:45:07"

Why hmscalc?

Approach Limitation
datetime.timedelta No "1:30:15" string parsing out of the box
Manual seconds math Verbose; easy to mishandle negative values
pytimeparse Parse-only — arithmetic is still on you
hmscalc Parse and add / subtract / aggregate in one API

Features

  • Addition, subtraction, and scalar multiply/divide
  • Sum, average, min, and max of multiple values
  • HH:MM and HH:MM:SS input (hours may exceed 24 — duration model)
  • Negative durations, comparison operators, datetime.timedelta integration
  • Input whitespace trimming (" 1:30:15 ")
  • Type hints with py.typed marker
  • Python 3.9 through 3.14
  • CLI: hmscalc add / sub / sum from the terminal

CLI

After pip install hmscalc:

hmscalc add 1:30 2:15 0:45
# 4:30:00

hmscalc sub 2:00 0:45
# 1:15:00

hmscalc sum 1:00 2:00 3:00
# 6:00:00

Equivalent: python -m hmscalc add 1:00 2:00

Usage

Import

from hmscalc import HMSTime

Creating HMSTime (string vs seconds vs timedelta)

Input Recommended API Example
"1:30:15" string HMSTime("1:30:15") Human-readable durations
Integer seconds HMSTime.from_seconds(3661) Programmatic / computed values
datetime.timedelta HMSTime.from_timedelta(delta) Interop with stdlib datetime

HMSTime(...) accepts strings only. Use from_seconds() for numeric seconds (TypeError if not int).

Basic Operations

a = HMSTime("1:30:15")
b = HMSTime("2:15:45")

print(a + b)            # "3:46:00"
print(a - b)            # "-0:45:30"
print(a > b)            # False
print(a.to_seconds())   # 5415
print(a.to_tuple())     # (1, 30, 15)
print(a.to_dict())      # {'hh': 1, 'mm': 30, 'ss': 15, 'negative': False}

Scalar Operations

HMSTime("1:00:00") * 3    # "3:00:00"
HMSTime("1:30:00") / 2    # "0:45:00"
2 * HMSTime("0:30:00")    # "1:00:00"

Aggregation

times = [HMSTime("1:30:15"), HMSTime("2:15:45"), HMSTime("0:45:30")]

HMSTime.sum(times)      # "4:31:30"
HMSTime.average(times)  # "1:30:30"
HMSTime.min(times)      # "0:45:30"
HMSTime.max(times)      # "2:15:45"

Work Time Example

work_sessions = [
    HMSTime("2:15:30"),
    HMSTime("1:45:00"),
    HMSTime("0:30:15"),
]
print(HMSTime.sum(work_sessions))  # "4:30:45"

timedelta Integration

import datetime

t = HMSTime("1:30:15")
delta = t.to_timedelta()
restored = HMSTime.from_timedelta(delta)  # HMSTime("1:30:15")

ISO 8601 Duration

t = HMSTime.from_iso8601("PT1H30M15S")
print(t.to_iso8601())  # "PT1H30M15S"
print(str(t))          # "1:30:15"

Time section only (PT…); date parts like P1D are not supported.

Custom Output Format

t = HMSTime("1:30:15")
t.format("HH:MM")     # "1:30"
t.format("HH:MM:SS")  # "1:30:15" — same as str(t)

Error Handling

from hmscalc import InvalidTimeFormatError, NotTimeStringError

HMSTime(" 1:30:15 ")   # OK — whitespace trimmed
HMSTime("1:99:00")     # InvalidTimeFormatError
HMSTime(123)             # NotTimeStringError

Negative Values

t = HMSTime("-1:00:00")
print(str(t))           # "-1:00:00"
print(t.is_negative)    # True
print(t.to_seconds())   # -3600
print(t.to_dict())      # {'hh': 1, 'mm': 0, 'ss': 0, 'negative': True}

to_tuple() returns absolute (hh, mm, ss); use is_negative or to_seconds() for sign.

Hashable (sets and dict keys)

a = HMSTime("1:00:00")
b = HMSTime("2:00:00")
sessions = {a, b, a}  # 2 unique items

API Reference

HMSTime(time_str: str)

Parse HH:MM or HH:MM:SS. Whitespace is trimmed. Hours may exceed 24 (duration model).

Class methods

Method Description
HMSTime.from_seconds(total_seconds: int) Build from integer seconds
HMSTime.from_timedelta(delta) Build from datetime.timedelta
HMSTime.from_iso8601(duration) Build from ISO 8601 PT… duration
HMSTime.sum(times) Sum iterable; empty → "0:00:00"
HMSTime.average(times) Mean, rounded to nearest second
HMSTime.min(times) / HMSTime.max(times) Min / max of iterable

Instance methods & properties

Member Description
is_negative True if total seconds < 0
to_seconds() Integer total seconds (signed)
to_minutes() / to_hours() Float conversion
to_timedelta() datetime.timedelta
to_iso8601() ISO 8601 PT… string
format(fmt) "HH:MM" or "HH:MM:SS" (__str__ = format("HH:MM:SS"))
to_tuple() (hh, mm, ss) absolute components
to_dict() {'hh', 'mm', 'ss', 'negative'}

Operators

+, -, *, / (scalar), ==, !=, <, <=, >, >=

Exceptions

from hmscalc import HMSTimeError, InvalidTimeFormatError, NotTimeStringError
Exception When
InvalidTimeFormatError Bad format, mm/ss ≥ 60, empty string
NotTimeStringError Non-string input
HMSTimeError Base class for both

Input Rules

  • Formats: HH:MM or HH:MM:SS
  • Minutes and seconds: 0–59
  • Optional leading - for negative durations
  • Surrounding whitespace is ignored
  • Strict mode only: overflow minutes/seconds (e.g. 1:90:00) are rejected — see Input Policy

Development

See CONTRIBUTING.md for branching, CI, and release process.

poetry install
poetry run pytest --cov=hmscalc

Docker matrix (Python 3.9–3.14): docker build -t hmscalc . && docker run --rm hmscalc ./runtests.sh

Links

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hmscalc-1.0.2.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hmscalc-1.0.2-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file hmscalc-1.0.2.tar.gz.

File metadata

  • Download URL: hmscalc-1.0.2.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1018-azure

File hashes

Hashes for hmscalc-1.0.2.tar.gz
Algorithm Hash digest
SHA256 a798db7b877ce7a52be8eaa41aaaa2400b0c729f7ea5b53caeb8f506c0033277
MD5 57e3958087876621c45588fbccfeb618
BLAKE2b-256 9a66692b5842e57075dbb43a3d0578201f945cb361f41308dabe9f377c08bdfc

See more details on using hashes here.

File details

Details for the file hmscalc-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: hmscalc-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1018-azure

File hashes

Hashes for hmscalc-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5aeba5ddcb4704c75a4854fa06c4b7370be8f509b7b32b1e8d3ca83a89129c57
MD5 29c38451f8cf8b8779ceb351b300af2b
BLAKE2b-256 6a75a25790b5cbf68cce15eb7097a9d098171f1eb54b01fffec140114be4a5f7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page