Created
May 14, 2012 03:35
-
-
Save jbaylor-rpx/2691624 to your computer and use it in GitHub Desktop.
Convert Salesforce IDs from 15 character to 18 characters (and back)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Salesforce originally used case-sensitive 15-character IDs. | |
# Later they added three error-correcting characters to make their 18-character ID. | |
# This class converts from one to the other and back | |
# | |
# Usage: | |
# SalesforceId.convert('a0D30000001n7Pi') => 'a0D30000001n7PiEAC' | |
# OR | |
# SalesforceId.convert('a0D30000001n7PiEAC') => 'a0D30000001n7Pi' | |
# SalesforceId.convert('A0d30000001N7pIeAc') => 'a0D30000001n7Pi' | |
# | |
class SalesforceId | |
class << self | |
def convert(str) | |
raise 'can only convert strings' unless str.is_a?(String) | |
return convert15to18(str) if str.length == 15 | |
return convert18to15(str) if str.length == 18 | |
raise 'must be either 15 or 18' | |
end | |
def base32todecimal(char) | |
base32[char] | |
end | |
def decimaltobase32(dec) | |
Array(base32.rassoc(dec)).first | |
end | |
private | |
def base32 | |
@@b32 ||= begin | |
hash = {} | |
('A'..'Z').each_with_index {|letter, idx| hash[letter] = idx } | |
('0'..'5').each_with_index {|digit, idx| hash[digit] = idx + 26 } | |
hash | |
end | |
end | |
def convert15to18(str) | |
bits = str.split('').collect {|char| (char =~ /[A-Z]/) ? '1' : 0 } | |
checkdigits = [ | |
bits[0..4].join.to_i(2), | |
bits[5..9].join.to_i(2), | |
bits[10..14].join.to_i(2), | |
] | |
checkdigits = checkdigits.collect {|d| decimaltobase32(d) }.join | |
str + checkdigits | |
end | |
def convert18to15(str) | |
base = str[0..14].downcase.split('') | |
dec = str[-3..-1].upcase.split('').collect {|char| base32todecimal(char) } | |
bits = dec.map {|d| ("%05b" % d.to_i).split('') }.flatten | |
base.zip(bits).map {|char,bit| bit == '1' ? char.upcase : char }.join | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment