Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pwiesner/a47fe0069ae4e1729a13 to your computer and use it in GitHub Desktop.
Save pwiesner/a47fe0069ae4e1729a13 to your computer and use it in GitHub Desktop.
/*
* A while back I overheard one of my coworkers grumbling about converting 15 digit salesforce ids to their
* 18 digit variant. I had no idea what he was talking about, but goolge and Alan Shanahan did. Below is my
* attempt at implementing the algorithm Alan described in this blog post
* https://astadiaemea.wordpress.com/2010/06/21/15-or-18-character-ids-in-salesforce-com-%E2%80%93-do-you-know-how-useful-unique-ids-are-to-your-development-effort/
*
* The following code has not been used anywhere or really tested for that matter. I just wanted to better
* understand what was being discussed on the other side of my cube.
*/
/// <summary>
/// Convert a case sensitive Salesforce id to the case insensitive format.
///
/// The algorithm for converting a case sensitive id to a case insensitive id is as follows.
///
/// 1 - Split the 15 character id into three five character chunks.
/// 2 - Reverse the order of the five character chunks.
/// 3 - Iterate over the three chunks and replace all capital letters with 1 and all lower case letters and
/// numeric characters with 0.
/// 4 - Each chunk is now a five digit binary number.
/// 5 - Convert the binary values to decimal.
/// 6 - The decimal value is used to look up a value in the following zero indexed array.
///
/// char[] map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
///
/// 7 - Append the three mapped characters to the end of the 15 character id.
///
/// For Example:
/// -> "00Do0000000HpVI"
/// -> ["00Do0", "00000", "0HpVI"]
/// -> ["0oD00", "00000", "IVpH0"]
/// -> ["00100", "00000", "11010"]
/// -> [4, 0, 26]
/// -> ["E", "A", "0"]
/// -> "00Do0000000HpVIEA0"
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string ToCaseInsensitive(string id)
{
const int chunkSize = 5;
var eighteenDigit = new StringBuilder(id);
for (int chunkStartIndex = 0; chunkStartIndex < id.Length; chunkStartIndex = chunkStartIndex + chunkSize)
{
eighteenDigit.Append(ParityBit(id.Substring(chunkStartIndex, chunkSize)));
}
return eighteenDigit.ToString();
}
/// <summary>
/// Given a five character block of alphanumeric characters produce a parity character.
/// </summary>
/// <param name="block"></param>
/// <returns></returns>
private char ParityBit(string block)
{
var asBinary = new StringBuilder();
char[] map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345".ToCharArray();
char[] reversedBlock = block.Reverse().ToArray();
foreach (char c in reversedBlock)
{
asBinary.Append(Regex.IsMatch(c.ToString(), @"^[A-Z]$") ? "1" : "0");
}
int index = Convert.ToInt32(asBinary.ToString(), fromBase: 2);
return map[index];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment