class SwedishPIN::Personnummer
Represents a parsed and valid Personnummer or Samordningsnummer for a particular individual.
Determine if this is a Personnummer or a Samordningsnummer using {coordination_number?}.
@see en.wikipedia.org/wiki/Personal_identity_number_(Sweden) Personnummer
on Wikipedia.
Attributes
Public Class Methods
@api private @private
Initializes a new instance from specific values. Please consider using {SwedishPIN.generate} instead of you want custom instances.
# File lib/swedish_pin/personnummer.rb, line 41 def initialize(year:, month:, day:, sequence_number:, control_digit:) @year = year @month = month @coordination_number = day > 60 @day = (day > 60 ? day - 60 : day) @sequence_number = sequence_number @control_digit = control_digit end
Public Instance Methods
Returns the age of the person this personnummer represents, as an integer of years since birth.
Swedish age could be defined as such: A person will be 0
years old when born, and 1
12 months after that, on the same day or the day after in the case of leap years. This is the same way most western countries count age.
If the {birthday} is in the future, then 0
will be returned.
@param [Time, Date] now The current time. @return [Integer] Number of 12 month periods that have passed since the birthdate; 0
or more.
# File lib/swedish_pin/personnummer.rb, line 159 def age(now = Time.now) age = now.year - year - (birthday_passed_this_year?(now) ? 0 : 1) [0, age].max end
Return the birthday for the person that is represented by this Personnummer.
@return [Date] the date of birth
# File lib/swedish_pin/personnummer.rb, line 54 def birthday Date.civil(year, month, day) end
Returns true
if this number is a Samordningsnummer (coordination number). This is a number that is granted to non-Swedish citizens until the time that they become citizens.
Coordination numbers are identical to a PIN, except that the “day” component has 60
added to it (i.e. 28+60=88
).
@note The {day} attribute will still return a valid date day, even for coordination numbers. @see sv.wikipedia.org/wiki/Samordningsnummer Samordningsnummer on Wikipedia (Swedish)
# File lib/swedish_pin/personnummer.rb, line 67 def coordination_number? @coordination_number end
Returns true
if the personnummer represents a person that is legally identified as female
. @return [true, false]
# File lib/swedish_pin/personnummer.rb, line 174 def female? sequence_number.even? end
Formats the personnummer in the unofficial “12-digit” format that includes the century and doesn't change separator depending on when the number is supposed to be shown.
This format is being adopted in a lot of places in favor of the “10-digit” format ({format_short}), but as of 2020 it remains an unofficial format.
Format: yyyymmdd-nnnn
@see format_short
# File lib/swedish_pin/personnummer.rb, line 112 def format_long [ format_date(true), "-", "%03d" % sequence_number, control_digit ].join("") end
Formats the PIN in the official “10-digit” format. This is the “real” Personnummer string.
Format: yymmdd-nnnn
or yymmdd+nnnn
The Personnummer specification says that starting from the year of a person's 100th birthday, the separator in their personnummer will change from a -
into a +
.
That means that every time you display a personnummer you also must consider the time of this action. Something that was read on date A and outputted on date B might not use the same string representation.
For this reason, the real personnummer is usually not what you want to store, only what you want to display in some cases.
This library recommends that you use {format_long} for storage.
@param [Time, Date] now The time when this personnummer is supposed to be displayed. @return [String] the formatted number @see format_long
# File lib/swedish_pin/personnummer.rb, line 92 def format_short(now = Time.now) [ format_date(false), short_separator(now), "%03d" % sequence_number, control_digit ].join("") end
Returns true
if the personnummer represents a person that is legally identified as male
. @return [true, false]
# File lib/swedish_pin/personnummer.rb, line 167 def male? sequence_number.odd? end
Formats the PIN into a String
.
You can provide the desired length to get different formats.
@note The length isn't how long the resulting string will be as the
resulting string will also have a separator included. The formats are colloquially called "10-digit" and "12-digit", which is why they are referred to as "length" here.
10
ornil
-
{format_short}
12
-
{format_long}
@param [Integer, nil] length The desired format. @param [Time, Date] now The current time. Only used by {format_short}. @raise [ArgumentError] If not provided a valid length. @return [String] @see format_short
@see format_long
# File lib/swedish_pin/personnummer.rb, line 139 def to_s(length = 10, now = Time.now) case length when 10 then format_short(now) when 12 then format_long else raise ArgumentError, "The only supported lengths are 10 or 12." end end
Private Instance Methods
# File lib/swedish_pin/personnummer.rb, line 201 def birthday_passed_this_year?(now) now.month > month || (now.month == month && now.day >= day) end
# File lib/swedish_pin/personnummer.rb, line 188 def format_date(include_century) [ (include_century ? pad(year / 100) : nil), pad(year % 100), pad(month), pad(coordination_number? ? day + 60 : day) ].join("") end
# File lib/swedish_pin/personnummer.rb, line 197 def pad(num) "%02d" % num end
# File lib/swedish_pin/personnummer.rb, line 180 def short_separator(now) if year <= (now.year - 100) "+" else "-" end end