Skip to content

PESEL

PESEL (Powszechny Elektroniczny System Ewidencji Ludności) is Poland’s universal 11-digit citizen identifier. It encodes the holder’s birth date, birth century, gender, and an ordinal serial number.

import { Numerik } from '@slashlab/numerik-js'
// Boolean
Numerik.pesel().isValid('92060512186') // true
// Rich result
const result = Numerik.pesel().validate('92060512186')
result.isValid // true
// Parse to value object
const pesel = Numerik.pesel().parse('92060512186')
// Null on failure instead of exception
const maybe = Numerik.pesel().tryParse('bad-input') // null

parse() and tryParse() return a Pesel instance.

MethodReturn typeDescription
getRaw()stringThe original input, untouched.
getNormalized()stringWhitespace-stripped digits.
toString()stringAlias for getNormalized().
MethodReturn typeDescription
getBirthDate()DateBirth date decoded from the PESEL. Returns a new Date object, decoupled from the original.
getGender()GenderGender.Male or Gender.Female.
getOrdinalNumber()numberThe 4-digit ordinal serial (digits 7–10). The last digit also encodes gender: odd = male, even = female.
getCentury()numberThe birth century as a base year, e.g. 1900, 2000, 2100.
MethodReturn typeDescription
isMale()booleantrue when gender is Gender.Male.
isFemale()booleantrue when gender is Gender.Female.
getAge()numberFull years elapsed from birth date to today.
isAdult()booleantrue when getAge() >= 18.
import { Numerik, Gender } from '@slashlab/numerik-js'
const pesel = Numerik.pesel().parse('92060512186')
pesel.getRaw() // '92060512186'
pesel.getNormalized() // '92060512186'
pesel.getBirthDate() // Date — 1992-06-05
pesel.getGender() // Gender.Female
pesel.isFemale() // true
pesel.getOrdinalNumber() // 1218 (digits 7–10)
pesel.getCentury() // 1900
pesel.getAge() // calculated from today
pesel.isAdult() // true

The month digits in a PESEL encode both the real month and the birth century:

Stored month rangeReal monthBirth century
01–1201–121900–1999
21–3201–122000–2099
41–5201–122100–2199
61–7201–122200–2299
81–9201–121800–1899
ReasonValueWhen
InvalidLengthinvalid_lengthInput is not exactly 11 digits after normalisation.
InvalidCharactersinvalid_charactersNon-digit characters remain after stripping whitespace.
InvalidMonthinvalid_monthMonth encoding does not match any known century range.
InvalidDateinvalid_dateThe decoded date is not a real calendar date.
FutureDatefuture_dateThe decoded birth date is in the future (strict mode only).
InvalidChecksuminvalid_checksumChecksum digit does not match the computed value.
AllSameDigitall_same_digitAll 11 digits are identical (strict mode only).

Weights: 1, 3, 7, 9, 1, 3, 7, 9, 1, 3

  1. Reject inputs longer than 32 characters. Strip whitespace. Assert exactly 11 digits.
  2. Decode birth date using the century encoding table above. Assert the date is a real calendar date. In strict mode, also reject birth dates in the future.
  3. Compute checksum: multiply each of the first 10 digits by its weight, sum the products, take mod 10, subtract from 10, take mod 10 again. The result must equal digit 11.
  4. In strict mode, reject inputs where all 11 digits are identical.

See Algorithms for the full reference.