lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.18-24-gbe33a80

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

python-stdnum branch master updated. 1.18-24-gbe33a80



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  be33a801fd1b4728915a89f3f82979cafa3c57f0 (commit)
      from  8ce4a47ce14f2775398fdae1e387362f21258ee3 (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=be33a801fd1b4728915a89f3f82979cafa3c57f0

commit be33a801fd1b4728915a89f3f82979cafa3c57f0
Author: Jeff Horemans <jeff.horemans@vortex-financials.be>
Date:   Tue Jun 20 11:08:42 2023 +0200

    Add Belgian BIS Number
    
    Closes https://github.com/arthurdejong/python-stdnum/pull/418

diff --git a/stdnum/be/bis.py b/stdnum/be/bis.py
new file mode 100644
index 0000000..467f3b7
--- /dev/null
+++ b/stdnum/be/bis.py
@@ -0,0 +1,125 @@
+# coding=utf-8
+# bis.py - functions for handling Belgian BIS numbers
+#
+# 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
+
+"""BIS (Belgian BIS number).
+
+
+The BIS number (BIS-nummer, Numéro BIS) is a unique identification number
+for individuals who are not registered in the National Register, but who
+still have a relationship with the Belgian government.
+This includes frontier workers, persons who own property in Belgium,
+persons with Belgian social security rights but who do not reside in Belgium, 
etc.
+
+The number is issued by the Belgian Crossroads Bank for Social Security (Banque
+Carrefour de la sécurité sociale, Kruispuntbank voor Sociale Zekerheid) and is
+constructed much in the same way as the Belgian National Number, i.e. 
consisting of
+11 digits, encoding the person's date of birth and gender, a checksum, etc.
+Other than with the national number though, the month of birth of the BIS 
number
+is increased by 20 or 40, depending on whether the sex of the person was known
+at the time or not.
+
+
+More information:
+
+* https://sma-help.bosa.belgium.be/en/faq/where-can-i-find-my-bis-number#7326
+* https://www.socialsecurity.be/site_nl/employer/applics/belgianidpro/index.htm
+* https://nl.wikipedia.org/wiki/Rijksregisternummer
+* https://fr.wikipedia.org/wiki/Numéro_de_registre_national
+
+>>> compact('98.47.28-997.65')
+'98472899765'
+>>> validate('98 47 28 997 65')
+'98472899765'
+>>> validate('01 49 07 001 85')
+'01490700185'
+>>> validate('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> 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 nn
+from stdnum.exceptions import *
+from stdnum.util import isdigits
+
+
+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 BIS Number."""
+    number = compact(number)
+    if not isdigits(number) or int(number) <= 0:
+        raise InvalidFormat()
+    if len(number) != 11:
+        raise InvalidLength()
+    nn._get_birth_date_parts(number)
+    if not 20 <= int(number[2:4]) <= 32 and not 40 <= int(number[2:4]) <= 52:
+        raise InvalidComponent('Month must be in 20..32 or 40..52 range')
+    return number
+
+
+def is_valid(number):
+    """Check if the number is a valid BIS Number."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+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'), which for BIS
+    numbers is only known if the month was incremented with 40."""
+    number = compact(number)
+    if int(number[2:4]) >= 40:
+        return nn.get_gender(number)
diff --git a/stdnum/be/nn.py b/stdnum/be/nn.py
index 12b05cb..1de122a 100644
--- a/stdnum/be/nn.py
+++ b/stdnum/be/nn.py
@@ -115,11 +115,12 @@ def _get_birth_date_parts(number):
     # If the fictitious dates 1900/00/01 or 2000/00/01 are detected,
     # the birth date (including the year) was not known when the number
     # was issued.
-    if number[:6] == '000001':
+    if number[:6] in ('000001', '002001', '004001'):
         return (None, None, None)
 
     year = int(number[:2]) + century
-    month, day = int(number[2:4]), int(number[4:6])
+    month = int(number[2:4]) % 20
+    day = int(number[4:6])
     # When the month is zero, it was either unknown when the number was issued,
     # or the day counter ran out. In both cases, the month and day are not 
known
     # reliably.
@@ -128,7 +129,7 @@ def _get_birth_date_parts(number):
 
     # Verify range of month
     if month > 12:
-        raise InvalidComponent('month must be in 1..12')
+        raise InvalidComponent('Month must be in 1..12')
 
     # Case when only the day of the birth date is unknown
     if day == 0 or day > calendar.monthrange(year, month)[1]:
@@ -145,6 +146,8 @@ def validate(number):
     if len(number) != 11:
         raise InvalidLength()
     _get_birth_date_parts(number)
+    if not 0 <= int(number[2:4]) <= 12:
+        raise InvalidComponent('Month must be in 1..12')
     return number
 
 
diff --git a/tests/test_be_bis.doctest b/tests/test_be_bis.doctest
new file mode 100644
index 0000000..b52607c
--- /dev/null
+++ b/tests/test_be_bis.doctest
@@ -0,0 +1,136 @@
+test_be_bis.doctest - more detailed doctests for stdnum.be.bis module
+
+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.bis module. It
+tries to test more corner cases and detailed functionality that is not
+really useful as module documentation.
+
+>>> from stdnum.be import bis
+
+
+Extra tests for getting birth date, year and/or month
+
+
+>>> bis.get_birth_date('75.46.08-980.95')
+datetime.date(1975, 6, 8)
+>>> bis.get_birth_year('75.46.08-980.95')
+1975
+>>> bis.get_birth_month('75.46.08-980.95')
+6
+>>> bis.get_birth_date('01 49 07 001 85')
+datetime.date(2001, 9, 7)
+>>> bis.get_birth_year('01 49 07 001 85')
+2001
+>>> bis.get_birth_month('01 49 07 001 85')
+9
+>>> bis.get_birth_date('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> bis.get_birth_year('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> bis.get_birth_month('12345678901')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> bis.get_birth_date('00400100155')  # Exact date of birth unknown 
(fictitious date case 1900-00-01)
+>>> bis.get_birth_year('00400100155')
+>>> bis.get_birth_month('00400100155')
+>>> bis.get_birth_date('00200100112')  # Birth date and gender unknown
+>>> bis.get_birth_year('00200100112')
+>>> bis.get_birth_month('00200100112')
+>>> bis.get_birth_date('00400100184')  # Exact date of birth unknown 
(fictitious date case 2000-00-01)
+>>> bis.get_birth_year('00400100184')
+>>> bis.get_birth_month('00400100184')
+>>> bis.get_birth_date('00200100141')  # Birth date and gender unknown
+>>> bis.get_birth_year('00200100141')
+>>> bis.get_birth_month('00200100141')
+>>> bis.get_birth_date('00400000117')  # Only birth year known (2000-00-00)
+>>> bis.get_birth_year('00400000117')
+2000
+>>> bis.get_birth_month('00400000117')
+>>> bis.get_birth_date('00200000171')  # Only birth year known and gender 
unknown
+>>> bis.get_birth_year('00200000171')
+2000
+>>> bis.get_birth_month('00200000171')
+>>> bis.get_birth_date('00410000124')  # Only birth year and month known 
(2000-01-00)
+>>> bis.get_birth_year('00410000124')
+2000
+>>> bis.get_birth_month('00410000124')
+1
+>>> bis.get_birth_date('00210000178')  # Only birth year and month known 
(2000-01-00) and gender unknown
+>>> bis.get_birth_year('00210000178')
+2000
+>>> bis.get_birth_month('00210000178')
+1
+>>> bis.get_birth_date('85473500193')  # Unknown day of birth date (35)
+>>> bis.get_birth_year('85473500193')
+1985
+>>> bis.get_birth_month('85473500193')
+7
+>>> bis.get_birth_date('85273500150')  # Unknown day of birth date (35) and 
gender unknown
+>>> bis.get_birth_year('85273500150')
+1985
+>>> bis.get_birth_month('85273500150')
+7
+>>> bis.get_birth_date('85533000191')  # Invalid month (13)
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> bis.get_birth_year('85533000191')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> bis.get_birth_month('85533000191')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> bis.get_birth_date('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> bis.get_birth_year('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> bis.get_birth_month('85333000148')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+Extra tests for getting gender.
+
+>>> bis.get_gender('75.46.08-980.95')
+'F'
+>>> bis.get_gender('75.26.08-980.52')  # Gender unknown (month incremented by 
20)
+>>> bis.get_gender('85473500193')
+'M'
+>>> bis.get_gender('85273500150')
+
+
+A NN should not be considered a valid BIS number.
+
+>>> bis.validate('00000100195')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
diff --git a/tests/test_be_nn.doctest b/tests/test_be_nn.doctest
index cada6b5..ebab87a 100644
--- a/tests/test_be_nn.doctest
+++ b/tests/test_be_nn.doctest
@@ -91,3 +91,11 @@ Extra tests for getting gender
 
 >>> nn.get_gender('75.06.08-980.09')
 'F'
+
+
+A BIS number is not considered a valid NN.
+
+>>> nn.validate('00400100184')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...

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

Summary of changes:
 stdnum/be/bis.py          | 125 ++++++++++++++++++++++++++++++++++++++++++
 stdnum/be/nn.py           |   9 ++-
 tests/test_be_bis.doctest | 136 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_be_nn.doctest  |   8 +++
 4 files changed, 275 insertions(+), 3 deletions(-)
 create mode 100644 stdnum/be/bis.py
 create mode 100644 tests/test_be_bis.doctest


hooks/post-receive
-- 
python-stdnum