diff --git a/src/Faker/Provider/lv_LV/Person.php b/src/Faker/Provider/lv_LV/Person.php index d251f891a6..4e9b93b75d 100644 --- a/src/Faker/Provider/lv_LV/Person.php +++ b/src/Faker/Provider/lv_LV/Person.php @@ -2,7 +2,6 @@ namespace Faker\Provider\lv_LV; -use Faker\Calculator\Luhn; use Faker\Provider\DateTime; class Person extends \Faker\Provider\Person @@ -145,11 +144,32 @@ public function personalIdentityNumber(\DateTime $birthdate = null) $birthdate = DateTime::dateTimeThisCentury(); } + $year = $birthdate->format('Y'); + + if ($year >= 2000 && $year <= 2099) { + $century = 2; + } elseif ($year >= 1900 && $year <= 1999) { + $century = 1; + } else { + $century = 0; + } + $datePart = $birthdate->format('dmy'); - $randomDigits = (string) static::numerify('####'); + $serialNumber = static::numerify('###'); + + $partialNumberSplit = str_split($datePart . $century . $serialNumber); + + $idDigitValidator = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; + $total = 0; + + foreach ($partialNumberSplit as $key => $digit) { + if (isset($idDigitValidator[$key])) { + $total += $idDigitValidator[$key] * (int) $digit; + } + } - $checksum = Luhn::computeCheckDigit($datePart . $randomDigits); + $checksumDigit = (1101 - $total) % 11 % 10; - return $datePart . '-' . $randomDigits . $checksum; + return $datePart . '-' . $century . $serialNumber . $checksumDigit; } } diff --git a/test/Faker/Provider/lv_LV/PersonTest.php b/test/Faker/Provider/lv_LV/PersonTest.php new file mode 100644 index 0000000000..94a3a05365 --- /dev/null +++ b/test/Faker/Provider/lv_LV/PersonTest.php @@ -0,0 +1,37 @@ +faker->personalIdentityNumber(); + + self::assertMatchesRegularExpression('/^[0-9]{6}-[0-9]{5}$/', $idNumber); + } + + public function testChecksumDigitCalculation(): void + { + $idNumber = $this->faker->personalIdentityNumber(\DateTime::createFromFormat('Y-m-d', '1981-05-24')); + + $serialNumber = substr($idNumber, 8, 3); + $serialNumberSplit = str_split($serialNumber); + + // calculate checksum, using static digits from date (2 4 0 5 8 1 1) and inserting random serial number digits + $checksumDigit = (1101 - (1 * 2 + 6 * 4 + 3 * 0 + 7 * 5 + 9 * 8 + 10 * 1 + 5 * 1 + 8 * (int) $serialNumberSplit[0] + 4 * (int) $serialNumberSplit[1] + 2 * (int) $serialNumberSplit[2])) % 11 % 10; + + self::assertSame('240581-1' . $serialNumber . $checksumDigit, $idNumber); + } + + protected function getProviders(): iterable + { + yield new Person($this->faker); + } +}