*! name change from todate 8 Sept 2005 *! 1.2.1 NJC 29 July 2003 * 1.2.0 NJC 4 July 2001 * 1.1.0 NJC 7 June 2001 program define todate7 version 7.0 syntax varlist [if] [in], Pattern(string) Generate(string) /* */ [ Format(string) Cend(numlist int >200 <=10000 max=1) ] * existing and new varlists tokenize `varlist' local nvars : word count `varlist' * do before second -syntax- marksample touse, novarlist local 0 "`generate'" syntax newvarlist local ngen : word count `varlist' if "`nvars'" != "`ngen'" { di as err "number of new variables not equal to" _c di as err " number of existing variables" exit 198 } * partial test of format if "`format'" != "" { capture display `format' 1 if _rc { di as err "invalid format()" exit 120 } } * parse pattern into m d y h q w elements * indulge upper case local pattern = lower("`pattern'") local plength = length("`pattern'") forval i = 1 / `plength' { local p = substr("`pattern'",`i',1) if "`p'" == "m" { local mlist "`mlist' `i'" } else if "`p'" == "d" { local dlist "`dlist' `i'" } else if "`p'" == "y" { local ylist "`ylist' `i'" } else if "`p'" == "h" { local hlist "`hlist' `i'" } else if "`p'" == "q" { local qlist "`qlist' `i'" } else if "`p'" == "w" { local wlist "`wlist' `i'" } else { di as err "invalid pattern" exit 198 } } * allow mdy yh yq ym yw permutations foreach i in m d y h q w { if "``i'list'" != "" { local ptype "`ptype'`i'" local pels "`pels' `i'" } } local badtype 1 foreach i in yh yq my yw mdy { if "`ptype'" == "`i'" { local badtype 0 } } if `badtype' { di as err "invalid pattern type: `ptype'" exit 198 } if "`ptype'" == "my" { local ptype "ym" } * contiguous digits will have range == # elements - 1 foreach i in `pels' { local `i'1 : word 1 of ``i'list' local `i'len : word count ``i'list' local last : word ``i'len' of ``i'list' local range = `last' - ``i'1' local range2 = ``i'len' - 1 if `range' != `range2' { di as err "`i' digits not contiguous in pattern" exit 198 } } * year digits and cend() compatible? if `ylen' != 4 & "`cend'" == "" { di as err "`ylen' digit years: need cend() option?" exit 198 } else if `ylen' == 4 & "`cend'" != "" { di as txt "4 digit years: cend() option ignored" local cend } * for each variable in original varlist qui forval i = 1 / `nvars' { tempvar strdate datelen touse2 * markout separately for each variable gen byte `touse2' = `touse' markout `touse2' ``i'', strok * working string variable copy of date variable gen str1 `strdate' = "" capture confirm string variable ``i'' if _rc { replace `strdate' = string(``i'',"%12.0g") if `touse2' } else replace `strdate' = trim(``i'') if `touse2' local v "``i''" local `i' "`strdate'" * how long is date variable? gen `datelen' = length(``i'') su `datelen' if `touse2', meanonly local range = r(max) - r(min) local min = r(min) local max = r(max) if `max' != `plength' { noi di as res "`v': " /* */ as txt "length does not match pattern" continue } * range == 0 is no problem if `range' == 1 { /* leading zero needs to be supplied? */ replace `strdate' = "0" + `strdate' /* */ if `datelen' == `min' & `touse2' } else if `range' >= 2 { /* range of lengths >= 2 => skip this */ noi di as res "`v': " /* */ as txt "length too variable to handle" continue } * construct month, day, year, half, quarter, week as needed foreach j in `pels' { tempvar `j' gen ``j'' = real(substr(``i'',``j'1',``j'len')) } if "`cend'" != "" { local c1 = int(`cend' / 100) local c2 = mod(`cend',100) replace `y' = /* */ `y' + 100 * cond(`y' <= `c2', `c1', `c1' - 1) } * generate new variable local newvar : word `i' of `varlist' if "`ptype'" == "mdy" { gen `newvar' = mdy(`m',`d',`y') if `touse2' } else { local o = substr("`ptype'",2,1) gen `newvar' = y`o'(`y',``o'') if `touse2' } if "`format'" != "" { format `format' `newvar' } drop `touse2' } end