Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/stdnum/cz
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2012-02-05 21:51:19 +0100
committerArthur de Jong <arthur@arthurdejong.org>2012-02-05 21:51:19 +0100
commit575fc75461a854f1fe468cb91a0332d0ffedc18d (patch)
tree6859a195005fb387a0424c02227ae226d2639668 /stdnum/cz
parent41dd8159b43e72f44f2e3ca0afcdeaac563b7180 (diff)
add a RČ (Rodné číslo, the Czech birth numbers) module
git-svn-id: http://arthurdejong.org/svn/python-stdnum/python-stdnum@101 9dea7c4f-944c-4273-ac1a-574ede026edc
Diffstat (limited to 'stdnum/cz')
-rw-r--r--stdnum/cz/__init__.py0
-rw-r--r--stdnum/cz/rc.py97
2 files changed, 97 insertions, 0 deletions
diff --git a/stdnum/cz/__init__.py b/stdnum/cz/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stdnum/cz/__init__.py
diff --git a/stdnum/cz/rc.py b/stdnum/cz/rc.py
new file mode 100644
index 0000000..eccc8ca
--- /dev/null
+++ b/stdnum/cz/rc.py
@@ -0,0 +1,97 @@
+# rc.py - functions for handling Czech birth numbers
+# coding: utf-8
+#
+# Copyright (C) 2012 Arthur de Jong
+#
+# 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
+
+"""Module for handling Czech birth numbers (RČ, Rodné číslo), the Czech
+national identifier.
+
+>>> compact('710319/2745')
+'7103192745'
+>>> is_valid('7103192745')
+True
+>>> is_valid('991231123')
+True
+>>> is_valid('7103192746') # invalid check digit
+False
+>>> is_valid('1103492745') # invalid date
+False
+>>> is_valid('590312/123') # 9 digit number in 1959
+False
+>>> format('7103192745')
+'710319/2745'
+"""
+
+import datetime
+
+from stdnum.util import clean
+
+
+def compact(number):
+ """Convert the number to the minimal representation. This strips the
+ number of any valid separators and removes surrounding whitespace."""
+ return clean(number, ' /').upper().strip()
+
+
+def _get_birth_date(number):
+ """Split the date parts from the number and return the birth date."""
+ year = 1900 + int(number[0:2])
+ # females have 50 added to the month value, 20 is added when the serial
+ # overflows (since 2004)
+ month = int(number[2:4]) % 50 % 20
+ day = int(number[4:6])
+ # 9 digit numbers were used until January 1st 1954
+ if len(number) == 9:
+ if year >= 1980:
+ year -= 100
+ if year > 1953:
+ raise ValueError('No 9 digit birth numbers after 1953.')
+ elif year < 1954:
+ year += 100
+ return datetime.date(year, month, day)
+
+
+def is_valid(number):
+ """Checks to see if the number provided is a valid birth number. This
+ checks the length, formatting, embedded date and check digit."""
+ try:
+ number = compact(number)
+ except:
+ return False
+ if not number.isdigit() or len(number) not in (9, 10):
+ return False
+ # check if birth date is valid
+ try:
+ birth_date = _get_birth_date(number)
+ # TODO: check that the birth date is not in the future
+ except ValueError, e:
+ return False
+ # check the check digit
+ if len(number) == 10:
+ check = int(number[:-1]) % 11
+ # before 1985 the checksum could be 0 or 10
+ if birth_date < datetime.date(1985, 1, 1):
+ check = check % 10
+ return number[-1] == str(check)
+ return True
+
+
+def format(number):
+ """Reformat the passed number to the standard format."""
+ number = compact(number)
+ return number[:6] + '/' + number[6:]