This package aims to provide a toolbox to handle Swedish identification numbers of three different types; social security numbers (or personal numbers), coordination numbers and organization numbers. They are all validated using the Luhn algorithm with some exceptions to the coordination number.
In addition to the correct checksum calculated with the Luhn algorithm, the following rules applies:
- Divider between digits and control numbers may only be divided with
-
, or+
- A social security number must be a valid date
- An organization numbers third digit must be >= 2
- A coordination number must have a date where day value is > 60
Some extra data may be extracted from a social security number regarding the person or the organization number regarding companies.
The Person
type holds and implements these things.
IsCoordination
tells if the person has a coordination numberDate
is atime.Time
type with the birth dateCounty
holds the county code for people born before 1990Gender
holds whether the person is aMale
orFemale
Zodiac
holds the persons zodiac sign (e.g. Aries)Age()
can tell the persons age (in UTC timezone)IsOfAge(n int)
can tell if the person isn
(or above)Male()
is true if it's aMale
Female()
is true if it's aFemale
The Organization
type holds and implements these things.
CompanyForm
hods the guessed form for the company
Just validate number with Luhn algorithm independent of type.
parsed, err := Parse("552099-1122")
if err != nil {
panic("could not parse")
}
if !parsed.Valid() {
panic("this is not a valid luhn number")
}
Validate a social security number or coordination number. The interface supports strings, integers and floats of the most common types.
// I just care for validation
if IsValidPerson("800101-3294") {
return RealFood()
}
if !IsValidPerson(800101329) {
return MaybeMetal()
}
// But for these I actually care!
person, err := NewPerson("20090314-6603")
if err != nil {
panic("what now?!")
}
if !person.Valid() {
return NotEvenForBabies()
}
if person.Female() && person.IsOfAge(16) {
return TimeToStartDriving()
}
The interface to validate organizations is the same.
if !IsValidOrganization("556703-7485") {
return NoGo()
}
If you want to skip parsing multiple times you can construct types from a parsed type.
parsed, err := Parse("800101-3294")
if err != nil {
panic("no?")
}
person, _ := NewPersonFromParsed(parsed)
org, _ := NewOrganizationFromParsed(parsed)
// Any valid goes!
return person.Valid() || org.Valid()
// Perform the validation without keeping the types and only parse once.
return parsed.ValidPerson() || parsed.ValidOrganization()
In addition to validation this package also provide support to generate social security numbers for private persons. This is great for testing purposes. There are two interfaces, one where everything is random (age and sex) and one where you provided it.
// Just give me something!
validPerson, err := GenerateAny()
if err != nil {
panic("oh lord")
}
// Or maybe with some preferences.
t, _ := time.Parse("2006-01-02", "1999-02-20")
girlFrom99, err := Generate(t, Female)
if err != nil {
panic("no Spice Girl I guess?!")
}