humfmt
Ergonomic human-readable formatting toolkit for Rust
humfmt turns raw machine values into readable text without turning formatting
into a side quest.
use Humanize;
println!; // 1.5M
println!; // 1.5KB
println!; // 42.3%
println!; // 21st
That's it. Import the trait, call a method, done.
What it does
| Input | Formatter | Output |
|---|---|---|
15320 |
number |
15.3K |
1536 |
bytes |
1.5KB |
0.423 |
percent |
42.3% |
21 |
ordinal |
21st |
3661s |
duration |
1h 1m |
90s |
ago |
1m 30s ago |
["red", "green", "blue"] |
list |
red, green, and blue |
All formatters implement Display — no intermediate heap strings. Write directly into any buffer.
Quick start
[]
= "0.5"
use Humanize;
use Duration;
// Extension trait — shortest path
println!; // 1.5M
println!; // 1.5KB
println!; // 42.3%
println!; // 42nd
println!; // 1m 30s ago
// Free functions — same result, no trait import needed
println!; // 15.3K
println!; // 1.5KB
println!; // 42.3%
println!; // 21st
println!; // 1h 1m
println!; // red, green, and blue
Customization
Every formatter has a *_with variant that takes an options builder:
use Duration;
use ;
// Bytes: binary units, space before suffix
let disk = 1536_u64.human_bytes_with;
println!; // 1.5 KiB
// Bytes: bits mode for network speeds
let speed = 1_500_000_u64.human_bytes_with;
println!; // 12Mb
// Bytes: always show in megabytes
let fixed = 1_500_000_u64.human_bytes_with;
println!; // 1.5MB
// Bytes: clamp minimum to KB (500 bytes -> 0.5 KB)
let clamped = 500_u64.human_bytes_with;
println!; // 0.5KB
// Numbers: long-form
let n = 15_320.human_number_with;
println!; // 15.32 thousand
// Numbers: full number with digit grouping
let full = 1_234_567.human_number_with;
println!; // 1,234,567
// Numbers: significant digits
let sig = 12345.human_number_with;
println!; // 12.3K
// Numbers: forced sign for deltas
let delta = 1500.human_number_with;
println!; // +1.5K
// Numbers: rounding modes
use RoundingMode;
let floor = 1_900.human_number_with;
println!; // 1K
// Percentages: 2 decimal places, fixed precision
let ratio = 0.425_f64.human_percent_with;
println!; // 42.50%
// Percentages: forced sign
let change = 0.15_f64.human_percent_with;
println!; // +15%
// Duration: long-form, 3 units
let elapsed = from_secs.human_duration_with;
println!; // 1 hour 1 minute 5 seconds
// Relative time: 3 units
let ago = from_secs.human_ago_with;
println!; // 1h 1m 5s ago
Lists
use ;
// Default: Oxford comma
assert_eq!;
// No serial comma
let no_oxford = list_with;
assert_eq!;
// Custom conjunction
let plus = list_with;
assert_eq!;
Locales
English is the default. Russian and Polish are available behind feature flags:
[]
= { = "0.5", = ["russian", "polish"] }
use ;
use ;
// Russian: comma decimal separator, space group separator, inflected suffixes
println!; // 15,3 тыс.
println!; // 1 тысяча
println!; // 5 тысяч
// Polish
println!; // 15,3 tys.
println!; // 21.
Custom locale for anything else:
use ;
let locale = english
.short_suffix
.separators;
println!; // 15,3k
Performance
humfmt is designed to be cheap in hot paths:
- Zero-alloc
Display— formatters write directly into the output, no intermediateString - O(1) scaling — integer path uses
ilog10, float path uses IEEE 754 exponent no_std— works without the standard library- No dependencies — core crate has zero required dependencies
See BENCHMARKS.md for comparisons against humansize, bytesize, byte-unit, prettier-bytes, human_format, humantime, timeago, and others.
Feature flags
| Feature | Default | Description |
|---|---|---|
std |
✓ | Standard library build |
english |
✓ | English locale |
russian |
Russian locale pack | |
polish |
Polish locale pack | |
chrono |
chrono::TimeDelta / DateTime adapters |
|
time |
time::Duration / OffsetDateTime adapters |
For no_std targets:
[]
= { = "0.5", = false }
With all locales:
[]
= { = "0.5", = ["russian", "polish"] }
Documentation
- docs.rs — full API reference
- BENCHMARKS.md — performance comparisons and methodology
- CHANGELOG.md — what changed and when
- TODO.md — planned features and known issues
- examples/ — runnable examples
- tests/ — integration and property tests
Philosophy
This crate follows one simple rule:
Human formatting should feel stupidly easy.
No giant config ceremony. No formatting gymnastics. No "why is this so annoying?" moments.
Just:
println!;
and move on with your life.
License
MIT.