Humanizer

Hex.pmHex DocsCILicense: MIT

Human-friendly formatting for Elixir. One flat module of pure functions that turn raw values into the strings you actually show to people — file sizes, durations, relative time, large numbers, thousands separators, ordinals, string truncation and list enumerations.

English-only, zero configuration, no global state. Replaces a handful of single-purpose dependencies (filesize, humanize_time, ad-hoc helpers) with one.

Installation

Add humanizer to your mix.exs:

def deps do
[
{:humanizer, "~> 0.2.0"}
]
end

Documentation is on HexDocs.

Quick start

Humanizer.bytes(2_456_789)
# => "2.5 MB"
Humanizer.bytes(2_456_789, system: :binary)
# => "2.3 MiB"
Humanizer.duration(3725)
# => "1 hour, 2 minutes"
Humanizer.duration(45, format: :short)
# => "45s"
Humanizer.relative_time(~U[2026-05-13 10:00:00Z], ~U[2026-05-15 10:00:00Z])
# => "2 days ago"
Humanizer.relative_time(~U[2026-05-13 10:00:00Z], ~U[2026-05-15 10:00:00Z], format: :short)
# => "2d ago"
Humanizer.number(1_234_567)
# => "1.2M"
Humanizer.delimit(1_234_567)
# => "1,234,567"
Humanizer.ordinal(23)
# => "23rd"
Humanizer.truncate("the quick brown fox", 9)
# => "the quic…"
Humanizer.list_join(["Alice", "Bob", "Charlie"])
# => "Alice, Bob and Charlie"
Humanizer.list_join(["Alice", "Bob", "Charlie", "Dave", "Eve"], max: 2)
# => "Alice, Bob and 3 others"

Every function takes its options as a keyword list — there is no Application env and nothing to configure globally.

API

FunctionExampleResult
bytes/2Humanizer.bytes(2_456_789)"2.5 MB"
duration/2Humanizer.duration(3725)"1 hour, 2 minutes"
relative_time/2,3Humanizer.relative_time(past, now)"2 days ago"
number/2Humanizer.number(1_234_567)"1.2M"
delimit/2Humanizer.delimit(1_234_567)"1,234,567"
ordinal/1Humanizer.ordinal(23)"23rd"
truncate/3Humanizer.truncate("the quick brown fox", 9)"the quic…"
list_join/2Humanizer.list_join(["a", "b", "c"])"a, b and c"

Numbers use one consistent rule: round-half-away-from-zero with a single fractional digit by default (override with :precision). Output is never in scientific notation, for any input up to 10 ** 15.

Localization

English only. This is deliberate. Real localization means pluralization, gender, grammatical cases and locale-specific decimal separators — a single bytes/1 under locales is a project of its own.

If you need serious internationalization, use ex_cldr and ex_cldr_numbers. Localization may arrive in a later version as an optional layer, but it is out of scope here.

Comparison

Humanizer is not "better than everything". It replaces four or five small dependencies with one, if English output is enough for you.

You needUse
One package for all small English formattingHumanizer
Only file sizesfilesize, sizeable
Times/durations with i18ntimex + manual localization
Pluralize, singularize, camel/snake caseinflex
Full number/date localization (CLDR)ex_cldr + ex_cldr_numbers
Parsing human time back into valueschronic

Roadmap

v0.2.0 added thousands separators, string truncation, list limits and richer relative time. Remaining planned work (an optional localization layer) is tracked in ROADMAP.md.

License

MIT. See LICENSE.