v0.2.0
Complete rewrite. Breaking changes throughout — not compatible with 0.1.x.
What's new
- All four HMRC rate series, not just monthly: monthly customs/VAT, spot, yearly average, and the discontinued 2014-2016 weekly amendments, all through one
Ratesvalue. - Deeper history: monthly back to 2014-02 (150 months), spot and average back to Dec 2010 (32 periods each, years ending 31 Mar / 31 Dec), backfilled from the UK Government Web Archive.
- Zero-cost bundling: the full dataset compiles into static tables at build time —
Rates::new()is free and infallible, no parsing or I/O at startup. - Exact arithmetic, strict lookups: conversions use
rust_decimaland are never rounded; an unpublished period is always an error, never a silently substituted older rate. An explicit, opt-in fallback (monthly_rate_or_earlier) is available when you want it. - Optional live updates (
httpfeature): a blockingUpdaterfetches newly published periods from the Trade Tariff API, with a verbatim on-disk cache. no_std+alloccore: builds onwasm32-unknown-unknownwith just thebundledfeature.serdefeature for compact string forms ("2026-07","USD","monthly").- Optional CLI (
clifeature):hmrc-rates convert,rate,list,currencies. - CI now checks for new HMRC rates daily and auto-releases patch versions.
Example
use hmrc_rates::{Month, Rates, YearEnd};
use rust_decimal::Decimal;
let rates = Rates::new();
let rate = rates.monthly_rate("USD", Month::new(2025, 8).unwrap())?;
println!("{}", rate.to_gbp(Decimal::from(2500)).round_dp(2)); // £1846.24
let eur = rates.average(YearEnd::march(2025))?.rate("EUR")?;
println!("{}", eur.units_per_gbp()); // 1.1880Coverage
| Series | Range |
|---|---|
| Monthly | 2014-02 - present |
| Spot | Dec 2010 - present (31 Mar / 31 Dec) |
| Yearly average | Dec 2010 - present (31 Mar / 31 Dec) |
| Weekly amendments | 2014-01-08 - 2016-04-27 (discontinued) |
Full details: README · data sources · API docs
MSRV 1.85 · MIT