swedish-pnr

1.0.3

Parse and verify Swedish personal identity numbers, "personnummer" in Swedish, or PNR for short in this library.
Oops-AB/swedish-pnr

What's New

Fix bug related to coordination numbers

2024-06-20T15:58:32Z

When deducing the century of a coordination number the normalized form must still be a coordination number. I.e., the day component is still increased by 60.

An example from the test cases (with a reference date of 2017-12-12): the coordination number 171270-0002 should normalize to 20171270-0002. Before this fix it was instead normalized to 20171210-0002.

SwedishPNR

Parse and verify Swedish personal identity numbers, "personnummer" in Swedish, or PNR for short in this library.

What's in a number?

The Swedish Tax Agency ("Skatteverket" in Swedish) has a description of the format, but it basically boils down to this:

  • A PNR comprises 10 digits and a separator on the form yyMMdd-nnnc where yyMMdd denotes the date of birth, nnn is a sequence number called "birth number", and c is a checksum of the previous nine digits.

  • The date of birth of a PNR lacks its century! So, the actual date of birth has to be deduced relative a reference date. In all normal uses, that reference date is today. Right now.

  • Temporary PNRs called coordination numbers ("sammordningsnummer" in Swedish) can be issued to people not listed in the Swedish Population Register. A listed person is "folkbokförd" in Swedish; an unlisted person is... not "folkbokförd"... umm, let's move on. These numbers follow the same rules as normal PNRs but have the number 60 added to the day number (dd in the format above).

  • When a person reaches the honorable age of 100 years, a plus sign (+) is used for the separator in their PNR, i.e., yyMMdd+nnnc.

  • Although the standard form of a PNR is the eleven character version described so far, other forms are also in common use. This library handles PNRs on the following forms. Note that the last two forms include the century, so no deduction is necessary, neither is the plus separator allowed; unsurprisingly these forms are popular, if not required in many apps and sites today.

    • 10 characters: yyMMddnnnc (standard form but lacking separator)
    • 11 characters: yyMMdd-nnnc (the "standard" form)
    • 11 characters: yyMMdd+nnnc (centennials)
    • 12 characters: yyyyMMddnnnc
    • 13 characters: yyyyMMdd-nnnc

Other curiosities:

  • As there are only 999 distinct birth numbers available1 for a given date, Skatteverket may run out of numbers! If that's the case identity numbers will apparently be selected from neighbouring dates. Thus, some people have PNRs with dates of birth that aren't their actual dates of birth.

  • Because the century is not part of the PNR, it is also not included in the checksum calculation. Two PNRs of the longer form that differ only by a century (or a multiple thereof) have identical checksums. Don't skip the age check!

  • Speaking of age, short form PNRs can't be used for really, really old people. Sorry, Bicentennial Man.

Getting started

To make use of this library, declare a dependency in your Package.swift:

// 🇸🇪 Swedish personal identity number validation
.package(url: "https://github.com/Oops-AB/swedish-pnr.git", from: "1.0.0"),

and to your target:

.executableTarget(name: "Smorgasbord", dependencies: [
    .product(name: "SwedishPNR", package: "swedish-pnr")
],

Let's get going:

let pnr = try! SwedishPNR.parse(input: "  20171210-0005\t")
print("\(pnr.normalized)")

Output

20171210-0005

The parse() function either returns a PNR or throws a Parser.ParseError .

The SwedishPNR type

A successful parse returns a SwedishPNR. This type has a few properties:

  • input is the original string, including leading or trailing space,
  • normalized is the full, 13 character version of the PNR,
  • birthDateComponents is a DateComponents instance holding year, month and day,
  • birthDate is a Date instance representing the first instant of the birth date in the Sweden time zone.

The SwedishPNR also has a method age(at:) -> Int that calculates the age in years relative a reference date (which defaults to now).

Note that all date calculations (age and deducing century) are performed in the Sweden time zone.

Footnotes

  1. There may very well be fewer birth numbers available as some might be reserved or excluded. I've not found a definite list. Skatteverket may know.

Description

  • Swift Tools 5.9.0
View More Packages from this Author

Dependencies

  • None
Last updated: Sat Oct 19 2024 17:39:12 GMT-0900 (Hawaii-Aleutian Daylight Time)