Skip to main content

SwePin

PyPI version Python versions License Documentation

A comprehensive library for parsing, validating, and handling Swedish Personal Identity Numbers (personnummer)

Features

  • ✅ Validate Swedish Personal Identity Numbers
  • 📊 Parse and extract all components (birth date, gender, validation digit, etc.)
  • 🌍 Multi-language support (English and Swedish)
  • 🧮 Age calculation with customizable reference date
  • 🔄 Format conversion (with/without separators, 10/12 digits)
  • ⚙️ Support for coordination numbers and centenarians
  • 🎲 Generate valid random PIN numbers for testing
  • 🔒 Strict mode for enforcing exact format requirements

Installation

pip install swepin

Quick Start

# Import using the full name
from swepin import SwedishIdentityPersonalNumber

# Or using the shorter alias
from swepin import SwePin

# For strict format validation (YYYYMMDD-NNNN only)
from swepin import SwePinStrict

# Parse a Swedish Personal Identity Number
pin = SwePin("198012241234")

# Get basic information
print(f"Birth date: {pin.get_date()}")          # 1980-12-24
print(f"Age: {pin.age}")                        # Current age based on today's date
print(f"Gender: {'Male' if pin.male else 'Female'}")

# Display detailed information
print(pin.pretty_print())                       # Prints a formatted table with all details

# Get structured data
pin.dict                                        # Dictionary representation
pin.json                                        # JSON representation

Understanding Swedish Personal Identity Numbers

Swedish Personal Identity Numbers follow this format: YYYYMMDD-XXXX or YYMMDD-XXXX (or + instead of - for separator)

┌───────────────┬───────┬───────────────────┐
│  BIRTH DATE   │ SEP   │   BIRTH NUMBER    │
├───┬───┬───┬───┼───────┼───┬───┬───┬───────┤
│ C │ Y │ M │ D │ - / + │ B │ B │ G │ Valid │
└───┴───┴───┴───┴───────┴───┴───┴───┴───────┘
  │   │   │   │     │     │   │   │     │
  │   │   │   │     │     │   │   │     └── Validation Digit (Luhn algorithm)
  │   │   │   │     │     │   │   │
  │   │   │   │     │     │   │   └── Gender Digit (odd = male, even = female)
  │   │   │   │     │     │   │
  │   │   │   │     │     └───┴── Birth Place (regional code for pre-1990)
  │   │   │   │     │
  │   │   │   │     └── Separator (- if < 100 years old, + if >= 100)
  │   │   │   │
  │   │   │   └── Day (01-31, or 61-91 for coordination numbers a.k.a samordningsnummer)
  │   │   │
  │   │   └── Month (01-12)
  │   │
  │   └── Year (last two digits)
  │
  └── Century (optional in short format, derived when not provided)

Features

Multiple Format Support

SwePin supports all standard formats of Swedish Personal Identity Numbers:

# All these are valid and will parse correctly with SwePin
SwePin("198012241234")    # Full format (12 digits)
SwePin("8012241234")      # Short format (10 digits)
SwePin("19801224-1234")   # With separator
SwePin("801224-1234")     # Short with separator
SwePin("19801284-1234")   # Coordination number (day 24 + 60 = 84)
SwePin("121212+1212")     # Person over 100 years old (+ separator)

Strict Format Validation

For applications that require exact format compliance, use SwePinStrict which enforces specific PIN formats through the PinFormat enum:

from swepin import SwePinStrict, PinFormat

# Default format (LONG_WITH_SEPARATOR)
pin = SwePinStrict("19801224-1234")  # ✅ Uses default format
pin = SwePinStrict("19801284-1234")  # ✅ Valid coordination number

# Specify format explicitly
pin1 = SwePinStrict("19801224-1234", PinFormat.LONG_WITH_SEPARATOR)    # 13 chars
pin2 = SwePinStrict("198012241234", PinFormat.LONG_WITHOUT_SEPARATOR)  # 12 chars
pin3 = SwePinStrict("801224-1234", PinFormat.SHORT_WITH_SEPARATOR)     # 11 chars

### Format Conversion

Easily convert between different representations:

```python
pin = SwePin("198012241234")

# Access different format representations
print(pin.long_str_repr)                # "198012241234" (12 digits, no separator)
print(pin.long_str_repr_w_separator)    # "19801224-1234" (12 digits with separator)
print(pin.short_str_repr_w_separator)   # "8012241234" (10 digits with separator)

Generate Random Valid PINs for Testing

Read this!

Language Support

from swepin.swedish_personal_identity_number import SwedishPersonalIdentityNumber, Language

pin = SwedishPersonalIdentityNumber("198012241234")

# Get output in different languages
print(pin.pretty_print(language=Language.ENG))  # Default - English
print(pin.pretty_print(language=Language.SWE))  # Swedish

# Get dictionary with Swedish keys
sv_dict = pin.to_dict(language=Language.SWE)

Detailed Information

Get comprehensive information about a personal number with a beautiful formatted display:

pin = SwePin("198012241234")
print(pin.pretty_print())

Output:

┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃  Swedish Personal Identity Number Details                         ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃         Property         ┃                 Value                  ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃      Original Number     ┃ 198012241234                           ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃        BIRTH DATE        ┃                                        ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃         Century          ┃ 19                                     ┃
┃      Year (2 digits)     ┃ 80                                     ┃
┃    Full Year (4 digits)  ┃ 1980                                   ┃
┃          Month           ┃ 12                                     ┃
┃           Day            ┃ 24                                     ┃
┃         Full Date        ┃ 1980-12-24                             ┃
┃    Coordination Number   ┃ No                                     ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃         SEPARATOR        ┃ -                                      ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃       BIRTH NUMBER       ┃                                        ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃      Complete Number     ┃ 123                                    ┃
┃     Birth Place Digits   ┃ 12                                     ┃
┃       Gender Digit       ┃ 3                                      ┃
┃     Validation Digit     ┃ 4                                      ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃    DERIVED PROPERTIES    ┃                                        ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃           Age            ┃ 44                                     ┃
┃          Gender          ┃ Male                                   ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃         FORMATS          ┃                                        ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃      Long (12 digits)    ┃ 198012241234                           ┃
┃         Long (sep)       ┃ 19801224-1234                          ┃
┃  Short (10 digits) (sep) ┃ 801224-1234                            ┃
┃     Short without (sep)  ┃ 8012241234                             ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Validation

The library validates personal numbers using the Luhn algorithm to ensure the check/validation digit is correct:

try:
    pin = SwePin("198012241234")  # Valid personal number
    print("Valid personal identity number")
except Exception as e:
    print(f"Invalid: {e}")

try:
    pin = SwePin("198012241235")  # Invalid check digit
    print("Valid personal identity number")
except Exception as e:
    print(f"Invalid: {e}")  # Will print error about validation digit mismatch

Special Cases

Coordination Numbers

For people without a permanent residence in Sweden, coordination numbers (samordningsnummer) are used where the day is increased by 60:

pin = SwePin("198012841234")  # Day 24 + 60 = 84
print(f"Is coordination number: {pin._is_coordination_number()}")  # True
print(f"Birth date: {pin.get_date()}")  # Still returns 1980-12-24

Centenarians

For people 100 years or older, a + separator is used instead of - in the short format:

pin = SwePin("121212+1212")  # Person born in 1912
print(pin.short_str_repr)    # "121212+1212"
print(pin.full_year)         # "1912"

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Made with ❤️ in Sweden

Metadata

Release files for swepin 1.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for swepin 1.1.7
File Size Uploaded Provenance Actions
swepin-1.1.7.tar.gz 18.3 kB Without provenance Details for swepin-1.1.7.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for swepin 1.1.7
File Interpreter ABI Platform Actions
swepin-1.1.7-py3-none-any.whl Python 3 none any Details for swepin-1.1.7-py3-none-any.whl

Total release size: 32.6 kB

Release files / swepin-1.1.7.tar.gz

Download URL swepin-1.1.7.tar.gz
Size 18.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c533a992366ae6464ac2c3055b79565f4ead91a42602f6f540cbede45cf70840
BLAKE2b-256 checksum
How to use checksums
aff5f63357b6693df6f86db30d6a75537755fa9f3d48f949ae2a100a07967475
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / swepin-1.1.7-py3-none-any.whl

Download URL swepin-1.1.7-py3-none-any.whl
Size 14.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a5ce966a5868fc90666d49704c7ac0ff2b1bf273357a67c96dbf907d7bcc24f
BLAKE2b-256 checksum
How to use checksums
e2e40227812103f1d5c9ce5fb1d4bf88a9173f8fa81e1080739b02e12f23ae09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Security for swepin 1.1.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page