Skip to main content

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.1.0

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

Source distribution (sdist)

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

Built distribution (wheel)

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

Total release size: 71.1 kB

Release files / mixradix-0.1.0.tar.gz

Download URL mixradix-0.1.0.tar.gz
Size 53.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9696d93df8729f58e4a266714ab9c152b78f696fed6217028305be63230711a3
BLAKE2b-256 checksum
How to use checksums
5749e74cddf0bbe01537403830949ba993616a72ae4043e1a519c9e49d831e98
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 13, 2026.

Transparency log

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

Download URL mixradix-0.1.0-py3-none-any.whl
Size 17.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b7915e7a7598291036494897c0ca6fdc18d8de06744dcd5f86cb29a30f19b786
BLAKE2b-256 checksum
How to use checksums
7f2afed507856e5fd0770a98904491a387f5974565bd5d942b1eafe1f52cf595
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 13, 2026.

Transparency log

Security for mixradix 0.1.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mixradix-0.1.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 13, 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.1.0 This release

2 release files Full 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