*! 1.2.1 NJC 16 January 2013
*! 1.2.0 NJC 22 October 2012
* 1.1.1 NJC 21 October 2012
* 1.1.0 NJC 20 October 2012
* 1.0.0 NJC 20 October 2012
program personage
	version 8.2
	syntax varlist(numeric min=1 max=2) [if] [in] , Generate(str) [ currdate(str)]

	marksample touse
	qui count if `touse'
	if r(N) == 0 error 2000

	tokenize `varlist'
	args bdate cdate

	foreach v in `bdate' `cdate' {
		local fmt : format `v'
		if substr("`fmt'", 1, 2) != "%d" {
			if substr("`fmt'", 1, 3) != "%td" {
				di "warning: `v' not formatted as daily date"
			}
		}
	}

	if "`currdate'" != "" & "`cdate'" != "" {
		di as err "two date variables supplied and also currdate() option"
		exit 498
	}

	if "`cdate'" == "" {
		if "`currdate'" == "" {
			di as err "only one date variable supplied, and no currdate() option"
			exit 498
		}
		tempvar cdate
		gen `cdate' = `currdate'
	}

	tokenize `generate'
	args yearsvar daysvar loyvar garbage
	if "`garbage'" != "" {
		di as err "at most three names should be given in generate()"
		exit 198
	}
	if "`loyvar'" != "" {
		confirm new variable `loyvar'
	}
	if "`daysvar'" != "" {
		confirm new variable `daysvar'
	}
	confirm new variable `yearsvar'

	tempvar work
	local bday_this_cal_yr ///
	(month(`bdate') < month(`cdate')) | (month(`bdate') == month(`cdate') & day(`bdate') <= day(`cdate'))

*quietly {
		// first focus on calculating last birthday

		// 1. last b'day earlier this year if current date is as late or later in year
		gen `work' = mdy(month(`bdate'), day(`bdate'), year(`cdate')) if `bday_this_cal_yr'

		// 2. else it was last year
		replace `work' = mdy(month(`bdate'), day(`bdate'), year(`cdate') - 1) if missing(`work')

		// but 1. won't work if born Feb 29 and it's not a leap year
		//     2. won't work if born Feb 29 and last year not a leap year
		local born_feb29 month(`bdate') == 2 & day(`bdate') == 29
		local this_not_leap missing(mdy(2, 29, year(`cdate')))
		local last_not_leap missing(mdy(2, 29, year(`cdate') - 1))

		// 3. is a fix for problem with 1.
		replace `work' = mdy(2, 28, year(`cdate')) ///
		if `this_not_leap' & `born_feb29' & `cdate' >= mdy(2, 28, year(`cdate'))
		// 4. is a fix for problem with 2.
		replace `work' = mdy(2, 28, year(`cdate') - 1) ///
		if `last_not_leap' & `born_feb29' & `cdate' <= mdy(2, 28, year(`cdate'))
*	}

	// now we can calculate results
	// traditional that messages about missing values are displayed

	gen `yearsvar' = year(`work') - year(`bdate') if `touse'
	if "`daysvar'" != "" {
		gen `daysvar' = `cdate' - `work' if `touse'
	}
	if "`loyvar'" != "" {
		quietly {
			tempvar work2
			gen `work2' = mdy(month(`bdate'), day(`bdate'), year(`work') + 1)
			replace `work2' = mdy(2, 28, year(`work') + 1) if missing(`work')
		}
		gen `loyvar' = `work2' - `work' if `touse'
	}

	quietly compress `yearsvar' `daysvar' `loyvar'
end