python-stdnum branch master updated. 1.13-8-gdf9f922
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
python-stdnum branch master updated. 1.13-8-gdf9f922
- From: Commits of the python-stdnum project <python-stdnum-commits [at] lists.arthurdejong.org>
- To: python-stdnum-commits [at] lists.arthurdejong.org
- Reply-to: python-stdnum-users [at] lists.arthurdejong.org, python-stdnum-commits [at] lists.arthurdejong.org
- Subject: python-stdnum branch master updated. 1.13-8-gdf9f922
- Date: Sun, 1 Mar 2020 21:22:34 +0100 (CET)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-stdnum".
The branch, master has been updated
via df9f9222f97ad2cccb3dd93499ae9e7768584565 (commit)
from 4500881cf6aad1ddd1ad8b3bcc1495f5a48c45cf (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://arthurdejong.org/git/python-stdnum/commit/?id=df9f9222f97ad2cccb3dd93499ae9e7768584565
commit df9f9222f97ad2cccb3dd93499ae9e7768584565
Author: Leon Sandøy <leon.haland@gmail.com>
Date: Fri Jan 31 17:32:00 2020 +0100
Implement get_birth_date() for no.fodselsnummer
This adds a function that allows you to determine a persons birth date
from a Norwegian fødselsnummer.
This also accounts for D-numbers, H-numbers, and FH-numbers, which
contain special exceptions and modifications to the birthdate portion of
the number.
Most of the information this is based on was found here:
https://no.wikipedia.org/wiki/F%C3%B8dselsnummer#H-nummer
It also updates the list of valid fødselsnummer in the tests, since this
list contained many numbers that are not valid by this new validation
that now accounts for dates.
Additionally, this updates all tests that were failing under the new
validation, and adds a few new tests to bring the coverage to 100%.
Closes https://github.com/arthurdejong/python-stdnum/pull/187
diff --git a/stdnum/no/fodselsnummer.py b/stdnum/no/fodselsnummer.py
index ce1ef13..50d27b6 100644
--- a/stdnum/no/fodselsnummer.py
+++ b/stdnum/no/fodselsnummer.py
@@ -3,6 +3,7 @@
#
# Copyright (C) 2018 Ilya Vihtinsky
# Copyright (C) 2018 Arthur de Jong
+# Copyright (C) 2020 Leon Sandøy
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -29,18 +30,20 @@ More information:
* https://no.wikipedia.org/wiki/F%C3%B8dselsnummer
* https://en.wikipedia.org/wiki/National_identification_number#Norway
->>> validate('684131 52112')
-'68413152112'
->>> get_gender('684131 52112')
-'M'
->>> validate('684131 52123')
+>>> validate('151086 95088')
+'15108695088'
+>>> get_gender('151086-95088')
+'F'
+>>> validate('15108695077')
Traceback (most recent call last):
...
InvalidChecksum: ...
->>> format('68413152112')
-'684131 52112'
+>>> format('15108695077')
+'151086 95077'
"""
+import datetime
+
from stdnum.exceptions import *
from stdnum.util import clean, isdigits
@@ -72,6 +75,42 @@ def get_gender(number):
return 'F'
+def get_birth_date(number):
+ """Determine and return the birth date."""
+ number = compact(number)
+ day = int(number[0:2])
+ month = int(number[2:4])
+ year = int(number[4:6])
+ individual_digits = int(number[6:9])
+ # Raise a more useful exception for FH numbers
+ if day >= 80:
+ raise InvalidComponent(
+ 'This number is an FH-number, and does not contain birth date
information by design.')
+ # Correct the birth day for D-numbers. These have a modified first digit.
+ # https://no.wikipedia.org/wiki/F%C3%B8dselsnummer#D-nummer
+ if day > 40:
+ day -= 40
+ # Correct the birth month for H-numbers. These have a modified third digit.
+ # https://no.wikipedia.org/wiki/F%C3%B8dselsnummer#H-nummer
+ if month > 40:
+ month -= 40
+ if individual_digits < 500:
+ year += 1900
+ elif 500 <= individual_digits < 750 and year >= 54:
+ year += 1800
+ elif 500 <= individual_digits < 1000 and year < 40:
+ year += 2000
+ elif 900 <= individual_digits < 1000 and year >= 40:
+ year += 1900
+ else:
+ # The birth century falls outside all defined ranges.
+ raise InvalidComponent('The birthdate century cannot be determined')
+ try:
+ return datetime.date(year, month, day)
+ except ValueError:
+ raise InvalidComponent('The number does not contain valid birth date
information.')
+
+
def validate(number):
"""Check if the number is a valid birth number."""
number = compact(number)
@@ -83,6 +122,9 @@ def validate(number):
raise InvalidChecksum()
if number[-1] != calc_check_digit2(number):
raise InvalidChecksum()
+ if get_birth_date(number) > datetime.date.today():
+ raise InvalidComponent(
+ 'The birth date information is valid, but this person has not been
born yet.')
return number
diff --git a/tests/test_no_fodselsnummer.doctest
b/tests/test_no_fodselsnummer.doctest
index abec35e..bca21cf 100644
--- a/tests/test_no_fodselsnummer.doctest
+++ b/tests/test_no_fodselsnummer.doctest
@@ -2,6 +2,7 @@ test_no_fodselsnummer.doctest - more detailed doctests for
stdnum.no.fodselsnumm
Copyright (C) 2018 Ilya Vihtinsky
Copyright (C) 2018 Arthur de Jong
+Copyright (C) 2020 Leon Sandøy
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -40,13 +41,13 @@ These numbers should be detected as male or female.
The last two check digits are validated independently of each other.
->>> fodselsnummer.is_valid('42485176432')
+>>> fodselsnummer.is_valid('26111593816')
True
->>> fodselsnummer.is_valid('42485176431') # only change last digit
+>>> fodselsnummer.is_valid('26111593817') # only change last digit
False
->>> fodselsnummer.is_valid('42485176412') # only change first digit
+>>> fodselsnummer.is_valid('26111593826') # only change first digit
False
->>> fodselsnummer.is_valid('42485176416') # change first, correct second
+>>> fodselsnummer.is_valid('26111593875') # change first, correct second
False
@@ -62,50 +63,56 @@ Traceback (most recent call last):
InvalidFormat: ...
-These have been found online and should all be valid numbers.
+The birth date can be extracted from the number:
+
+>>> fodselsnummer.get_birth_date('11111598403')
+datetime.date(2015, 11, 11)
+>>> fodselsnummer.get_birth_date('151086-95088')
+datetime.date(1986, 10, 15)
+>>> fodselsnummer.get_birth_date('180615 92527')
+datetime.date(2015, 6, 18)
+>>> fodselsnummer.get_birth_date('10 04 87 44 732')
+datetime.date(1987, 4, 10)
+>>> fodselsnummer.get_birth_date('13-04-99-58441')
+datetime.date(1899, 4, 13)
+
+
+Invalid dates are rejected:
+
+>>> fodselsnummer.validate('19575770838')
+Traceback (most recent call last):
+ ...
+InvalidComponent: The number does not contain valid birth date information.
+>>> fodselsnummer.get_birth_date('45014054018')
+Traceback (most recent call last):
+ ...
+InvalidComponent: The birthdate century cannot be determined
+>>> fodselsnummer.get_birth_date('82314251342')
+Traceback (most recent call last):
+ ...
+InvalidComponent: This number is an FH-number, and does not contain birth date
information by design.
+>>> fodselsnummer.validate('19102270846')
+Traceback (most recent call last):
+ ...
+InvalidComponent: The birth date information is valid, but this person has not
been born yet.
+
+
+These should all be valid numbers.
>>> numbers = '''
...
-... 11027794191
-... 11051996811
-... 19575770838
-... 21918484865
-... 24396859900
-... 27213364885
-... 27389446152
-... 30383131118
-... 30777674125
-... 31042639152
-... 34831582121
-... 39043009846
-... 40070897972
-... 40673759612
-... 42115114470
-... 42485176432
-... 42957044500
-... 44207789809
-... 45014054018
-... 46929323343
-... 50067834221
-... 56403643756
-... 56653047547
-... 63282310041
-... 68413152112
-... 70031073454
-... 70341666064
-... 70624830529
-... 71494457037
-... 71946503120
-... 75442702381
-... 79189404641
-... 79318270827
-... 82938389280
-... 83814827871
-... 89829529360
-... 92782833709
-... 95700625908
-... 96517753502
-... 98576936818
+... 100487 45526
+... 10048744732
+... 10048745364
+... 111115984-03
+... 151086-95088
+... 18-06-15-92527
+... 231140-38547
+... 23114048690
+... 26 11 15 940 14
+... 26111593816
+... 26111594286
+... 26111594448
...
... '''
>>> [x for x in numbers.splitlines() if x and not fodselsnummer.is_valid(x)]
-----------------------------------------------------------------------
Summary of changes:
stdnum/no/fodselsnummer.py | 56 ++++++++++++++++++---
tests/test_no_fodselsnummer.doctest | 97 ++++++++++++++++++++-----------------
2 files changed, 101 insertions(+), 52 deletions(-)
hooks/post-receive
--
python-stdnum
- python-stdnum branch master updated. 1.13-8-gdf9f922,
Commits of the python-stdnum project