Crate pesel_rs

Source
Expand description

PESEL validation and detail extraction with multiple data layout implementations.

Crates.io Version Static Badge Crates.io License

§Definitions

PESEL: YYMMDDOOOOC

  • YY - Last two digits of year of birth
  • MM - Month of birth (shifted depending on year of birth as shown by the table below)
Year1800 - 18991900 - 19992000 - 20992100 - 21992200 - 2299
Month shift+800+20+40+60
  • DD - Day of birth
  • OOOO - Ordinal number, where the last digit denotes the gender ([0, 2, 4, 6, 8] = female, [1, 3, 5, 7, 9] = male)
  • C - Control number

§Usage

There are two PESEL structs provided by the crate, both implementing the PeselTrait.

  • crate::bit_fields::Pesel - Stores each section of the PESEL in the following layout: 7 bits | YY | 5 bits | MM | 5 bits | DD | 5 bits | OOOO | 5 bits | C, where in between bits are unused. Extracting each field is done using bitwise operations. You can get the human readable number using u64::from.

  • crate::human_redable::Pesel - Stores the PESEL as a plain number, extracting each field requires modulo and division operations, if often accessing individual fields is important to you, you should probably use crate::bit_fields::Pesel.

If you just need to validate a number or extract a specific section without using the structs, you could use functions in the lib root. Most of these functions won’t check if the value they’re returning is valid, unlike the structs who are guaranteed to always return a valid value.

§Examples

Function that takes a name and welcomes the person based on date of birth and gender from the PESEL. Implemented using crate::bit_fields::Pesel because we’re mostly reading the fields.

use pesel_rs::{prelude::*, bit_fields::Pesel};

fn welcome(first_name: &str, pesel: u64) {
    match Pesel::try_from(pesel) {
        Ok(pesel) => {
            if pesel.date_of_birth() > NaiveDate::from_ymd_opt(2015, 1, 1).unwrap() {
                let gender = if pesel.gender() == Gender::Male { "boy" } else { "girl" };
                println!("Wow {first_name}! You're such a young {gender}!");
            } else {
                println!("{first_name}, you're very old, I'm sorry 😞");
            }
        }
        Err(_) => println!("Huh, what you gave me doesn't seem to be a valid pesel {first_name}..."),
    }
}

Function finding a pesel with the oldest date of birth. Working with a generic PESEL, we introduce additional bounds (required by PeselTrait).

use pesel_rs::prelude::*;

fn oldest<T: PeselTrait>(pesels: &[T])
where
    u64: From<T>,
    for<'a> u64: From<&'a T>
{
    assert!(pesels.len() > 0);

    let mut oldest_index = 0;
    pesels.iter().skip(1).enumerate().for_each(|(i, pesel)| {
        if pesels[oldest_index].date_of_birth() < pesel.date_of_birth() {
            oldest_index = i;
        }
    });

    let date_of_birth = pesels[oldest_index].date_of_birth();
    println!("PESEL nr. {oldest_index} is the oldest! Born at {date_of_birth}")
}

Re-exports§

pub use chrono;
pub use thiserror;

Modules§

bit_fields
human_redable
prelude

Macros§

impl_try_from_str_for_pesel

Enums§

Gender
PeselTryFromError
ValidationError

Traits§

PeselTrait
Trait for implementing a PESEL.

Functions§

control_section
Extract the control section.
date_of_birth
Extract date of birth.
day
Extract day of birth.
day_section
Extract the day of birth section.
gender
Extract gender.
month
Extract month of birth.
month_from_section
Errors
month_section
Extract the month of birth section.
month_to_section
Errors
ordinal_section
Extract the ordinal section.
validate
Check if the PESEL is valid.
year
Extract year of birth.
year_from_sections
year_section
Extract the year of birth section.