Skip to content

Commit

Permalink
Implement age
Browse files Browse the repository at this point in the history
  • Loading branch information
bombsimon committed May 26, 2024
1 parent 0945912 commit a6238cb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/personnummer.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import gleam/regex
import gleam/result
import gleam/string

/// DateTime represents the type return from Erlang `local_time`.
pub type DateTime =
#(#(Int, Int, Int), #(Int, Int, Int))

// An external function call to calendar.local_time/0. This is marked as public
// to be able to use from unit tests but is not intended to be used by external
// packages.
// https://www.erlang.org/doc/apps/stdlib/calendar#local_time/0
@external(erlang, "calendar", "local_time")
pub fn now() -> DateTime

/// A representation of a date in time, holding a year, month and day.
pub type Date {
Date(year: Int, month: Int, day: Int)
Expand Down Expand Up @@ -154,6 +165,20 @@ fn valid_date(date: Date) -> Bool {
}
}

/// Get the age of the person holding the passed personnummer.
pub fn age(pnr: Personnummer) -> Int {
let #(#(current_year, current_month, current_day), _) = now()

case pnr.date.month > current_month {
True -> current_year - pnr.date.year - 1
False ->
case pnr.date.month == current_month && pnr.date.day > current_day {
True -> current_year - pnr.date.year - 1
False -> current_year - pnr.date.year
}
}
}

/// Check if the personnummer is a coordination number (Samordningsnummer):
/// https://skatteverket.se/privat/folkbokforing/samordningsnummer.4.5c281c7015abecc2e201130b.html
pub fn is_coordination(pnr: Personnummer) -> Bool {
Expand Down
68 changes: 68 additions & 0 deletions test/personnummer_test.gleam
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import gleam/int
import gleam/list
import gleam/string
import gleeunit
import gleeunit/should
import personnummer
Expand Down Expand Up @@ -65,3 +67,69 @@ pub fn gender_test() {
)
})
}

pub fn age_test() {
let #(#(current_year, current_month, current_day), _) = personnummer.now()
let forty_years_ago = { current_year - 40 } % 1900

let #(y1, m1, d1) = case current_month > 1 {
True -> #(forty_years_ago, current_month - 1, current_day)
False -> #(forty_years_ago - 1, 12, 31)
}

let #(y2, m2, d2) = case current_month < 12 {
True -> #(forty_years_ago, current_month + 1, current_day)
False -> #(forty_years_ago + 1, 1, 1)
}

let assert Ok(forty) =
string.concat([
int.to_string(y1),
int.to_string(m1)
|> string.pad_left(to: 2, with: "0"),
int.to_string(d1)
|> string.pad_left(to: 2, with: "0"),
"0000",
])
|> personnummer.new()

let assert Ok(forty_one) =
string.concat([
int.to_string(forty_years_ago - 1),
int.to_string(current_month)
|> string.pad_left(to: 2, with: "0"),
int.to_string(current_day)
|> string.pad_left(to: 2, with: "0"),
"0000",
])
|> personnummer.new()

let assert Ok(thirty_nine) =
string.concat([
int.to_string(y2),
int.to_string(m2)
|> string.pad_left(to: 2, with: "0"),
int.to_string(d2)
|> string.pad_left(to: 2, with: "0"),
"0000",
])
|> personnummer.new()

should.equal(
forty
|> personnummer.age(),
40,
)

should.equal(
forty_one
|> personnummer.age(),
41,
)

should.equal(
thirty_nine
|> personnummer.age(),
39,
)
}

0 comments on commit a6238cb

Please sign in to comment.