This repository has been archived by the owner on Sep 1, 2020. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
personnummer.go
118 lines (90 loc) · 2.12 KB
/
personnummer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package personnummer
import (
"math"
"reflect"
"regexp"
"strconv"
"time"
)
// luhn will test if the given string is a valid luhn string.
func luhn(str string) int {
sum := 0
for i, r := range str {
c := string(r)
v, _ := strconv.Atoi(c)
v *= 2 - (i % 2)
if v > 9 {
v -= 9
}
sum += v
}
return int(math.Ceil(float64(sum)/10)*10 - float64(sum))
}
// testDate will test if date is valid or not.
func testDate(century string, year string, month string, day string) bool {
t, err := time.Parse("01/02/2006", month+"/"+day+"/"+century+year)
if err != nil {
return false
}
y, _ := strconv.Atoi(century + year)
m, _ := strconv.Atoi(month)
d, _ := strconv.Atoi(day)
if y > time.Now().Year() {
return false
}
return !(t.Year() != y || int(t.Month()) != m || t.Day() != d)
}
// getCoOrdinationDay will return co-ordination day.
func getCoOrdinationDay(day string) string {
d, _ := strconv.Atoi(day)
d -= 60
day = strconv.Itoa(d)
if d < 10 {
day = "0" + day
}
return day
}
// Valid will validate Swedish social security numbers.
func Valid(str interface{}) bool {
if reflect.TypeOf(str).Kind() != reflect.Int && reflect.TypeOf(str).Kind() != reflect.String {
return false
}
pr := ""
if reflect.TypeOf(str).Kind() == reflect.Int {
pr = strconv.Itoa(str.(int))
} else {
pr = str.(string)
}
re, _ := regexp.Compile(`^(\d{2}){0,1}(\d{2})(\d{2})(\d{2})([\-|\+]{0,1})?(\d{3})(\d{0,1})$`)
match := re.FindStringSubmatch(pr)
if len(match) == 0 {
return false
}
century := match[1]
year := match[2]
month := match[3]
day := match[4]
num := match[6]
check := match[7]
if len(century) == 0 {
yearNow := time.Now().Year()
years := [...]int{yearNow, yearNow - 100, yearNow - 150}
for _, yi := range years {
ys := strconv.Itoa(yi)
if Valid(ys[:2] + pr) {
return true
}
}
return false
}
if len(year) == 4 {
year = year[2:]
}
c, _ := strconv.Atoi(check)
valid := luhn(year+month+day+num) == c && len(check) != 0
if valid && testDate(century, year, month, day) {
return valid
}
day = getCoOrdinationDay(day)
return valid && testDate(century, year, month, day)
}