Last active
March 11, 2024 13:17
-
-
Save pwiesner/a47fe0069ae4e1729a13 to your computer and use it in GitHub Desktop.
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
/* | |
* 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