hmrc-rates
HMRC exchange rates as a Rust library.
The full published history is compiled into your binary (~450 KB of read-only data), so Rates::new() is free and infallible — no parsing, no I/O, no startup cost.
Conversions use exact rust_decimal arithmetic and are never rounded.
Install
[]
= "0.3"
= "1"
Quick start
use ;
use Decimal;
Data coverage
One Rates value holds all four series HMRC has published:
| Series | Coverage | Lookup |
|---|---|---|
| Monthly customs/VAT | 2014-02 — present, no gaps | monthly_rate(code, month) |
| Spot | Dec 2010 — present, years ending 31 Mar / 31 Dec | spot(YearEnd) |
| Yearly average | Dec 2010 — present, years ending 31 Mar / 31 Dec | average(YearEnd) |
| Weekly amendments | 2014-01 — 2016-04, complete (discontinued by HMRC) | weekly(date) |
Lookups are strict: a period HMRC never published is an error, never a silently substituted older rate. The error says why: unknown currency, period not available (with the loaded range), or currency absent from that period. Fallback is opt-in and visible:
let rate = rates.monthly_rate_or_earlier?;
rate.period // reveals which month was actually used
Currency codes are as published by HMRC, which is not always ISO 4217
E.g., Ecuador appears as ECS.
See docs/data-sources.md for where every rate comes from.
Features
| Feature | Default | Adds |
|---|---|---|
std |
yes | — |
bundled |
yes | the compiled-in history and Rates::new() |
http |
no | blocking Updater (ureq) with an on-disk cache |
serde |
no | compact string forms: "2026-07", "USD", "monthly" |
cli |
no | the hmrc-rates binary |
The core is no_std + alloc: default-features = false, features = ["bundled"] builds on wasm32-unknown-unknown.
Fresh rates (http)
Updater fetches whatever HMRC has published since the crate release and caches the files verbatim in the system cache directory.
Past periods are served from disk forever; amendable periods get a 24-hour TTL.
use Updater;
let updater = new;
// Offline fallback is explicit: stale rates should be a visible choice
let rates = updater.refreshed.unwrap_or_else;
Python
The same library is on PyPI as hmrc-rates (Python 3.10+):
=
= # also accepts datetime.date or "2025-08"
= # exact decimal.Decimal, you choose the rounding
=
See python/README.md for the full Python API.
Documentation
- API reference: docs.rs/hmrc-rates
- Data provenance: docs/data-sources.md
- Runnable examples:
examples/convert.rs,examples/fresh.rs
MSRV and licence
Rust 1.85. Licensed under MIT.
Disclaimer
This project is not affiliated with, endorsed by, or maintained by HMRC. Only the underlying rate data comes from HMRC.