Blogginlägg

Introducerar ActiveLogin.Identity.Swedish

Av Viktor Andersson | Blogg | 1 februari 2019

Idag introducerar vi ActiveLogin.Identity.Swedish 2.0.0, ett bibliotek för parsning, validering och normalisering av svenska personnummer för .NET. Enkelt att installera från NuGet och all källkod tillgänglig på GitHub.


I flera kundprojekt har vi haft ett behov att hantera personnummer. I sin enklaste form kan det handla om att en användare matar in ett personnummer i ett formulär, eller att vi tar emot ett personnummer från ett annat system.

När vi såg behovet av validering och normalisering av personnummer i flera projekt undersökte vi vad för bibliotek som fanns tillgänliga. De vi hittade byggde antingen på enkla Regex som inte validerade checksumman, eller så kunde de endast validera men inte normalisera personnumret. Därför valde vi att själva implementera en lösning som skulle lösa dessa problem.

ActiveLogin.Identity.Swedish är byggt i .NET Standard och kan därför användas i t.ex. .NET Core och .NET Framework. Det är enkelt att installera och köra på flertalet plattformar så som Windows, Linux och macOS.

Biblioteket hanterar både personnummer med sekelsiffra (12-siffror YYYYMMDDBBBC) och utan (10 siffror YYMMDD-BBBC, YYMMDD+BBBC). Alla ogiltiga tecken och blanksteg tvättas bort före parsning och biblioteket kan parsa alla inputsträngar som innehåller ett giltigt personnummer med 10 eller 12 siffror. Självklart verifieras även checksumman för att säkerställa att personnummret är korrekt. För exempel på giltiga och ogiltiga input se testerna.

Exempelanvändning C#

  1. Installera paketet, t.ex. med dotnet cli
dotnet add ActiveLogin.Identity.Swedish
  1. Parsa ett personnummer
using ActiveLogin.Identity.Swedish;

if (SwedishPersonalIdentityNumber.TryParse("990807-2391", out var personalIdentityNumber))
{
    Console.WriteLine($"Personnummer med 10 siffror: {personalIdentityNumber.To10DigitString()}");
    Console.WriteLine($"Personnummer med 12 siffror: {personalIdentityNumber.To12DigitString()}");
}
else
{
    Console.WriteLine("Personnumret är inte giltigt");
}

// Output:
// Personnummer (10 siffror): 990807-2391
// Personnummer representerat med 12 siffror: 199908072391

Exempelanvändning F#

Då biblioteket är implementerat i F# exponerar vi även ett F#-vänligt api för den som så föredrar.

  1. Installera paketet, förslagsvis med paket
paket add ActiveLogin.Identity.Swedish`
  1. Parsa ett personnummer
open ActiveLogin.Identity.Swedish.FSharp

let pin = "990807-2391" |> SwedishPersonalIdentityNumber.parse |> Error.handle
pin |> SwedishPersonalIdentityNumber.to10DigitString |> printfn "Personnummer med 10 siffror: %s"
pin |> SwedishPersonalIdentityNumber.to12DigitString |> printfn "Personnummer med 12 siffror: %s"

// Output:
// Personnummer (10 siffror): 990807-2391
// Personnummer representerat med 12 siffror: 199908072391

Hjälpfunktioner

Biblioteket innehåller även ett antal hjälpfunktioner som kan användas för att läsa ut data från ett personnummer, t.ex. födelsedatum, ålder och kön. Eftersom det inte finns något sätt att garantera att dessa uppgifter är korrekta har vi valt att ge dessa funktioner ett Hints-suffix.

I C# är metoderna exponerade som extensionmetoder och ligger i namespacet ActiveLogin.Identity.Swedish.Extensions. De kan användas enligt:

using ActiveLogin.Identity.Swedish;
using ActiveLogin.Identity.Swedish.Extensions;

var pin = new SwedishPersonalIdentityNumber(1999, 8, 7, 239, 1);
Console.WriteLine($"Födelsedatum: {pin.GetDateOfBirthHint().ToShortDateString()}");
Console.WriteLine($"Ålder: {pin.GetAgeHint().ToString()}");
Console.WriteLine($"Kön: {pin.GetGenderHint().ToString()}");

// Output:
// Födelsedatum: 8/7/99
// Ålder: 19
// Kön: Male

I F# hittas funktionerna i en Hints-modul:

open ActiveLogin.Identity.Swedish.FSharp

let pin =
    { Year = 1999
      Month = 8
      Day = 7
      BirthNumber = 239
      Checksum = 1 }
    |> SwedishPersonalIdentityNumber.create
    |> Error.handle

pin 
|> SwedishPersonalIdentityNumber.Hints.getDateOfBirthHint 
|> fun date -> date.ToShortDateString() 
|> printfn "Födelsedatum: %s" 
pin |> SwedishPersonalIdentityNumber.Hints.getAgeHint |> Option.iter (printfn "Ålder: %i")
pin |> SwedishPersonalIdentityNumber.Hints.getGenderHint |> printfn "Kön: %A"

// Output:
// Födelsedatum: 8/7/99
// Ålder: 19
// Kön: Male

Tester

Implementationen har arbetats fram testdrivet och idag finns mer än 200 tester som säkerställer att vi följer Folkbokföringslagens definition (FOL 18 §). För att vara kompatibel med GDPR används de testpersonnummer som Skatteverket tillhandahåller som öppen data.

Vill du vara med och bidra till utvecklingen av Active Login?

ActiveLogin är ett Open Source projekt och vi ser gärna att fler är med och bidrar. All källkod finns tillgänglig på GitHub under MIT-licensen. Grundläggande kunskap om Git och GitHub krävs för att komma igång. Skicka in dina kodändringar som en Pull request. Glöm inte att skriva en utförlig beskrivning och att tillhandahålla tester som täcker de ändringar du har gjort. Har du idéer om ny funktionalitet eller stött på problem? Skapa en ny Issue för att starta en diskussion om ämnet.

Sist men inte minst, ge gärna vårt repo en stjärna om du gillar projektet :)

Författare

Det här blogginlägget är komponerat av Viktor Andersson, en av huvudutvecklarna bakom ActiveLogin.Identity, till vardags IT-konsult och systemutvecklare på Active Solution.

Till inlägget