(JS) Validate Swedish personnummer and organisationsnummer

By | May 12, 2020

Javascript functions for validating Swedish personal identity numbers (personnummer), and organisation numbers (organisationsnummer). The functions for personal identity number will also validate co-ordination number (samordningsnummer).

  /**
     * Validate a 10 digit swedish personnummer
     * @param pnr
     * @returns {boolean|boolean}
     */
    function validatePersonnummer(pnr) {
        var personummer = cleanDigitString(pnr);
        if (personummer.length > 10) {
            return false;
        }

        return isValidLuhn(personummer) && isPersonnummerDate(personummer);
    }


    function validateOrganisationNumber(orgnr) {
        var orgnumber = cleanDigitString(orgnr);

        if (orgnumber.length < 10 || orgnumber.length > 12 || orgnumber.length == 11) {
            console.log(orgnumber.length);
        }

        return isValidLuhn(orgnumber);
    }


    /**
     * Remove any non digit characters
     * @param digitString
     * @returns {*}
     */
    function cleanDigitString(digitString) {
        return digitString.replace(/\D/g, '');
    }


    /**
     * Check if date is valid for personnummer
     * @param pnr
     * @returns {boolean}
     */
    function isPersonnummerDate(pnr) {
        var year = parseInt(pnr.substring(0, 2));
        var month = parseInt(pnr.substring(2, 4));
        var day = parseInt(pnr.substring(4, 6));

        // Check year and month values
        if (year < 0 || year > 99 || month < 0 || month > 12) {
            return false;
        }

        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        // Adjust for leap years
        if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
            daysInMonth[1] = 29;
        }

        // Check that day is within range
        var dayIsValid = day > 0 && day <= daysInMonth[month - 1];

        // If day is outside range, check if it's +60 for samordningsnummer
        if (!dayIsValid) {
            dayIsValid = day > 60 && day <= daysInMonth[month - 1] + 60;
        }

        return dayIsValid;
    }

    /**
     * Check if last digit of number is vald Luhn control digit
     * @param pnr
     * @returns {boolean} 
     */
    function isValidLuhn(pnr) {
        var number;
        var checksum = 0;
        for (var i = pnr.length - 1; i >= 0; i--) {
            number = parseInt(pnr.charAt(i));
            if (i % 2 == 1) {
                checksum += number;
            } else {
                checksum += (number * 2) > 9 ? (number * 2) - 9 : number * 2;
            }
        }

        return checksum % 10 == 0;
    }

2 thoughts on “(JS) Validate Swedish personnummer and organisationsnummer

Leave a Reply to Johannes Kjellberg Cancel reply

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