""" Convert numbers from base 10 integers to base X strings and back again. Original: http://www.djangosnippets.org/snippets/1431/ Sample usage: >>> converter = the_converter >>> converter.encode('1234') 'DvY' >>> converter.decode('DvY') '1234' Tests: >>> converter.decode(converter.encode('1234')) == '1234' True >>> converter.decode(converter.encode('1234A')) == '1234A' True >>> converter.decode(converter.encode('1234A-')) == '1234A-' True >>> converter.decode(converter.encode('1234A-')) == '1234A' False """ import time import string import datetime class BaseConverter(object): letter_set = set(string.letters) decimal_digits = "0123456789" base62_digits = "0123456789abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" base63_digits = "0123456789abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ-" decimal_char = "D" base62_char = "2" base63_char = "3" char_map = { decimal_char: decimal_digits, base62_char: base62_digits, base63_char: base63_digits, } def __init__(self, digits): self.digits = digits def __get_base_digits(self, value): if "-" in value: return self.base63_digits, self.base63_char elif self.letter_set.intersection(value): return self.base62_digits, self.base62_char else: return self.decimal_digits, self.decimal_char def encode(self, i): decimal_digits, b_char = self.__get_base_digits(i) results = self.convert(i, decimal_digits, self.digits) return "%s%s" % (b_char, results) def one_way_encode(self, i): """ One way encode, not possible to decode. using base62 digits no - """ return self.convert(i, self.base62_digits, self.digits) def decode(self, s): # strip out the first base_char. return self.convert(s[1 : len(s)], self.digits, self.char_map[s[0]]) def convert(number, fromdigits, todigits): # Based on http://code.activestate.com/recipes/111286/ if str(number)[0] == "-": number = str(number)[1:] neg = 1 else: neg = 0 # make an integer out of the number x = 0 for digit in str(number): x = x * len(fromdigits) + fromdigits.index(digit) # create the result in base 'len(todigits)' if x == 0: res = todigits[0] else: res = "" while x > 0: digit = x % len(todigits) res = todigits[digit] + res x = int(x / len(todigits)) if neg: res = "-" + res return res convert = staticmethod(convert) pbp_converter = BaseConverter( "012345abcdefghijklmnopqrstuvwxyz67" "ABCDEFGHIJKLMNOPQRSTUVWXYZ89" ) def temp_code(now=None): """We need a unique temp code, so we get a timestamp to the microsecond and that should be good enough """ if not now: now = datetime.datetime.now() return "%s%s" % (int(time.mktime(now.timetuple())), now.microsecond)