Skip to content

Instantly share code, notes, and snippets.

@celoyd
Created March 17, 2016 00:47
Show Gist options
  • Save celoyd/a3f1b515929493f512d5 to your computer and use it in GitHub Desktop.
Save celoyd/a3f1b515929493f512d5 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Calculate an ISO 6346 check digit (probably).
# The official algorithm costs about $100 to know.
# By Charlie Loyd, 2008-04-11.
from re import compile as regex
from string import uppercase
def iso6346checksum(code, ten='error'):
'''Call with a string like 'TEXU 328422' and optionally ten=
what you want a check digit of 10 to return instead of an error
(probably 0 or 10)'''
valid = regex('[A-Z]{3}[UJZ] [0-9]{6}')
if not valid.match(code):
raise ValueError, code + ' should look like "ZZZZ 111111".'
prefix, suffix = code.split()
prefix = list(prefix)
# Letter values are A=10, etc., skipping those divisible by 11, so Z=38
lettervals = filter(lambda e: e % 11 != 0, range(10, 39))
lettertable = dict(zip(uppercase, lettervals))
prefix = [lettertable[l] for l in prefix]
code = prefix + map(int, list(suffix))
s = sum([code[ind] * 2**ind for ind in range(0, 10)])
dummy = int(s/11) * 11 # futureproof!
cksum = s - dummy
if cksum == 10:
if ten == 'error':
raise ValueError, 'ISO 6346 checksum of 10.'
else: return ten
else: return cksum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment