Skip to content

Commit

Permalink
Merge pull request #31 from MartinAskestad/is-future-date
Browse files Browse the repository at this point in the history
Is future date
  • Loading branch information
MartinAskestad committed Mar 8, 2023
2 parents 9ce4965 + 028ba3d commit 155fd50
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 33 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Install with npm
var swedenNationalId = require("sweden-national-id");

// National id number
swedenNationalId.parse("850823-6463"); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6463' }
swedenNationalId.parse("850823-6463"); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6463', isFutureDate: false, isUnder18: false }

// Co-ordination number
swedenNationalId.parse("850863-6464"); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6460' }
swedenNationalId.parse("850863-6464"); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6460', isFutureDate: false, isUnder18: false }

// Corporate id number
swedenNationalId.parse("556036-0793"); // { nationalIdNumber: "556036-0793", numberType: 5 }
Expand All @@ -38,16 +38,16 @@ swedenNationalId.parse("850823-6464"); // null
const { parse } from 'sweden-national-id';

// National id number
parse('850823-6463'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6463' }
parse('850823-6463'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6463', isFutureDate: false, isUnder18: false }

// Co-ordination number
parse('850863-6464'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850863-6460' }
parse('850863-6464'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850863-6460', isFutureDate: false, isUnder18: false }

// Person over 100 years
parse('850863+6464'); // { dateOfBirth: 1885-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823+6460' }
parse('850863+6464'); // { dateOfBirth: 1885-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823+6460', isFutureDate: false, isUnder18: false }

// 12-digit format of id number
parse('198508636460'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6460' }
parse('198508636460'); // { dateOfBirth: 1985-08-23T00:00:00.000Z, gender: 0, nationalIdNumber: '850823-6460', isFutureDate: false, isUnder18: false }

// Corporate id number
parse('556036-0793'); // { nationalIdNumber: "556036-0793", numberType: 5 }
Expand Down
27 changes: 20 additions & 7 deletions src/national-id-number.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import test from "ava";
import {
CorporateIdNumberType,
Gender,
NationalIdNumber,
parse,
PersonalNumberType
CorporateIdNumberType,
Gender,
NationalIdNumber,
parse,
PersonalNumberType,
} from "./national-id-number";
import { parseDateOfBirth } from "./parse-date-of-birth";

Expand All @@ -20,6 +20,8 @@ test("should parse a valid 10-digit national id number", (t) => {
dateOfBirth: new Date("1985-08-23 00:00:00"),
gender: Gender.F,
nationalIdNumber: "850823-6463",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.personalNumber,
};

Expand All @@ -32,6 +34,8 @@ test("should parse a valid 11-digit national id number of someone older than 100
dateOfBirth: parseDateOfBirth("18850823"),
gender: Gender.F,
nationalIdNumber: "850823+6463",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.personalNumber,
};
t.deepEqual(res, expected);
Expand All @@ -42,6 +46,8 @@ test("should parse a valid 11-digit national id number", (t) => {
dateOfBirth: new Date("1985-08-23 00:00:00"),
gender: Gender.F,
nationalIdNumber: "850823-6463",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.personalNumber,
};
t.deepEqual(parse("850823-6463"), expected);
Expand All @@ -52,6 +58,8 @@ test("should parse a valid national 12-digit id number", (t) => {
dateOfBirth: new Date("1985-08-23 00:00:00"),
gender: Gender.F,
nationalIdNumber: "850823-6463",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.personalNumber,
};
t.deepEqual(parse("198508236463"), expected);
Expand All @@ -62,6 +70,8 @@ test("should parse a valid co-ordination number", (t) => {
dateOfBirth: new Date("1985-08-23 00:00:00"),
gender: Gender.F,
nationalIdNumber: "850883-6460",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.coOrdinationNumber,
};
t.deepEqual(parse("850883-6460"), expected);
Expand All @@ -72,6 +82,8 @@ test("should identify the gender of a national id number as Female", (t) => {
dateOfBirth: new Date("1985-08-23 00:00:00"),
gender: Gender.F,
nationalIdNumber: "850883-6460",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.coOrdinationNumber,
};
t.deepEqual(parse("850883-6460"), expected);
Expand All @@ -82,6 +94,8 @@ test("should identify the gender of a national id number as Male", (t) => {
dateOfBirth: new Date("1979-11-14 00:00:00"),
gender: Gender.M,
nationalIdNumber: "791114-2011",
isFutureDate: false,
isUnder18: false,
numberType: PersonalNumberType.personalNumber,
};
t.deepEqual(parse("791114-2011"), expected);
Expand Down Expand Up @@ -110,7 +124,7 @@ test("should identify a corporate id number", (t) => {
t.deepEqual(parse("556036-0793"), expected);
});

test("should identify a number as a \"council\" number", (t) => {
test('should identify a number as a "council" number', (t) => {
const expected: NationalIdNumber = {
nationalIdNumber: "212000-0142",
numberType: CorporateIdNumberType.council,
Expand All @@ -125,4 +139,3 @@ test("should identify a corporate id number with a leading 16", (t) => {
};
t.deepEqual(parse("165560360793"), expected);
});

51 changes: 36 additions & 15 deletions src/national-id-number.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { format } from "./format";
import { validate } from "./luhn";
import { parseDateOfBirth } from "./parse-date-of-birth";
import {
isFutureDate as _isFutureDate,
isUnder18 as _isUnder18,
parseDateOfBirth,
} from "./parse-date-of-birth";
import { toFourDigitYear } from "./to-four-digit-year";

/**
* Represents the legal gender of the personal-id-number.
*/
export enum Gender {
F,
M
M,
}

/**
* Represents the type of company of a company-id number.
*/
export enum CorporateIdNumberType {
export const enum CorporateIdNumberType {
/**
* An estate of a deceased person. In Swedish, dödsbo.
*/
Expand Down Expand Up @@ -46,36 +50,49 @@ export enum CorporateIdNumberType {
/**
* A trading partnership.
*/
tradingPartnership = 9 // Handelsbolag, kommanditbolag, enkelt bolag
tradingPartnership = 9, // Handelsbolag, kommanditbolag, enkelt bolag
}

/**
* The type of id number.
*/
export enum PersonalNumberType {
export const enum PersonalNumberType {
/**
* The national id number of a private individual.
*/
personalNumber = 10,
/**
* The id number of a corporation of council.
*/
coOrdinationNumber
coOrdinationNumber,
}

/**
* The details of the number that has been parsed.
/*
* Details of a personal id number.
*/
export interface NationalIdNumber {
export type PersonalIdNumber = {
/** The date of birth of a person if number is a personal or co-ordination number otherwise undefined. */
dateOfBirth?: Date;
/** The gender of the person if the number is a personal or co-ordination number otherwise undefined. */
gender?: Gender;
/** The number formatted according to official formating rules. */
nationalIdNumber: string;
/** The type of number, a personal co-ordination or corporate id number. */
numberType: PersonalNumberType | CorporateIdNumberType;
}
isFutureDate: boolean;
isUnder18: boolean;
numberType: PersonalNumberType;
};

/**
* Details of a corporate id number.
*/
export type CorporateIdNumber = {
nationalIdNumber: string;
numberType: CorporateIdNumberType;
};
/**
* The details of the number that has been parsed.
*/
export type NationalIdNumber = PersonalIdNumber | CorporateIdNumber;

/**
* Parses a string representing a Swedish National Id number and returns details about it.
Expand All @@ -99,11 +116,11 @@ export function parse(value: string): NationalIdNumber | null {
if (+nationalIdNumber.substr(2, 2) >= 20) {
return {
nationalIdNumber: nationalIdNumber.replace("+", "-"),
numberType: +nationalIdNumber[0]
numberType: +nationalIdNumber[0],
};
}

if (isNaN((dateOfBirth as unknown) as number)) {
if (isNaN(dateOfBirth as unknown as number)) {
return null;
}
if (hasPlus) {
Expand All @@ -114,10 +131,14 @@ export function parse(value: string): NationalIdNumber | null {
+nationalIdNumber.substr(4, 2) > 60
? PersonalNumberType.coOrdinationNumber
: PersonalNumberType.personalNumber;
const isFutureDate = _isFutureDate(dateOfBirth);
const isUnder18 = _isUnder18(dateOfBirth);
return {
dateOfBirth,
gender,
nationalIdNumber,
numberType
numberType,
isFutureDate,
isUnder18,
};
}
24 changes: 21 additions & 3 deletions src/parse-date-of-birth.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import test from "ava";
import { parseDateOfBirth } from "./parse-date-of-birth";
import {
isFutureDate,
isUnder18,
parseDateOfBirth,
} from "./parse-date-of-birth";

test("should parse the date of birth from a personal number", (t) => {
t.deepEqual(parseDateOfBirth("19850823"), new Date("1985-08-23 00:00:00"));
Expand All @@ -9,6 +13,20 @@ test("should parse the date of birth from a co-ordination number", (t) => {
t.deepEqual(parseDateOfBirth("19850883"), new Date("1985-08-23 00:00:00"));
});

test("should parse the date of birth from someone older than 100 years", t => {
t.deepEqual(parseDateOfBirth("18850823"), new Date("1885-08-23 00:00:00"))
test("should parse the date of birth from someone older than 100 years", (t) => {
t.deepEqual(parseDateOfBirth("18850823"), new Date("1885-08-23 00:00:00"));
});

test("should return true if date of birth is in the future", (t) => {
const dateOfBirth = new Date();
const today = new Date();
dateOfBirth.setFullYear(today.getFullYear() + 1);
t.true(isFutureDate(dateOfBirth));
});

test("should return true if date of birth is more recent that 18 years", (t) => {
const today = new Date();
const dateOfBirth = new Date();
dateOfBirth.setFullYear(today.getFullYear() - 12);
t.true(isUnder18(dateOfBirth));
});
22 changes: 20 additions & 2 deletions src/parse-date-of-birth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@ export function parseDateOfBirth(dateOfBirth: string): Date {
const year = +dateOfBirth.substr(0, 4);
const month = dateOfBirth.substr(4, 2);
let day = +dateOfBirth.substr(6, 2);

if (day >= 32) {
day -= 60;
}
const retval = new Date(`${year}-${month}-${padWithLeadingZero(day)} 00:0.000Z`);
const retval = new Date(
`${year}-${month}-${padWithLeadingZero(day)} 00:0.000Z`
);
retval.setHours(0);
retval.setMinutes(0);
retval.setSeconds(0);
return retval;
}

export function isFutureDate(dateOfBirth: Date): boolean {
const today = new Date();
return today < dateOfBirth;
}

export function isUnder18(dateOfBirth: Date): boolean {
const today = new Date();
let years = today.getFullYear() - dateOfBirth.getFullYear();
if (
today.getMonth() < dateOfBirth.getMonth() ||
(today.getMonth() == dateOfBirth.getMonth() &&
today.getDate() < dateOfBirth.getDate())
) {
years--;
}
return years < 18;
}

0 comments on commit 155fd50

Please sign in to comment.