Skip to content

Commit

Permalink
Implement correspondence check
Browse files Browse the repository at this point in the history
Signed-off-by: Sunghyun Hwang <[email protected]>
  • Loading branch information
0xd669 committed Aug 31, 2018
1 parent d13e198 commit c8f2d1e
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 4 deletions.
65 changes: 62 additions & 3 deletions rrn.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import itertools
import re
from datetime import datetime
from datetime import date, datetime
from typing import Optional


HYPHEN = re.compile('[-–]')
Expand All @@ -10,6 +11,8 @@
MONTH_OF_BIRTH_FORMAT = '%y%m'
DAY_OF_BIRTH_FORMAT = '%y%m%d'

SEX = 6

LOC = 7, 9
MAX_LOC = 97

Expand Down Expand Up @@ -84,5 +87,61 @@ def is_valid_rrn(rrn: str) -> bool:
return False


def is_corresponding_rrn(rrn: str) -> bool:
pass
def _is_birthday_corresponding(rrn: str, birthday: date) -> Optional[bool]:
try:
return datetime.strptime(
rrn[slice(*BIRTH)],
DAY_OF_BIRTH_FORMAT
).date() == birthday
except (TypeError, ValueError):
return None


def _is_sex_corresponding(rrn: str, female: bool) -> Optional[bool]:
try:
return (int(rrn[SEX]) % 2 == 0) == female
except IndexError:
return None


def _is_foreignness_corresponding(rrn: str, foreign: bool) -> Optional[bool]:
try:
return (5 <= int(rrn[SEX]) <= 8) == foreign
except IndexError:
return None


def is_corresponding_rrn(
rrn: str,
*,
birthday: Optional[date]=None,
foreign: Optional[bool]=None,
female: Optional[bool]=None
) -> Optional[bool]:
"""
Check given RRN if it corresponds with given information or not.
It returns None if correspondence is undecidable.
For example, 6-digit RRN string does not contain any information about sex.
:param rrn: RRN string
:param birthday: expected date of birth
:param foreign: expected to be foreigner or not
:param female: expected to be female or not
:return: correspondence (None if it's undecidable)
"""
try:
rrn = HYPHEN.sub('', rrn)
assert rrn.isdigit()
return (
(
birthday is None or _is_birthday_corresponding(rrn, birthday)
) and
(
foreign is None or _is_foreignness_corresponding(rrn, foreign)
) and
(
female is None or _is_sex_corresponding(rrn, female)
)
)
except (AssertionError, TypeError):
return None
26 changes: 25 additions & 1 deletion tests/test_rrn.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import unittest
from datetime import date

import rrn

Expand Down Expand Up @@ -42,4 +43,27 @@ def test_is_valid_rrn(self):
self.assertEqual(expected, rrn.is_valid_rrn(s))

def test_is_corresponding_rrn(self):
self.assertEqual(1 + 1, 2)
undecided, corresponding, not_corresponding = None, True, False
female, male = True, False
foreign, domestic = True, False

for r, (b, s, f), expected in [
('RRN', (None, None, None), undecided),
('940812', (None, None, None), corresponding),
('940812', (None, male, None), undecided),
('940812', (None, None, foreign), undecided),
('940812', (None, female, foreign), undecided),
('8808121', (None, male, domestic), corresponding),
('6008122', (None, None, foreign), not_corresponding),
('7403225', (None, female, None), not_corresponding),
('9408131', (date(1994, 8, 13), None, None), corresponding),
('9408121', (date(1994, 8, 12), None, domestic), corresponding),
('0408127', (date(2004, 8, 12), male, domestic), not_corresponding),
('9408122', (date(1994, 8, 12), female, domestic), corresponding),
('9802145', (date(1998, 2, 14), male, foreign), corresponding),
('9103226', (date(1991, 3, 22), female, foreign), corresponding)
]:
self.assertEqual(
expected,
rrn.is_corresponding_rrn(r, birthday=b, female=s, foreign=f)
)

0 comments on commit c8f2d1e

Please sign in to comment.