Skip to main content
Change of provenance

The repository or configuration that created this release differ from a previous release. View details.

mixradix

Add, subtract and convert integers of any size in mixed radix bases, where every digit position has its own radix: hours:minutes:seconds, pounds:shillings:pence, feet:inches, or plain hexadecimal. Zero dependencies, fully typed, with a command line tool.

pipx install mixradix        # or: pip install mixradix / uv tool install mixradix
$ mixradix add 23:59:59 1 -b 24:60:60
1:0:0:0
$ mixradix sub 0:15 0:30 -b 24:60/wrap
23:45
$ mixradix convert 100000 -t 24:60:60
1:3:46:40

Also available for JavaScript and TypeScript as mixradix on npm, with the same behaviour and CLI.

Bases

A base lists one radix per digit position, most significant first, like the digits of a number:

Base Meaning
10, 16, 2 plain decimal, hexadecimal, binary
24:60:60 hours:minutes:seconds (days above that have no limit)
20:12 pounds:shillings:pence
24:60/wrap a 24-hour clock that wraps around
2:3:4/repeat ...2:2:3:4: the leftmost radix repeats

The part after / is the overflow: what happens left of the leftmost radix.

Overflow What is left of the leftmost radix Default for
repeat the same radix again, forever one radix (16)
extend one more digit with no limit several radices (24:60:60)
wrap nothing: values wrap around modulo the product of the radices

So 30 days in 24:60:60 is 30:0:0:0, and in 24:60:60/wrap it is 0:0:0.

Numbers

  • One character per digit (ff, 1011, case-insensitive) in a base with one radix of at most 36, like 16 or 2.
  • Decimal digits separated by : (1:23:59) in every base.
  • In a base like 24:60:60, text without : is a single digit: 45 is 45 seconds.
  • A leading - or + sets the sign. With wrap, values are never negative.

Every digit must be below its position's radix, so 1:60:0 is rejected in 24:60:60.

Command line

mixradix add <NUMBER> <NUMBER>... [-b BASE] [-t TO] [--json]
mixradix sub <NUMBER> <NUMBER>... [-b BASE] [-t TO] [--json]   (alias: subtract)
mixradix convert <NUMBER> -t TO [-b BASE] [--json]
mixradix info <BASE> [--json]
  • -b, --base: the base the numbers are written in. Defaults to 10.
  • -t, --to: the base to write the result in. Defaults to --base.
  • Negative numbers work as they are: -5, -1:30, -ff. Only one that starts with an option letter, like -b1 in base 16, goes after --.
$ mixradix add 1:30 2:45 0:50 -b 60                  # sum of durations
5:5
$ mixradix add 1:19:11 1 -b 20:12                    # pounds:shillings:pence
2:0:0
$ mixradix convert ff -b 16 -t 2
11111111
$ mixradix convert -90 -t 60 --json
{"result":"-1:30","value":-90,"digits":[1,30],"negative":true,"base":"60"}
$ mixradix info 24:60/wrap
base:         24:60/wrap
overflow:     wrap (values wrap around modulo 1440)
digits:       exactly 2
place values: 60, 1
range:        0 to 1439

Exit codes: 0 on success, 1 for an invalid base or number, 2 for a usage error. python -m mixradix works too.

Library

from mixradix import MixedRadix, MixedRadixNumber, add, sub, convert

# Quick string in, string out.
add("23:59:59", "1", base="24:60:60")        # '1:0:0:0'
sub("1:0:0", "1", base="24:60:60", to=10)    # '3599'
convert(5000, to="24:60:60")                 # '1:23:20'

# Bases and numbers.
time = MixedRadix("24:60:60")                # or MixedRadix([24, 60, 60])
t = time.parse("1:23:59")                    # or time.from_int(5039)
t.value, t.digits                            # 5039, (1, 23, 59)
str(t + 1), str(t - "0:23:59")               # '1:24:0', '1:0:0'
str(t.to(10))                                # '5039'
t == 5039                                    # True: comparison is by value

clock = MixedRadix([24, 60], overflow="wrap")
str(clock.parse("23:30") + "1:0")            # '0:30'

MixedRadixNumber("ff", 16).value             # 255
API What it does
MixedRadix(base, overflow=None) Base from "24:60:60", 16, or [24, 60, 60]
.radices, .overflow, .max_digits, .modulus Describe the base
.radix_at(p), .place_value(p) Radix and place value of position p (0 = least significant)
.parse(text), .from_int(n), .from_digits(digits, negative=False) Make a number (digits most significant first)
MixedRadixNumber(number, base=10) Number from text or an int
.value, .digits, .is_negative, .base Read a number
a + b, a - b, -a, abs(a), int(a), <, == Arithmetic and comparison on values
.to(base) Same value in another base
add(*numbers, base=10, to=None), sub(...), convert(number, to, base=10) String in, string out

Operands can be other numbers in any base, ints, or text in the left operand's base. The result uses the left operand's base.

Errors are MixedRadixError (a ValueError) with subclasses InvalidBaseError, InvalidNumberError and DigitOutOfRangeError.

License

MIT OR Apache-2.0, at your option.

Metadata

Release files for mixradix 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Change of provenance

The repository or configuration that created these release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Source distribution (sdist)

Source distribution for mixradix 0.2.0
File Size Uploaded Provenance Actions
mixradix-0.2.0.tar.gz 55.2 kB With provenance Details for mixradix-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mixradix 0.2.0
File Interpreter ABI Platform Actions
mixradix-0.2.0-py3-none-any.whl Python 3 none any Details for mixradix-0.2.0-py3-none-any.whl

Total release size: 76.0 kB

Release files / mixradix-0.2.0.tar.gz

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL mixradix-0.2.0.tar.gz
Size 55.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b82e9d6c58175e595d016e1132a3fd539424a3aeb011d22e42bfc6f1b121ee69
BLAKE2b-256 checksum
How to use checksums
507195972286ab1b4b9f0f3612d0e69997f5fe1b158c0eb145bf9f53a01c636f
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 Oct 14, 2026.

Transparency log

Release files / mixradix-0.2.0-py3-none-any.whl

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL mixradix-0.2.0-py3-none-any.whl
Size 20.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bc4d504e5a11c144744e049a850d46eea4911ed51d0820b940a40962b26baad4
BLAKE2b-256 checksum
How to use checksums
c8080acb0f6530f6ffddebf6b44e2a01ac7355596d50956f3cab5ccc5d4ebd33
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 Oct 14, 2026.

Transparency log

Security for mixradix 0.2.0

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.

Change of provenance

The repository and configuration that created this release differ from a previous release.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Select from 2 files

Attestation for mixradix-0.2.0.tar.gz

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 Oct 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Change of provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page