Skip to content

Commit 07b9f82

Browse files
committed
Add support for Hong Kong TIN
Fixes #320.
1 parent e40c827 commit 07b9f82

File tree

3 files changed

+178
-0
lines changed

3 files changed

+178
-0
lines changed

stdnum/hk/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# __init__.py - collection of Hong Kong numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""Collection of Hong Kong numbers."""
22+
23+
# provide aliases
24+
from stdnum.hk import brn as vat # noqa: F401

stdnum/hk/brn.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# nit.py - functions for handling Hong Kong BR numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""BRN (Bussiness Registration number, Hong Kong tax number).
22+
23+
Sometimes also called "商業登記號碼" or "BR No."
24+
25+
This number consists of 8 digits. It is the first 8 digits at the front of the
26+
Business Registration Certificate Number, which in turn has the
27+
22222222-XXX-XX-XX-X format. It is provided by the Inland Revenue Department
28+
(IRD) of Hong Kong at the date of incorporation.
29+
30+
More information:
31+
32+
* https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Hong-Kong-TIN.pdf
33+
* https://sleek.com/hk/resources/hong-kong-business-registration-number-vs-company-registration-number/
34+
* https://blog.startupr.hk/hong-kong-business-registration-number-brn/
35+
36+
>>> validate('31130878')
37+
'31130878'
38+
>>> validate('1767 4094')
39+
'17674094'
40+
>>> validate('12345')
41+
Traceback (most recent call last):
42+
...
43+
InvalidLength: ...
44+
>>> format('1767 4094')
45+
'17674094'
46+
""" # noqa: E501
47+
48+
from stdnum.exceptions import *
49+
from stdnum.util import clean, isdigits
50+
51+
52+
def compact(number):
53+
"""Convert the number to the minimal representation.
54+
55+
This strips the number of any valid separators and removes surrounding
56+
whitespace.
57+
"""
58+
return clean(number, ' -')
59+
60+
61+
def validate(number):
62+
"""Check if the number is a valid Hong Kong BR number.
63+
64+
This checks the length and formatting.
65+
"""
66+
number = compact(number)
67+
if len(number) != 8:
68+
raise InvalidLength()
69+
if not isdigits(number):
70+
raise InvalidFormat()
71+
return number
72+
73+
74+
def is_valid(number):
75+
"""Check if the number is a valid Hong Kong BR number."""
76+
try:
77+
return bool(validate(number))
78+
except ValidationError:
79+
return False
80+
81+
82+
def format(number):
83+
"""Reformat the number to the standard presentation format."""
84+
return compact(number)

tests/test_hk_brn.doctest

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
test_hk_brn.doctest - more detailed doctests for stdnum.hk.brn module
2+
3+
Copyright (C) 2022 Leandro Regueiro
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
02110-1301 USA
19+
20+
21+
This file contains more detailed doctests for the stdnum.hk.brn module. It
22+
tries to test more corner cases and detailed functionality that is not really
23+
useful as module documentation.
24+
25+
>>> from stdnum.hk import brn
26+
27+
28+
Tests for some corner cases.
29+
30+
>>> brn.validate('31130878')
31+
'31130878'
32+
>>> brn.validate('1767 4094')
33+
'17674094'
34+
>>> brn.format('1767 4094')
35+
'17674094'
36+
>>> brn.validate('12345')
37+
Traceback (most recent call last):
38+
...
39+
InvalidLength: ...
40+
>>> brn.validate('X2345678')
41+
Traceback (most recent call last):
42+
...
43+
InvalidFormat: ...
44+
45+
46+
These have been found online and should all be valid numbers.
47+
48+
>>> numbers = '''
49+
...
50+
... 31130878
51+
... 52399423
52+
... 71623118
53+
... 33120398
54+
... 34647541
55+
... 58443527
56+
... 34214805
57+
... 12004664
58+
... 71536751
59+
... 1767 4094
60+
... 13603580
61+
... 34773491
62+
... 34395970
63+
... 33833767
64+
... 65556656
65+
... 15538767
66+
... 58650623
67+
...
68+
... '''
69+
>>> [x for x in numbers.splitlines() if x and not brn.is_valid(x)]
70+
[]

0 commit comments

Comments
 (0)