| import re |
| import datetime |
| |
| def id_number_checksum(gd): |
| """ |
| Calculates a Swedish ID number checksum, using the |
| "Luhn"-algoritm |
| """ |
| n = s = 0 |
| for c in (gd['year'] + gd['month'] + gd['day'] + gd['serial']): |
| tmp = ((n % 2) and 1 or 2) * int(c) |
| |
| if tmp > 9: |
| tmp = sum([int(i) for i in str(tmp)]) |
| |
| s += tmp |
| n += 1 |
| |
| if (s % 10) == 0: |
| return 0 |
| |
| return (((s / 10) + 1) * 10) - s |
| |
| def validate_id_birthday(gd, fix_coordination_number_day=True): |
| """ |
| Validates the birth_day and returns the datetime.date object for |
| the birth_day. |
| |
| If the date is an invalid birth day, a ValueError will be raised. |
| """ |
| |
| today = datetime.date.today() |
| |
| day = int(gd['day']) |
| if fix_coordination_number_day and day > 60: |
| day -= 60 |
| |
| if gd['century'] is None: |
| |
| # The century was not specified, and need to be calculated from todays date |
| current_year = today.year |
| year = int(today.strftime('%Y')) - int(today.strftime('%y')) + int(gd['year']) |
| |
| if ('%s%s%02d' % (gd['year'], gd['month'], day)) > today.strftime('%y%m%d'): |
| year -= 100 |
| |
| # If the person is older than 100 years |
| if gd['sign'] == '+': |
| year -= 100 |
| else: |
| year = int(gd['century'] + gd['year']) |
| |
| # Make sure the year is valid |
| # There are no swedish personal identity numbers where year < 1800 |
| if year < 1800: |
| raise ValueError |
| |
| # ValueError will be raise for invalid dates |
| birth_day = datetime.date(year, int(gd['month']), day) |
| |
| # birth_day must not be in the future |
| if birth_day > today: |
| raise ValueError |
| |
| return birth_day |
| |
| def format_personal_id_number(birth_day, gd): |
| # birth_day.strftime cannot be used, since it does not support dates < 1900 |
| return unicode(str(birth_day.year) + gd['month'] + gd['day'] + gd['serial'] + gd['checksum']) |
| |
| def format_organisation_number(gd): |
| if gd['century'] is None: |
| century = '' |
| else: |
| century = gd['century'] |
| |
| return unicode(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum']) |
| |
| def valid_organisation(gd): |
| return gd['century'] in (None, 16) and \ |
| int(gd['month']) >= 20 and \ |
| gd['sign'] in (None, '-') and \ |
| gd['year'][0] in ('2', '5', '7', '8', '9') # group identifier |
| |