Validera personnummer


Exempel på hur du kan kontrollera att ett svenskt personnummer. Exempel i JavaScript, XPATH och Ruby. Alla tre exempel testar inte endast att det är en korrekt kontrollsiffra utan även att datumet är riktigt.

Se även hur wikipedia beskriver Luhn-algoritmen, där finns även ett antal implementationer och på den engelska sidan så länkas det till ännu fler implementationer.

Checksiffran för International Securities Identification Number (ISIN) räknas ut på ett liknande vis.

All source code on this page is published under the MIT License as stipulated here.


JavaScript


Mata in ditt personnummer på formen 195703209999. Ditt inmatade personnummer lämnar aldrig din dator och kan inte, ens om jag ville, loggas. Om du kan läsa JavaScript/ECMAScript så behöver inte lita på mitt ord utan det är bara att göra "View source" och se att informationen inte skickas till servern.
JavaScript har tyvärr ganska begränsat stöd för datumvalidering. Det är det som funktionerna getYear och isDate löser.

(yyyymmddcccc)




XPATH


$pnum innehåller en sträng med ett personnummer på formen: yyyyMMddcccc
Kom till efter en fikapaus där XPATHs begränsningar diskuterades och där någon sade att han inte trodde att det gick att validera ett personnummer i det.

(validate-dateTime("yyyyMMdd", left($pnum, 8 )))
and
(((number(substring($pnum,3,1))*2) mod 9 + (floor(number(substring($pnum,3,1)) div 9)*9) + (number(substring($pnum,4,1))) +
(number(substring($pnum,5,1))*2) mod 9 + (floor(number(substring($pnum,5,1)) div 9)*9) + (number(substring($pnum,6,1))) +
(number(substring($pnum,7,1))*2) mod 9 + (floor(number(substring($pnum,7,1)) div 9)*9) + (number(substring($pnum,8,1))) +
(number(substring($pnum,9,1))*2) mod 9 + (floor(number(substring($pnum,9,1)) div 9)*9) + (number(substring($pnum,10,1))) +
(number(substring($pnum,11,1))*2) mod 9 + (floor(number(substring($pnum,11,1)) div 9)*9) + (number(substring($pnum,12,1)))
) mod 10 = 0)


Ruby


Inparametern är en sträng med ett personnummer på formen: yyyyMMddcccc

# Validera ett svenskt personnummer i Ruby
# jonelf har mail hos gmail punkt com
require 'date.rb'
pnum=ARGV[0]
if pnum==nil then
  print "Ange personnummer som yyyyMMddcccc.\n"
  exit
elsif pnum.length!=12 then
  print "Det skall vara 12 siffror."
else
  begin
  date=DateTime.strptime(pnum[0,4] +'-'+ pnum[4,2] +'-'+ pnum[6,2], '%F')
  rescue ArgumentError => argerr
    printf("%s är inte ett riktigt datum.\n", pnum[0,8])
    exit
  rescue Exception => ex
    print ex.to_s
    exit
  end

  checksum=0
  pos=0
  n=0
  0.upto(9) do |pos|
    n=pnum[pos+2].to_i-48
    if pos%2==0 then
      checksum+=(n*2).modulo(9)+(n/9)*9
    else
      checksum+=n
    end
  end

  if checksum%10==0 then
    print "Personnumret har ett korrekt datum och en korrekt checksumma.\n"
  else
    printf("Personnumret är inte korrekt. Checksumman skall vara jämnt delbar med 10 men är %d.\n", checksum)
  end
end

Pastie

DOS/cmd.exe/bat-fil


Fredrik M visar nedan att det även går att validera med en bat-fil.
"Om man bortser från formatkontroller och felhantering så går det att göra på tre rader. Det förutsätter i så fall att personnumret anges på formen ååmmddnnnn."
Observera att denna variant inte kontrollerar att det är ett korrekt datum.

SET N=%1

SET/a C=(90-2*%N:~0,1%%%10-2*%N:~0,1%/10-%N:~1,1%-2*%N:~2,1%%%10-2*%N:~2,1%/10-%N:~3,1%-2*%N:~4,1%%%10-2*%N:~4,1%/10-%N:~5,1%-2*%N:~6,1%%%10-2*%N:~6,1%/10-%N:~7,1%-2*%N:~8,1%%%10-2*%N:~8,1%/10)%%10
IF %C%==%N:~9,1% (ECHO %1 is OK) ELSE (ECHO %1 is invalid, last digit should be %C%.)