lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.20-9-gaf3a728

[Date Prev][Date Next] [Thread Prev][Thread Next]

python-stdnum branch master updated. 1.20-9-gaf3a728



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  af3a728f6f3533da7ad398614163cc0f776dcb95 (commit)
      from  0da257c6646c2565eeb1820e3d2a1a1d95d12884 (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=af3a728f6f3533da7ad398614163cc0f776dcb95

commit af3a728f6f3533da7ad398614163cc0f776dcb95
Author: Jeff Horemans <jeff.horemans@vortex-financials.be>
Date:   Tue Jul 4 13:57:39 2023 +0200

    Add Belgian SSN number
    
    Closes https://github.com/arthurdejong/python-stdnum/pull/438

diff --git a/stdnum/be/ssn.py b/stdnum/be/ssn.py
new file mode 100644
index 0000000..65045c1
--- /dev/null
+++ b/stdnum/be/ssn.py
@@ -0,0 +1,155 @@
+# coding: utf-8
+# ssn.py - function for handling Belgian social security numbers
+#
+# Copyright (C) 2023-2024 Jeff Horemans
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+"""SSN, INSZ, NISS (Belgian social security number).
+
+The Belgian social security identification number, also known as the INSZ
+number (Identificatienummer van de sociale zekerheid), NISS number (Numéro
+d'identification de la sécurité sociale) or ENSS number (Erkennungsnummer
+der sozialen Sicherheit), is the unique identification number of a person
+working in or covered for social benefits in Belgium.
+
+For Belgian residents, the number is identical to their Belgian National
+Number (Rijksregisternummer, Numéro National).
+For non-residents, the number is identical to their Belgian BIS number.
+
+Both numbers consists of 11 digits and encode a person's date of birth and
+gender. It encodes the date of birth in the first 6 digits in the format
+YYMMDD. The following 3 digits represent a counter of people born on the same
+date, separated by sex (odd for male and even for females respectively). The
+final 2 digits form a check number based on the 9 preceding digits.
+
+
+More information:
+
+* https://www.socialsecurity.be/site_nl/employer/applics/belgianidpro/index.htm
+* https://overheid.vlaanderen.be/personeel/regelgeving/insz-nummer
+* https://www.ksz-bcss.fgov.be/nl/project/rijksregisterksz-registers
+
+>>> compact('85.07.30-033 28')
+'85073003328'
+>>> compact('98.47.28-997.65')
+'98472899765'
+>>> validate('85 07 30 033 28')
+'85073003328'
+>>> validate('98 47 28 997 65')
+'98472899765'
+>>> validate('17 07 30 033 84')
+'17073003384'
+>>> validate('01 49 07 001 85')
+'01490700185'
+>>> validate('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+
+>>> guess_type('85.07.30-033 28')
+'nn'
+>>> guess_type('98.47.28-997.65')
+'bis'
+
+>>> format('85073003328')
+'85.07.30-033.28'
+>>> get_birth_date('85.07.30-033 28')
+datetime.date(1985, 7, 30)
+>>> get_birth_year('85.07.30-033 28')
+1985
+>>> get_birth_month('85.07.30-033 28')
+7
+>>> get_gender('85.07.30-033 28')
+'M'
+
+>>> format('98472899765')
+'98.47.28-997.65'
+>>> get_birth_date('98.47.28-997.65')
+datetime.date(1998, 7, 28)
+>>> get_birth_year('98.47.28-997.65')
+1998
+>>> get_birth_month('98.47.28-997.65')
+7
+>>> get_gender('98.47.28-997.65')
+'M'
+
+"""
+
+from stdnum.be import bis, nn
+from stdnum.exceptions import *
+
+
+_ssn_modules = (nn, bis)
+
+
+def compact(number):
+    """Convert the number to the minimal representation. This strips the
+    number of any valid separators and removes surrounding whitespace."""
+    return nn.compact(number)
+
+
+def validate(number):
+    """Check if the number is a valid Belgian SSN. This searches for
+    the proper sub-type and validates using that."""
+    try:
+        return bis.validate(number)
+    except InvalidComponent:
+        # Only try NN validation in case of an invalid component,
+        # other validation errors are shared between BIS and NN
+        return nn.validate(number)
+
+
+def is_valid(number):
+    """Check if the number is a valid Belgian SSN number."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+def guess_type(number):
+    """Return the Belgian SSN type for which this number is valid."""
+    for mod in _ssn_modules:
+        if mod.is_valid(number):
+            return mod.__name__.rsplit('.', 1)[-1]
+
+
+def format(number):
+    """Reformat the number to the standard presentation format."""
+    return nn.format(number)
+
+
+def get_birth_year(number):
+    """Return the year of the birth date."""
+    return nn.get_birth_year(number)
+
+
+def get_birth_month(number):
+    """Return the month of the birth date."""
+    return nn.get_birth_month(number)
+
+
+def get_birth_date(number):
+    """Return the date of birth."""
+    return nn.get_birth_date(number)
+
+
+def get_gender(number):
+    """Get the person's gender ('M' or 'F')."""
+    for mod in _ssn_modules:
+        if mod.is_valid(number):
+            return mod.get_gender(number)
diff --git a/tests/test_be_ssn.doctest b/tests/test_be_ssn.doctest
new file mode 100644
index 0000000..88ff1e2
--- /dev/null
+++ b/tests/test_be_ssn.doctest
@@ -0,0 +1,205 @@
+test_be_ssn.doctest - more detailed doctests for stdnum.be.ssn module
+
+Copyright (C) 2022 Arthur de Jong
+Copyright (C) 2023 Jeff Horemans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA
+
+
+This file contains more detailed doctests for the stdnum.be.ssn module. It
+tries to test more corner cases and detailed functionality that is not
+really useful as module documentation.
+
+>>> from stdnum.be import ssn
+
+
+Extra tests for getting birth date, year and/or month from National Number.
+
+
+>>> ssn.get_birth_date('85.07.30-033 28')
+datetime.date(1985, 7, 30)
+>>> ssn.get_birth_year('85.07.30-033 28')
+1985
+>>> ssn.get_birth_month('85.07.30-033 28')
+7
+>>> ssn.get_birth_date('17 07 30 033 84')
+datetime.date(2017, 7, 30)
+>>> ssn.get_birth_year('17 07 30 033 84')
+2017
+>>> ssn.get_birth_month('17 07 30 033 84')
+7
+>>> ssn.get_birth_date('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_year('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_month('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_date('00000100166')  # Exact date of birth unknown 
(fictitious date case 1900-00-01)
+>>> ssn.get_birth_year('00000100166')
+>>> ssn.get_birth_month('00000100166')
+>>> ssn.get_birth_date('00000100195')  # Exact date of birth unknown 
(fictitious date case 2000-00-01)
+>>> ssn.get_birth_year('00000100195')
+>>> ssn.get_birth_month('00000100195')
+>>> ssn.get_birth_date('00000000128')  # Only birth year known (2000-00-00)
+>>> ssn.get_birth_year('00000000128')
+2000
+>>> ssn.get_birth_month('00000000128')
+>>> ssn.get_birth_date('00010000135')  # Only birth year and month known 
(2000-01-00)
+>>> ssn.get_birth_year('00010000135')
+2000
+>>> ssn.get_birth_month('00010000135')
+1
+>>> ssn.get_birth_date('85073500107')  # Unknown day of birth date (35)
+>>> ssn.get_birth_year('85073500107')
+1985
+>>> ssn.get_birth_month('85073500107')
+7
+>>> ssn.get_birth_date('85133000105')  # Invalid month (13)
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_year('85133000105')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_month('85133000105')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+
+Extra tests for getting gender from National Number
+
+>>> ssn.get_gender('75.06.08-980.09')
+'F'
+>>> ssn.get_gender('12345678901')
+
+
+Extra tests for getting birth date, year and/or month from BIS number.
+
+
+>>> ssn.get_birth_date('75.46.08-980.95')
+datetime.date(1975, 6, 8)
+>>> ssn.get_birth_year('75.46.08-980.95')
+1975
+>>> ssn.get_birth_month('75.46.08-980.95')
+6
+>>> ssn.get_birth_date('01 49 07 001 85')
+datetime.date(2001, 9, 7)
+>>> ssn.get_birth_year('01 49 07 001 85')
+2001
+>>> ssn.get_birth_month('01 49 07 001 85')
+9
+>>> ssn.get_birth_date('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_year('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_month('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> ssn.get_birth_date('00400100155')  # Exact date of birth unknown 
(fictitious date case 1900-00-01)
+>>> ssn.get_birth_year('00400100155')
+>>> ssn.get_birth_month('00400100155')
+>>> ssn.get_birth_date('00200100112')  # Birth date and gender unknown
+>>> ssn.get_birth_year('00200100112')
+>>> ssn.get_birth_month('00200100112')
+>>> ssn.get_birth_date('00400100184')  # Exact date of birth unknown 
(fictitious date case 2000-00-01)
+>>> ssn.get_birth_year('00400100184')
+>>> ssn.get_birth_month('00400100184')
+>>> ssn.get_birth_date('00200100141')  # Birth date and gender unknown
+>>> ssn.get_birth_year('00200100141')
+>>> ssn.get_birth_month('00200100141')
+>>> ssn.get_birth_date('00400000117')  # Only birth year known (2000-00-00)
+>>> ssn.get_birth_year('00400000117')
+2000
+>>> ssn.get_birth_month('00400000117')
+>>> ssn.get_birth_date('00200000171')  # Only birth year known and gender 
unknown
+>>> ssn.get_birth_year('00200000171')
+2000
+>>> ssn.get_birth_month('00200000171')
+>>> ssn.get_birth_date('00410000124')  # Only birth year and month known 
(2000-01-00)
+>>> ssn.get_birth_year('00410000124')
+2000
+>>> ssn.get_birth_month('00410000124')
+1
+>>> ssn.get_birth_date('00210000178')  # Only birth year and month known 
(2000-01-00) and gender unknown
+>>> ssn.get_birth_year('00210000178')
+2000
+>>> ssn.get_birth_month('00210000178')
+1
+>>> ssn.get_birth_date('85473500193')  # Unknown day of birth date (35)
+>>> ssn.get_birth_year('85473500193')
+1985
+>>> ssn.get_birth_month('85473500193')
+7
+>>> ssn.get_birth_date('85273500150')  # Unknown day of birth date (35) and 
gender unknown
+>>> ssn.get_birth_year('85273500150')
+1985
+>>> ssn.get_birth_month('85273500150')
+7
+>>> ssn.get_birth_date('85533000191')  # Invalid month (13)
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_year('85533000191')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_month('85533000191')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_date('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_year('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ssn.get_birth_month('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+Extra tests for getting gender from BIS number.
+
+>>> ssn.get_gender('75.46.08-980.95')
+'F'
+>>> ssn.get_gender('75.26.08-980.52')  # Gender unknown (month incremented by 
20)
+>>> ssn.get_gender('85473500193')
+'M'
+>>> ssn.get_gender('85273500150')
+>>> ssn.get_gender('12345678901')
+
+
+Extra tests for guessing type of invalid numbers
+
+
+>>> ssn.guess_type('12345678901')

-----------------------------------------------------------------------

Summary of changes:
 stdnum/be/ssn.py          | 155 +++++++++++++++++++++++++++++++++++
 tests/test_be_ssn.doctest | 205 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 360 insertions(+)
 create mode 100644 stdnum/be/ssn.py
 create mode 100644 tests/test_be_ssn.doctest


hooks/post-receive
-- 
python-stdnum