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

Uploaded Python 3

File details

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

File metadata

  • Download URL: hmscalc-1.0.5.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.5.tar.gz
Algorithm Hash digest
SHA256 2abdde03a534f556aab4119274f848b08d9aa9bbffb9e1828870db070d9cfb42
MD5 1aefe5c9165acd658831d3e9c8ab190b
BLAKE2b-256 8642fb2b80ea5b94544040b5ebc7b0e4164c1aa1d3925518fdce38437ef121e8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: hmscalc-1.0.5-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.5-py3-none-any.whl
Algorithm Hash digest
SHA256 aca1a6f2b887fbbe30fa57ecc989b370452d9187f4a95fa2b42d0fcce5162b77
MD5 faeba910135ff66030b075f0dc17ce06
BLAKE2b-256 87a0cfd39f818003e343deafa028e92b2fc3eed48ecedb1f0370659efaf201b3

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