/***************************************************************************************************************** SAS file name: cprnumber.sas File location: __________________________________________________________________________________________________________________ Purpose: To demonstrate how the Danish Sociel Security Number works and how we can extract information from it. Author: Peter Clemmensen Creation Date: 14May2019 This program supports the blog post "The Danish Social Security Number CPR in SAS" on SASnrd.com *****************************************************************************************************************/ /* Gender determination */ data _null_; cpr='2308792308'; if char(cpr, 8) in ('0', '2', '4', '6', '8') then gender='Female'; else if char(cpr, 8) in ('1', '3', '5', '7', '9') then gender='Male'; put gender=; run; /* Birthdate calculation */ data _null_; cpr='2308792308'; day=substr(cpr, 1, 2); mon=substr(cpr, 3, 2); _56=substr(cpr, 5, 2); _7 =substr(cpr, 7, 1); array _ {0:9, 0:99} _temporary_ (4*(37*19 21*19 42*19) 1*(37*20 21*19 42*19) 4*(37*20 21*20 42*18) 1*(37*20 21*19 42*19)); cen = _[input(_7, 1.), input(_56, 2.)]; year = input(cats(cen, _56), 4.); birthdate=mdy(input(mon, 2.), input(day, 2.), year); put "The individuals birthdate is " birthdate date9.; run; /* A custom function to calculate birthdate from CPR */ proc fcmp outlib=work.functions.fun; function cprbirthdate(cpr $); day=substr(cpr, 1, 2); mon=substr(cpr, 3, 2); _56=substr(cpr, 5, 2); _7 =substr(cpr, 7, 1); array _ {10, 100} / nosymbols (19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19); cen = _[input(_7, 1.)+1, input(_56, 2.)+1]; year = input(cats(cen, _56), 4.); if prxmatch('/^(((0[1-9]|[12][0-9]|3[01])[-](0[13578]|1[02])|(0[1-9]|[12][0-9]|30)[-](0[469]|11)|(0[1-9]|1\d|2[0-8])[-]02)[-]\d{4}|29[-]02[-](\d{2}(0[48]|[2468][048]|[13579][26])|([02468][048]|[1359][26])00))$/', cats(day, '-', mon, '-', put(year, 4.))) = 0 then call missing(birthdate); else birthdate=mdy(input(mon, 2.), input(day, 2.), year); return (birthdate); endsub; run;quit; /* Use the function in a data step */ data cprnumbers; cpr='2307891556'; output; cpr='2902004165'; output; cpr='0904193498'; output; cpr='0000000000'; output; cpr='2902055165'; output; run; options cmplib=work.functions; data test; set cprnumbers; bd=cprbirthdate(cpr); format bd date9.; run; proc print data=test;run;