diff --git a/src/bg/egn.spec.ts b/src/bg/egn.spec.ts index 75c1bcab..215ecc8f 100644 --- a/src/bg/egn.spec.ts +++ b/src/bg/egn.spec.ts @@ -1,5 +1,9 @@ import { validate, format } from './egn'; -import { InvalidLength, InvalidChecksum } from '../exceptions'; +import { + InvalidLength, + InvalidChecksum, + InvalidComponent, +} from '../exceptions'; describe('bg/egn', () => { it('format:752316 926 3', () => { @@ -25,4 +29,19 @@ describe('bg/egn', () => { expect(result.error).toBeInstanceOf(InvalidChecksum); }); + + // The first six digits are a birth date whose month encodes the century + // (41-52 -> 2000s, 21-32 -> 1800s); an impossible date must be rejected even + // when the check digit is correct. + it('validate:2992070971 (impossible month, valid check digit)', () => { + const result = validate('2992070971'); + + expect(result.error).toBeInstanceOf(InvalidComponent); + }); + + it('validate:8019010008 (impossible month)', () => { + const result = validate('8019010008'); + + expect(result.error).toBeInstanceOf(InvalidComponent); + }); }); diff --git a/src/bg/egn.ts b/src/bg/egn.ts index 37ee996d..0777f3ea 100644 --- a/src/bg/egn.ts +++ b/src/bg/egn.ts @@ -10,7 +10,7 @@ */ import * as exceptions from '../exceptions'; -import { strings } from '../util'; +import { isValidDate, strings } from '../util'; import { Validator, ValidateReturn } from '../types'; import { weightedSum } from '../util/checksum'; @@ -51,6 +51,24 @@ const impl: Validator = { return { isValid: false, error: new exceptions.InvalidFormat() }; } + // The first six digits are the birth date. The month encodes the century: + // 41-52 -> 2000s, 21-32 -> 1800s, 01-12 -> 1900s. + const [yy, mm, dd] = strings.splitAt(value, 2, 4, 6); + let year = parseInt(yy, 10); + let month = parseInt(mm, 10); + if (month > 40) { + year += 2000; + month -= 40; + } else if (month > 20) { + year += 1800; + month -= 20; + } else { + year += 1900; + } + if (!isValidDate(String(year), String(month), dd)) { + return { isValid: false, error: new exceptions.InvalidComponent() }; + } + const [front, check] = strings.splitAt(value, -1); const sum = weightedSum(front, {