|
29
|
1 |
import re |
|
|
2 |
import datetime |
|
|
3 |
|
|
|
4 |
def id_number_checksum(gd): |
|
|
5 |
""" |
|
|
6 |
Calculates a Swedish ID number checksum, using the |
|
|
7 |
"Luhn"-algoritm |
|
|
8 |
""" |
|
|
9 |
n = s = 0 |
|
|
10 |
for c in (gd['year'] + gd['month'] + gd['day'] + gd['serial']): |
|
|
11 |
tmp = ((n % 2) and 1 or 2) * int(c) |
|
|
12 |
|
|
|
13 |
if tmp > 9: |
|
|
14 |
tmp = sum([int(i) for i in str(tmp)]) |
|
|
15 |
|
|
|
16 |
s += tmp |
|
|
17 |
n += 1 |
|
|
18 |
|
|
|
19 |
if (s % 10) == 0: |
|
|
20 |
return 0 |
|
|
21 |
|
|
|
22 |
return (((s / 10) + 1) * 10) - s |
|
|
23 |
|
|
|
24 |
def validate_id_birthday(gd, fix_coordination_number_day=True): |
|
|
25 |
""" |
|
|
26 |
Validates the birth_day and returns the datetime.date object for |
|
|
27 |
the birth_day. |
|
|
28 |
|
|
|
29 |
If the date is an invalid birth day, a ValueError will be raised. |
|
|
30 |
""" |
|
|
31 |
|
|
|
32 |
today = datetime.date.today() |
|
|
33 |
|
|
|
34 |
day = int(gd['day']) |
|
|
35 |
if fix_coordination_number_day and day > 60: |
|
|
36 |
day -= 60 |
|
|
37 |
|
|
|
38 |
if gd['century'] is None: |
|
|
39 |
|
|
|
40 |
# The century was not specified, and need to be calculated from todays date |
|
|
41 |
current_year = today.year |
|
|
42 |
year = int(today.strftime('%Y')) - int(today.strftime('%y')) + int(gd['year']) |
|
|
43 |
|
|
|
44 |
if ('%s%s%02d' % (gd['year'], gd['month'], day)) > today.strftime('%y%m%d'): |
|
|
45 |
year -= 100 |
|
|
46 |
|
|
|
47 |
# If the person is older than 100 years |
|
|
48 |
if gd['sign'] == '+': |
|
|
49 |
year -= 100 |
|
|
50 |
else: |
|
|
51 |
year = int(gd['century'] + gd['year']) |
|
|
52 |
|
|
|
53 |
# Make sure the year is valid |
|
|
54 |
# There are no swedish personal identity numbers where year < 1800 |
|
|
55 |
if year < 1800: |
|
|
56 |
raise ValueError |
|
|
57 |
|
|
|
58 |
# ValueError will be raise for invalid dates |
|
|
59 |
birth_day = datetime.date(year, int(gd['month']), day) |
|
|
60 |
|
|
|
61 |
# birth_day must not be in the future |
|
|
62 |
if birth_day > today: |
|
|
63 |
raise ValueError |
|
|
64 |
|
|
|
65 |
return birth_day |
|
|
66 |
|
|
|
67 |
def format_personal_id_number(birth_day, gd): |
|
|
68 |
# birth_day.strftime cannot be used, since it does not support dates < 1900 |
|
|
69 |
return unicode(str(birth_day.year) + gd['month'] + gd['day'] + gd['serial'] + gd['checksum']) |
|
|
70 |
|
|
|
71 |
def format_organisation_number(gd): |
|
|
72 |
if gd['century'] is None: |
|
|
73 |
century = '' |
|
|
74 |
else: |
|
|
75 |
century = gd['century'] |
|
|
76 |
|
|
|
77 |
return unicode(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum']) |
|
|
78 |
|
|
|
79 |
def valid_organisation(gd): |
|
|
80 |
return gd['century'] in (None, 16) and \ |
|
|
81 |
int(gd['month']) >= 20 and \ |
|
|
82 |
gd['sign'] in (None, '-') and \ |
|
|
83 |
gd['year'][0] in ('2', '5', '7', '8', '9') # group identifier |
|
|
84 |
|