Skip to content

Commit 6512ffb

Browse files
committed
finito
1 parent 2fdcb32 commit 6512ffb

File tree

2 files changed

+38
-27
lines changed

2 files changed

+38
-27
lines changed

packages/validation/src/se.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ export function validateNationalIdentityNumber(
117117
return false;
118118
}
119119

120-
const [_, century, year, month, day, separator, rest] = match;
120+
const [_, centuryStr, yearStr, monthStr, dayStr, separator, rest] = match;
121121

122-
if (century && options.format === 'short') {
122+
if (centuryStr && options.format === 'short') {
123123
return false;
124124
}
125125

@@ -128,38 +128,49 @@ export function validateNationalIdentityNumber(
128128
}
129129

130130
// when verifying the value, we must always use the short format, discaring the century
131-
// if included it would generate a different checksum
132-
const isValid = mod10(`${year}${month}${day}${rest}`);
131+
// if we include the century it would generate a different checksum
132+
const isValid = mod10(`${yearStr}${monthStr}${dayStr}${rest}`);
133133
if (!isValid) {
134134
return false;
135135
}
136136

137-
// // this allows us to handle both YYYYMMDD and YYMMDD when extracting the date
138-
// const offset = isLongFormat ? 2 : 0;
139-
// // copy/inspiration from NAV https://github.com/navikt/fnrvalidator/blob/77e57f0bc8e3570ddc2f0a94558c58d0f7259fe0/src/validator.ts#L108
140-
// let year = Number(value.substring(0, 2 + offset));
141-
// const month = Number(value.substring(2 + offset, 4 + offset));
142-
// let day = Number(value.substring(4 + offset, 6 + offset));
143-
//
144-
145-
const month2 = Number(month);
146-
let day2 = Number(day);
147-
let year2 = Number(century ? century + year : year);
148-
// for a samordningsnummer the day is increased by 60. Eg the 31st of a month would be 91, or the 3rd would be 63.
149-
// thus we need to subtract 60 to get the correct day of the month
150-
if (day2 > 60) {
151-
day2 = day2 - 60;
137+
let year = 0;
138+
switch (true) {
139+
// if we have the long format version, we already have the full year
140+
case centuryStr:
141+
year = Number(centuryStr + yearStr);
142+
break;
143+
// otherwise, we can use the separator to determine the century of the personnummer
144+
// if the separator is '+', the person is over a 100 years old
145+
// we can then get
146+
case separator: {
147+
const date = new Date();
148+
const baseYear =
149+
separator === '+' ? date.getUTCFullYear() - 100 : date.getUTCFullYear();
150+
year = baseYear - ((baseYear - yearStr) % 100);
151+
break;
152+
}
153+
// if it's the short format, without a separator, we need to special handle the year for the date validation.
154+
// 1900 isn't a leap year, but 2000 is. Since JS two digits years to the Date constructor is an offset from the year 1900
155+
// we need to special handle that case. For other cases it doesn't really matter if the year is 1925 or 2025.
156+
case yearStr === '00':
157+
year = 2000;
158+
break;
159+
// short version without separator
160+
default:
161+
year = Number(yearStr);
152162
}
153163

154-
// 1900 isn't a leap year, but 2000 is. Since JS two digits years to the Date constructor is an offset from the year 1900
155-
// we need to special handle that case. For other cases it doesn't really matter if the year is 1925 or 2025.
156-
if (!separator && !century && year === '00') {
157-
year2 = 2000;
158-
} else if (century) {
159-
year2 = Number(century + year);
164+
const month = Number(monthStr);
165+
166+
let day = Number(dayStr);
167+
// for a samordningsnummer the day is increased by 60. Eg the 31st of a month would be 91, or the 3rd would be 63.
168+
// thus we need to subtract 60 to get the correct day of the month
169+
if (day > 60) {
170+
day = day - 60;
160171
}
161172

162-
return isValidDate(year2, month2, day2);
173+
return isValidDate(year, month, day);
163174
}
164175

165176
// just reexport the no method for API feature parity

packages/validation/src/validation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ describe('se', () => {
223223
}
224224
});
225225

226-
test('validateNationalIdentityNumber() - handles leap years', () => {
226+
test.only('validateNationalIdentityNumber() - handles leap years', () => {
227227
expect(se.validateNationalIdentityNumber('0002297422')).toBe(true);
228228
});
229229
});

0 commit comments

Comments
 (0)