personnummer_erl
Validate, parse and format Swedish personal identity numbers (personnummer) in Erlang/OTP. Implements the personnummer specification v3.1.
Supports:
-
Regular personnummer (
YYMMDD-XXXX,YYYYMMDD-XXXX,+separator for ages 100+) - Coordination numbers (samordningsnummer, day = real day + 60)
- Interim numbers (T-numbers, opt-in via options map)
Installation
Once published to Hex, add to rebar.config:
{deps, [{personnummer_erl, "3.1.0"}]}.Until then, depend on the GitHub source:
{deps, [
{personnummer_erl,
{git, "https://github.com/denizdogan/personnummer_erl.git",
{branch, "main"}}}
]}.Requires Erlang/OTP 27 or newer.
Quick start
{ok, Pnr} = personnummer:parse(<<"198608134667">>),
true = personnummer:valid(<<"198608134667">>),
<<"860813-4667">> = personnummer:format(Pnr),
<<"198608134667">> = personnummer:format(Pnr, true),
{1986, 8, 13} = personnummer:get_date(Pnr),
19 = personnummer:get_century(Pnr),
<<"466">> = personnummer:get_serial(Pnr),
7 = personnummer:get_check(Pnr),
<<"-">> = personnummer:get_separator(Pnr),
true = personnummer:is_female(Pnr),
false = personnummer:is_coordination_number(Pnr),
false = personnummer:is_interim_number(Pnr).Options
%% Reject coordination numbers (samordningsnummer).
personnummer:parse(Input, #{allow_coordination_number => false}).
%% Accept interim numbers (T-numbers). Disabled by default.
personnummer:parse(<<"20000101T220">>, #{allow_interim_number => true}).
Defaults: allow_coordination_number => true,
allow_interim_number => false.
Compliance
The test suite is driven by JSON fixtures vendored from personnummer/meta. See test/testdata/README.md for refresh instructions.
Development
This project uses Mise for tool versions and task running.
$ mise compile
$ mise test
$ mise format # apply erlfmt
$ mise check # fmt-check, eunit, dialyzer
$ mise eq-all # eqwalizer (requires `elp` on PATH)
$ mise cover # test coverage report
$ mise docs # ex_doc
CI runs mise check plus codecov upload on OTP 27 and 28.
Conventions
-
Formatting:
erlfmt— CI enforces withrebar3 fmt --check. -
Type checking: dialyzer must report 0 warnings; eqwalizer must
report
NO ERRORS(run viaelp). -
Tests: prefer one focused EUnit function per behavior. The
compliance suite is driven by JSON fixtures vendored from
personnummer/meta; refresh
with
mise refresh-testdata. -
Changelog: describe user-facing changes under
[Unreleased]in CHANGELOG.md.
Releasing
-
Bump
vsninsrc/personnummer.app.srcand convert the[Unreleased]heading inCHANGELOG.mdto the new version. Commit and push. -
Run
mise checkto confirm everything is green. -
Run
mise publish. This publishes to Hex (requiresrebar3 hex user authonce), tagsvX.Y.Z, and pushes the tag.