Skip to content
Snippets Groups Projects
Commit 4569fc42 authored by Tore.Brede's avatar Tore.Brede
Browse files

Merge branch 'GREG-60_national_id_number_validation' into 'master'

GREG-60: Adding a utility method for validation national ID numbers

See merge request !86
parents 8e1173be 65ab6c83
No related branches found
No related tags found
1 merge request!86GREG-60: Adding a utility method for validation national ID numbers
Pipeline #96018 passed
import pytest
from greg.utils import is_valid_norwegian_national_id_number
test_data = [
# Mostly random numbers from http://www.fnrinfo.no/Verktoy/FinnLovlige_Tilfeldig.aspx
("13063626672", False, True),
("09095114412", False, True),
("02048538757", False, True),
("12042335418", False, True),
("16061739592", False, True),
("05087648003", False, True),
("22051602882", False, True),
("11120618212", False, True),
("19045838326", False, True),
("17041579641", False, True),
("20064632362", False, True),
("12118913939", False, True),
("04062141242", False, True),
("10075049345", False, True),
("17093749006", False, True),
("07049226653", False, True),
("25110899915", False, True),
("01014000719", False, True),
("19035205023", False, True),
("12345678912", False, False),
("410185", True, False),
# Test cases from https://github.com/navikt/fnrvalidator/blob/master/tests/fnr.spec.js
("13097248022", False, True),
("29029648784", False, True),
("29020075838", False, True),
("29020112345", False, False),
("15021951940", False, True),
("1234567890", False, False),
("123456789101", False, False),
("1234567891A", False, False),
("13097248032", False, False),
("13097248023", False, False),
("32127248022", False, False),
("13137248022", False, False),
("53097248016", True, True),
]
@pytest.mark.parametrize("test_number, is_dnumber, valid", test_data)
def test_register_guest(test_number, is_dnumber, valid):
assert is_valid_norwegian_national_id_number(test_number, is_dnumber) == valid
import re
from datetime import date
def camel_to_snake(s: str) -> str:
"""Turns `FooBar` into `foo_bar`."""
return re.sub("([A-Z])", "_\\1", s).lower().lstrip("_")
def is_valid_norwegian_national_id_number(input_digits: str, is_dnumber: bool) -> bool:
"""
Checks whether input_digits is a valid national ID number of D-number.
It is based on the code found here:
https://github.com/navikt/fnrvalidator/blob/master/src/validator.js
"""
return (
_check_correct_number_of_digits(input_digits)
and _compute_checksum(input_digits)
and _check_birthdate(input_digits, is_dnumber)
)
def _check_correct_number_of_digits(input_digits: str) -> bool:
return re.search("^\\d{11}$", input_digits) is not None
def _check_birthdate(digits: str, is_dnumber: bool) -> bool:
if is_dnumber:
# First number has been increased by 4, look here for an explanation of what the
# numbers in the D-number mean:
# https://www.skatteetaten.no/person/utenlandsk/norsk-identitetsnummer/d-nummer/
digits = str((int(digits[0:1]) - 4)) + digits[1:]
day = int(digits[0:2])
month = int(digits[2:4])
year = int(digits[4:6])
# Year 0 should mean 2000, not 1900
if year == 0:
year = 2000
try:
# Try to create a date object, it will fail is the date is not valid
date(year, month, day)
except ValueError:
# Not a valid date
return False
return True
def _compute_checksum(input_digits: str) -> bool:
d = [int(s) for s in input_digits]
k1 = 11 - (
(
3 * d[0]
+ 7 * d[1]
+ 6 * d[2]
+ 1 * d[3]
+ 8 * d[4]
+ 9 * d[5]
+ 4 * d[6]
+ 5 * d[7]
+ 2 * d[8]
)
% 11
)
k2 = 11 - (
(
5 * d[0]
+ 4 * d[1]
+ 3 * d[2]
+ 2 * d[3]
+ 7 * d[4]
+ 6 * d[5]
+ 5 * d[6]
+ 4 * d[7]
+ 3 * d[8]
+ 2 * k1
)
% 11
)
if k1 == 11:
k1 = 0
if k2 == 11:
k2 = 0
return k1 < 10 and k2 < 10 and k1 == d[9] and k2 == d[10]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment