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.0.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.0-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hmscalc-1.0.0.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.0.tar.gz
Algorithm Hash digest
SHA256 5e254c3fb06a99aed01d2d7b0e0c6ba123845cd104da48e1521b786b04450a1b
MD5 0bc91d3c2ea5a6cd28680aceb5e7ec03
BLAKE2b-256 8cb06444ad987da61277839bf6f3fba5ad2e25fbb4da9f34db4a135b95f00435

See more details on using hashes here.

File details

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

File metadata

  • Download URL: hmscalc-1.0.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f08286f7cf5307801257200692a1a16a153a7b0fa6e20dd00f52ce5f45a36327
MD5 dce4b7c6a7dfe67655300e8a0d4969d8
BLAKE2b-256 d1f106ace60e1dd7657fc7c5defb80a67550b1840882a04bd8c0065677e0fe05

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