Skip to content

Instantly share code, notes, and snippets.

@taurit
Forked from supix/CheckCodiceFiscale.cs
Last active February 25, 2021 14:49
Show Gist options
  • Save taurit/b9316e0a0efb719fbc43d6487e660e72 to your computer and use it in GitHub Desktop.
Save taurit/b9316e0a0efb719fbc43d6487e660e72 to your computer and use it in GitHub Desktop.
Italian Fiscal Code validation in C#
/// <summary>
/// Validate Italian Fiscal Code (https://en.wikipedia.org/wiki/Italian_fiscal_code_card)
/// </summary>
/// <param name="fiscalCode">code to be checked</param>
/// <returns><c>true</c> if checksum is valid, <c>false</c> otherwise</returns>
/// <remarks>
/// Based on: https://gist.github.com/supix/97dfe1e2c4b804bd3721faf4bec1c573
/// </remarks>
public static bool IsFiscalCodeValid(string fiscalCode)
{
if (fiscalCode == null) return false;
const string regex =
@"^(?:[B-DF-HJ-NP-TV-Z](?:[AEIOU]{2}|[AEIOU]X)|[AEIOU]{2}X|[B-DF-HJ-NP-TV-Z]{2}[A-Z]){2}[\dLMNP-V]{2}(?:[A-EHLMPR-T](?:[04LQ][1-9MNP-V]|[1256LMRS][\dLMNP-V])|[DHPS][37PT][0L]|[ACELMRT][37PT][01LM])(?:[A-MZ][1-9MNP-V][\dLMNP-V]{2}|[A-M][0L](?:[\dLMNP-V][1-9MNP-V]|[1-9MNP-V][0L]))[A-Z]$";
if (!Regex.IsMatch(fiscalCode, regex)) return false;
#region static maps
var oddMap = new Dictionary<char, int>
{
{ '0', 1 },
{ '1', 0 },
{ '2', 5 },
{ '3', 7 },
{ '4', 9 },
{ '5', 13 },
{ '6', 15 },
{ '7', 17 },
{ '8', 19 },
{ '9', 21 },
{ 'A', 1 },
{ 'B', 0 },
{ 'C', 5 },
{ 'D', 7 },
{ 'E', 9 },
{ 'F', 13 },
{ 'G', 15 },
{ 'H', 17 },
{ 'I', 19 },
{ 'J', 21 },
{ 'K', 2 },
{ 'L', 4 },
{ 'M', 18 },
{ 'N', 20 },
{ 'O', 11 },
{ 'P', 3 },
{ 'Q', 6 },
{ 'R', 8 },
{ 'S', 12 },
{ 'T', 14 },
{ 'U', 16 },
{ 'V', 10 },
{ 'W', 22 },
{ 'X', 25 },
{ 'Y', 24 },
{ 'Z', 23 }
};
var evenMap = new Dictionary<char, int>
{
{ '0', 0 },
{ '1', 1 },
{ '2', 2 },
{ '3', 3 },
{ '4', 4 },
{ '5', 5 },
{ '6', 6 },
{ '7', 7 },
{ '8', 8 },
{ '9', 9 },
{ 'A', 0 },
{ 'B', 1 },
{ 'C', 2 },
{ 'D', 3 },
{ 'E', 4 },
{ 'F', 5 },
{ 'G', 6 },
{ 'H', 7 },
{ 'I', 8 },
{ 'J', 9 },
{ 'K', 10 },
{ 'L', 11 },
{ 'M', 12 },
{ 'N', 13 },
{ 'O', 14 },
{ 'P', 15 },
{ 'Q', 16 },
{ 'R', 17 },
{ 'S', 18 },
{ 'T', 19 },
{ 'U', 20 },
{ 'V', 21 },
{ 'W', 22 },
{ 'X', 23 },
{ 'Y', 24 },
{ 'Z', 25 }
};
#endregion static maps
var total = 0;
for (var i = 0; i < 15; i += 2) total += oddMap[fiscalCode[i]];
for (var i = 1; i < 15; i += 2) total += evenMap[fiscalCode[i]];
return fiscalCode[15] == (char)('A' + total % 26);
}
/* Xunit tests for validator */
[Fact]
public void WhenCodeContainsInvalidControlCharacter_ReturnsFalse()
{
// example of valid code from https://en.wikipedia.org/wiki/Italian_fiscal_code_card
var code = "MRTMTT25D09F205X"; // last "X" is invalid, control character should be "Z"
// Act
var valid = ItalianFiscalCodeValidator.IsFiscalCodeValid(code);
// Assert
Assert.Equal(false, valid);
}
[Fact]
public void WhenCodeIsTooShort_ReturnsFalse()
{
// code should contain 15 characters
var code0 = "";
var code1 = "M";
var code2 = "MR";
var code14 = "MRTMTT25D09F205"; // last "X" is invalid, control character should be "Z"
// Act
var valid0 = ItalianFiscalCodeValidator.IsFiscalCodeValid(code0);
var valid1 = ItalianFiscalCodeValidator.IsFiscalCodeValid(code1);
var valid2 = ItalianFiscalCodeValidator.IsFiscalCodeValid(code2);
var valid14 = ItalianFiscalCodeValidator.IsFiscalCodeValid(code14);
// Assert
Assert.Equal(false, valid0);
Assert.Equal(false, valid1);
Assert.Equal(false, valid2);
Assert.Equal(false, valid14);
}
[Fact]
public void WhenNullCodeIsPassed_ReturnsFalse()
{
// Act
var valid = ItalianFiscalCodeValidator.IsFiscalCodeValid(null);
// Assert
Assert.Equal(false, valid);
}
[Fact]
public void WhenValidCodeIsGiven_ForForeignCitizen_ReturnsTrue()
{
// example of valid code from https://en.wikipedia.org/wiki/Italian_fiscal_code_card
var code = "MLLSNT82P65Z404U";
// Act
var valid = ItalianFiscalCodeValidator.IsFiscalCodeValid(code);
// Assert
Assert.Equal(true, valid);
}
[Fact]
public void WhenValidCodeIsGiven_ReturnsTrue()
{
// example of valid code from https://en.wikipedia.org/wiki/Italian_fiscal_code_card
var code = "MRTMTT25D09F205Z";
// Act
var valid = ItalianFiscalCodeValidator.IsFiscalCodeValid(code);
// Assert
Assert.Equal(true, valid);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment