Skip to content

Instantly share code, notes, and snippets.

@esthezia
Created October 19, 2021 13:29
Show Gist options
  • Save esthezia/8f6e85c0634d6b01d7de51a3b01e3ead to your computer and use it in GitHub Desktop.
Save esthezia/8f6e85c0634d6b01d7de51a3b01e3ead to your computer and use it in GitHub Desktop.
cnp-validation
<?php
function isCnpValid (string $cnp) : bool {
if (empty($cnp) || (preg_match('/^[1-9]{1}[0-9]{12}$/', $cnp) !== 1)) {
return false;
}
$birthMonth = (int) ($cnp[3] . $cnp[4]);
if (!$birthMonth || ($birthMonth > 12)) {
return false;
}
$birthDay = (int) ($cnp[5] . $cnp[6]);
$birthYear = '19';
if (($cnp[0] === '3') || ($cnp[0] === '4')) {
$birthYear = '18';
} elseif (($cnp[0] === '5') || ($cnp[0] === '6')) {
$birthYear = '20';
}
$birthYear = (int) ($birthYear . $cnp[1] . $cnp[2]);
// check if the birth day doesn't exceed the number of days in the birth month
if (!$birthDay || ($birthDay > (int) date('t', strtotime($birthYear . '-' . $birthMonth . '-01')))) {
return false;
}
$birthPlace = (int) ($cnp[7] . $cnp[8]);
if (
!$birthPlace ||
(($birthPlace > 46) && ($birthPlace < 51)) ||
($birthPlace > 52)
) {
return false;
}
// the number formed by the 9th, 10th, and 11th digits (0-indexed) must be between 1 and 999
if (($cnp[9] === '0') && ($cnp[10] === '0') && ($cnp[11] === '0')) {
return false;
}
$controlNumber = (($cnp[0] * 2) + ($cnp[1] * 7) + ($cnp[2] * 9) + ($cnp[3] * 1) + ($cnp[4] * 4) + ($cnp[5] * 6) + ($cnp[6] * 3) + ($cnp[7] * 5) + ($cnp[8] * 8) + ($cnp[9] * 2) + ($cnp[10] * 7) + ($cnp[11] * 9)) % 11;
$controlNumber = $controlNumber === 10 ? 1 : $controlNumber;
if ((int) $cnp[12] !== $controlNumber) {
return false;
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment