isikukood
Version:
Estonian personal ID (isikukood) JavaScript module
213 lines (212 loc) • 6.01 kB
JavaScript
class Isikukood {
constructor(c) {
this._code = String(c);
}
get code() {
return this._code;
}
set code(c) {
this._code = String(c);
}
/**
* Algorithm to get control number.
*/
getControlNumber(code = "") {
if (!code) {
code = this.code;
}
const mul1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1];
const mul2 = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3];
let controlNum = 0;
let total = 0;
for (let i = 0; i < 10; ++i) {
total += Number(code.charAt(i)) * mul1[i];
}
controlNum = total % 11;
total = 0;
if (controlNum === 10) {
for (let i = 0; i < 10; ++i) {
total += Number(code.charAt(i)) * mul2[i];
}
controlNum = total % 11;
if (10 === controlNum) {
controlNum = 0;
}
}
return controlNum;
}
/**
* Validates the Estonian personal ID.
*/
validate() {
if (this.code.charAt(0) === "0" || this.code.length !== 11) {
return false;
}
if (this.getControlNumber() !== Number(this.code.charAt(10))) {
return false;
}
const year = Number(this.code.substring(1, 3));
const month = Number(this.code.substring(3, 5));
const day = Number(this.code.substring(5, 7));
const birthDate = this.getBirthday();
return year === birthDate.getFullYear() % 100 && birthDate.getMonth() + 1 === month && day === birthDate.getDate();
}
/**
* Gets the gender of a person
*/
getGender() {
const genderNum = this.code.charAt(0);
const maleDigits = ["1", "3", "5"];
const femaleDigits = ["2", "4", "6"];
if (maleDigits.includes(genderNum)) {
return "male" /* MALE */;
} else if (femaleDigits.includes(genderNum)) {
return "female" /* FEMALE */;
} else {
return "unknown" /* UNKNOWN */;
}
}
/**
* Get the age of a person in years.
*/
getAge() {
const birthDate = this.getBirthday();
const today = /* @__PURE__ */ new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birthDate.getDate()) {
age--;
}
return age;
}
/**
* Get the birthday of a person.
*/
getBirthday() {
let year = Number(this.code.substring(1, 3));
const month = Number(this.code.substring(3, 5).replace(/^0/, "")) - 1;
const day = Number(this.code.substring(5, 7).replace(/^0/, ""));
const firstNumber = this.code.charAt(0);
for (let i = 1, j = 1800; i <= 8; i += 2, j += 100) {
if ([i, i + 1].map(String).includes(firstNumber)) {
year += j;
}
}
return new Date(year, month, day);
}
/**
* Parses the code and return it's data as object.
*/
parse() {
return Isikukood.parse(this.code);
}
static parse(code) {
const ik = new this(code);
const data = {
gender: ik.getGender(),
birthDay: ik.getBirthday(),
age: ik.getAge()
};
return data;
}
/**
* Validates the Estonian personal ID.
* In params argument months are beginning from 1, not from 0.
* If code cannot be generated empty string is returned.
* 1 - January
* 2 - February
* 3 - March
* etc.
*/
static generate(params = {}) {
let y;
let m;
let d;
const gender = params.gender || (Math.round(Math.random()) === 0 ? "male" /* MALE */ : "female" /* FEMALE */);
let personalId = "";
const hospitals = [
"00",
// Kuressaare Haigla (järjekorranumbrid 001 kuni 020)
"01",
// Tartu Ülikooli Naistekliinik, Tartumaa, Tartu (011...019)
"02",
// Ida-Tallinna Keskhaigla, Hiiumaa, Keila, Rapla haigla (021...220)
"22",
// Ida-Viru Keskhaigla (Kohtla-Järve, endine Jõhvi) (221...270)
"27",
// Maarjamõisa Kliinikum (Tartu), Jõgeva Haigla (271...370)
"37",
// Narva Haigla (371...420)
"42",
// Pärnu Haigla (421...470)
"47",
// Pelgulinna Sünnitusmaja (Tallinn), Haapsalu haigla (471...490)
"49",
// Järvamaa Haigla (Paide) (491...520)
"52",
// Rakvere, Tapa haigla (521...570)
"57",
// Valga Haigla (571...600)
"60",
// Viljandi Haigla (601...650)
"65",
// Lõuna-Eesti Haigla (Võru), Pälva Haigla (651...710?)
"70",
// All other hospitals
"95"
// Foreigners who are born in Estonia
];
if (!["male" /* MALE */, "female" /* FEMALE */].includes(gender)) {
return "";
}
if (params.birthYear) {
y = params.birthYear;
} else {
y = Math.round(
Math.random() * 100 + 1900 + ((/* @__PURE__ */ new Date()).getFullYear() - 2e3)
);
}
if (params.birthMonth) {
m = params.birthMonth;
} else {
m = Math.floor(Math.random() * 12) + 1;
}
if (params.birthDay) {
d = params.birthDay;
} else {
const daysInMonth = new Date(y, m, 0).getDate();
d = Math.floor(Math.random() * daysInMonth) + 1;
}
for (let i = 1800, j = 2; i <= 2100; i += 100, j += 2) {
if (y >= i && y < i + 100) {
switch (gender) {
case "male" /* MALE */:
personalId += String(j - 1);
break;
case "female" /* FEMALE */:
personalId += String(j);
break;
default:
return "";
}
}
}
personalId += String(y).substring(2, 4);
personalId += String(m).padStart(2, "0");
personalId += String(d).padStart(2, "0");
personalId += hospitals[Math.floor(Math.random() * hospitals.length)];
personalId += String(Math.floor(Math.random() * 10));
personalId += String(this.prototype.getControlNumber(personalId));
return personalId;
}
}
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["MALE"] = "male";
Gender2["FEMALE"] = "female";
Gender2["UNKNOWN"] = "unknown";
return Gender2;
})(Gender || {});
export {
Gender,
Isikukood as default
};