****************************************************************************************************
*                                           PROGRAM OVERVIEW
****************************************************************************************************
*
* PROGRAM: ms_agestrat.sas  
*
* Created (mm/dd/yyyy): 12/19/2014
* Last modified: 05/15/2018
* Version: 1.4
*
*--------------------------------------------------------------------------------------------------
* PURPOSE:
*	This program creates an age group variable consisting of custom, user-specified groupings,        
*   with allowance for any mix of time units.                                        
*   
*  Program inputs:                                                                                   
*	-SAS data file (.SAS7BDAT format) including START and END dates to calculate age    
*    for each observation and a text string defining the age stratifications            
*                                                                                  
*    or                                                                                 
*                                                                                                      
*	-SAS data file (.SAS7BDAT format) including a START date and a constant date        
*    parameter to calculate age for each observation and a text string                  
*    defining the stratifications            
* 
*  Program outputs:                                                                                                                                       
*	-SAS data file (.SAS7BDAT format) containing the age group for each observation 
* 
*  PARAMETERS:                                                                       
*	-INFILE    = Input file containing start date (required)                                            
*	-OUTFILE   = Output file                                                                             
*	-STARTDT   = Start date to measure age                                                              
*	-ENDDT     = End date to measure age                                                                
*	-TIMESTRAT = Age groups for stratification   
* 
*  Programming Notes:                                                                                
*	-The default value for the age stratification text string is                        
*    00-01 02-04 05-09 10-14 15-18 19-21 22-44 45-64 65-74 75+                                                                            
*
*
*--------------------------------------------------------------------------------------------------
* CONTACT INFO: 
*  Sentinel Coordinating Center
*  info@sentinelsystem.org
*
*--------------------------------------------------------------------------------------------------
*  CHANGE LOG: 
*
*   Version   Date       Initials      Comment (reference external documentation when available)
*   -------   --------   --------   ---------------------------------------------------------------
*   1.4		  05/15/18	  AP		Added AgeGroupNum to output dataset for correct AgeGroup sort
*
***************************************************************************************************;

%macro MS_AGESTRAT(INFILE=,OUTFILE=,STARTDT=,ENDDT=,TIMESTRAT=);

%put =====> MACRO CALLED: ms_agestrat v1.4;

  %global NBSTRAT AGETYP MINAGE MAXAGE AGETHRESH; 

  *Converting constant end date to value in numeric if required;
  %if %index(&ENDDT.,/) %then %do; 
    data _null_;
    Call Symputx('ENDDT',put(input("&ENDDT",mmddyy10.),best12.));
    run;
    %put END DATE CONVERTED TO NUMERIC: &ENDDT;
  %end;
 
  *Setting default values for time text string (years);
  %if %str("&TIMESTRAT.")=%str("") %then %do;
    %let TIMESTRAT=00-01 02-04 05-09 10-14 15-18 19-21 22-44 45-64 65-74 75+;
  %end;
  
  *Counting time categories;
  %let NUMARG=0; 
  %do %while(%qscan(&TIMESTRAT,&NUMARG+1,%str( )) ne %str());
    %let NUMARG = %eval(&NUMARG+1);
  %end;
  
  %let NBSTRAT=&NUMARG.;
  
  *Defining each time category;
  data _NULL_;
  format AgeThresh $200. AgeTyp $200.;
  do i=1 to &NBSTRAT.;
    _agetyp=compress(scan("&TIMESTRAT.",i*2-1),'DWMQY','klu');
    _agetyp=TRANWRD(UPCASE(_agetyp),'Y','Years');
    _agetyp=TRANWRD(UPCASE(_agetyp),'D','Days');
    _agetyp=TRANWRD(UPCASE(_agetyp),'W','Weeks');
    _agetyp=TRANWRD(UPCASE(_agetyp),'Q','Quarters');
    _agetyp=TRANWRD(UPCASE(_agetyp),'M','Months');
      
    if _agetyp ne '' then   AgeTyp=strip(AgeTyp)||" "||strip(_Agetyp);
    else AgeTyp=strip(AgeTyp)||' Years';
      
    AgeThresh=strip(AgeThresh)||" "||compress(scan("&TIMESTRAT.",i*2-1),'DWMQY','lu');
    if i=1 then MinAge=input(AgeThresh,best.);
    if i=&NBSTRAT. then do;
      MaxAge=input(compress(scan("&TIMESTRAT.",i*2),'DWMQY','lu'),best.);
      if MaxAge=. then MaxAge=99999;
    end;
    output;
  end;
  call symputx('AGETHRESH',AgeThresh);
  call symputx('AGETYP',AgeTyp);
  call symputx('MINAGE',MinAge);
  call symputx('MAXAGE',MaxAge);
  run;
  
  *Echoing macro variable;
  %put _LOCAL_;
  
  *Assigning age categories;
  data &OUTFILE.(drop=i comparedt);
  length AgeGroupNum 3 MinAgeDt MaxAgeDt 4;
  set &INFILE.;
  format MinAgeDt MaxAgeDt date9. AgeGroup $9.; 
  MinAgeDt = intnx(scan("&AGETYP.",1),&STARTDT.,&MINAGE.,'sameday');
  if &MAXAGE.=99999 then MaxAgeDt=intnx('Years',&STARTDT.,110,'sameday');
  else if mod(year(&STARTDT.),4)= 0 and month(&STARTDT.) = 2 and day(&STARTDT.) = 29 then 
  MaxAgeDt= intnx(scan("&AGETYP.",&NBSTRAT.),&STARTDT.,&MAXAGE.+1,'sameday');
  else MaxAgeDt= intnx(scan("&AGETYP.",&NBSTRAT.),&STARTDT.,&MAXAGE.+1,'sameday')-1; 
  AgeGroup="";

  if MinAgeDt <= &ENDDT. <= MaxAgeDt then do;
    do i=&NBSTRAT. to 1 by -1;   
    if mod(year(&STARTDT.),4)= 0 and month(&STARTDT.) = 2 and day(&STARTDT.) = 29 then  
      comparedt = intnx(scan("&AGETYP.",i),&STARTDT.,input(scan("&AGETHRESH.",i),best.),'sameday')+1;
    else
      comparedt = intnx(scan("&AGETYP.",i),&STARTDT.,input(scan("&AGETHRESH.",i),best.),'sameday');     
      if &ENDDT. >= comparedt then do;
        AgeGroup = scan("&TIMESTRAT.",i,' ');
    AgeGroupNum=i;
        leave;
      end;
    end;        
  end;

  run;

%put NOTE: ******** END OF MACRO: ms_agestrat v1.4 ********;

%mend MS_AGESTRAT;