PHP Function to Validate Lithuanian Personal Identification Number

[Update: here is a service that can be used either in browser or as an API to check multiple personal codes, using the functions described below: https://pr.lapas.info/ak]

Below is a simple function for PHP to check if a number is a valid Lithuanian personal identification number. As I made it for Codeigniter 4, it is included in a class (that can be easily integrated into CI4 framework), but if you want, you can use it as a standalone function.

By default it does not consider valid the numbers with future dates (as people at the time of validation cannot have such numbers). But it might be modified easily to allow for such theoretical numbers.

To check an ID outside the Codeigniter 4 validation context, you would do something like this:

$check = new CustomRules();
$error = '';

$code = '36709010185';
echo $check->valid_lt_id($code, $error) ? 'ok' : $error;
// prints "Lithuanian Personal Identification Number is not valid:
// wrong control number"
$error = '';
$code = '36709010186';
echo $check->valid_lt_id($code, $error) ? 'ok' : $error;
// prints "ok"

To use the class within your Codeigniter 4 project follow the instructions in documentation. You may also want to add translation to the messages if the function should work not only in English (again, see documentation examples for that).

So, here is the class with the relevant function:

/**
 * Codeigniter 4 validation rule for Lithuanian personal idntification number
 */

class CustomRules
{
    public function valid_lt_id($value, ?string &$error = null): bool
    {
        $valid = true;
        $error_msg = '';

        //check length/type
        if ($valid && (strlen($value) !== 11 || !is_numeric($value))) {
            $valid = false;
            $error_msg = 'length not equal to 11 numbers, or not all numbers';
        }

        $digits = str_split($value);

        //check date for validity
        if ($valid) {
            if (in_array($digits[0], [1, 2])) {
                $prefix = '18';
            } elseif (in_array($digits[0], [3, 4])) {
                $prefix = '19';
            } elseif (in_array($digits[0], [5, 6])) {
                $prefix = '20';
            } else {
                $prefix = '21';
            }

            $fullDate = $prefix . substr($value, 1, 6);
            $dateFormat = 'Ymd';

            // Create a DateTime object from the provided date string
            $date = DateTime::createFromFormat($dateFormat, $fullDate);

            // Check if the date is valid and the input format is correct
            $valid = $date && $date->format($dateFormat) === ($fullDate);
            if (!$valid) {
                $error_msg = 'wrong date inside number';
            }
        }

        // check date for not future
        if ($valid) {
            $valid = $fullDate <= date('Ymd');

            if (!$valid) {
                $error_msg = 'date in the future cannot be correct';
            }
        }

        // check control number
        if ($valid) {

            $last = null;
            $s = $digits[0] * 1 + $digits[1] * 2 + $digits[2] * 3
                + $digits[3] * 4 + $digits[4] * 5 + $digits[5] * 6
                + $digits[6] * 7 + $digits[7] * 8 + $digits[8] * 9
                + $digits[9] * 1;

            if (($s % 11) !== 10) {
                $last = $s % 11;
            } else {
                $s = $digits[0] * 3 + $digits[1] * 4 + $digits[2] * 5
                    + $digits[3] * 6 + $digits[4] * 7 + $digits[5] * 8
                    + $digits[6] * 9 + $digits[7] * 1 + $digits[8] * 2
                    + $digits[9] * 3;

                if (($s % 11) !== 10) {
                    $last = $s % 11;
                } else {
                    $last = 0;
                }
            }

            $valid = $digits[10] == $last;
            if (!$valid) {
                $error_msg = 'wrong control number';
            }
        }

        //check if the order number is not zero, should never be
        if ($valid && (string) substr($value, 7, 3) === '000') {
            $valid = false;
            $error_msg = 'wrong registration number';
        }

        if ($valid) {
            return true;
        }
        // $error = lang('myerrors.invalidCode');
        $error = 'Lithuanian Personal Identification Number is not valid: '
            . $error_msg;
        return false;
    }
}

Lithuanian person identification number structure is described in this Wikipedia article. The most complicated part is the last digit – control number. So, if you ever need to fake such numbers for tests, below I provide a function that, upon receiving an otherwise soundly composed personal identification number will spit it out with the 11th digit calculated correctly.

/**
 * This function adds/updates the 11th digit to the Lithuanian Personal
 * Identification Number supplied as parameter to function thus making it
 * a valid number.
 */
function completeLPIN(int $code): int
{
    if (strlen($code) < 10) {
        throw new Exception(
            'Too few digits; Lithuanian personal code has '
                . '11 digits, and this function has to receive at '
                . 'least the first 10.'
        );
        // exception saying "too few numbers" here
    }
    $ak = str_split($code);
    $last = null;

    $s = $ak[0] * 1 + $ak[1] * 2 + $ak[2] * 3 + $ak[3] * 4 + $ak[4] * 5
        + $ak[5] * 6 + $ak[6] * 7 + $ak[7] * 8 + $ak[8] * 9 + $ak[9] * 1;
    if (($s % 11) !== 10) {
        $last = $s % 11;
    } else {
        $s = $ak[0] * 3 + $ak[1] * 4 + $ak[2] * 5 + $ak[3] * 6 + $ak[4] * 7
            + $ak[5] * 8 + $ak[6] * 9 + $ak[7] * 1 + $ak[8] * 2 + $ak[9] * 3;
        if (($s % 11) !== 10) {
            $last = $s % 11;
        } else {
            $last = 0;
        }
    }

    return substr($code, 0, 10)  . $last;
}

echo completeLPIN(3770909012);
// would output:
// 37709090123

Paskelbta

sukūrė

Žymos:

Komentarai

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Raktažodžiai

atviras kodas bylos Codeigniter darbas drėlingas el. parašas EŽTT genocidas gimimas holokaustas InEnglish internetas joga Jurgelis karo nusikaltimai kde konferencija Kononov Kraujelis kubuntu LAT LGGRTC lietuvybė linux microsoft mokslai mokslas nusikaltimai žmoniškumui partizanai PHP pokaris programavimas programos religija religijos laisvė sausio13 sektos seneliai teismas teisė tinklaraštis vasiliauskas vertimas wordpress žurnalizmas

Vėliausi įrašai

Visuomenė, politika, etc.

Tinklaraščiai

Technologijos

Mano viešasis PGP raktas
keybase.io paskyra

Autorinės teisės

© 2004-2024, Donatas Glodenis. Šiame tinklaraštyje paskelbtą autorinį turinį kitur galima naudoti tik gavus raštišką autoriaus sutikimą.

Jei konkrečiu atveju nėra nurodyta kitaip, tinklaraščio įrašuose išsakomi vertinimai yra asmeninė jų autoriaus nuomonė.