******************************************************************************** *** Convert Gregorian to Ethiopian dates ******************************************************************************** program define to_ethiopian version 10.0 syntax varlist(min=1 max=1) [if] [in] [, eth_year(string) eth_month(string) eth_day(string)] // Date variables are numberic confirm numeric variable `varlist' marksample touse local fmt : format `varlist' local fmt = lower("`fmt'") // Obtain number of days since January 01, 1960 tempvar temp_numeric_var_touse if "`fmt'" == "%td" { gen double `temp_numeric_var_touse' = `varlist' if `touse' } else if "`fmt'" == "%tc" { gen double `temp_numeric_var_touse' = dofc(`varlist') if `touse' } else { display as error "Date variable must be valid STATA date variable formatted as %td, %tc or %tC." exit 198 } // Default variable names if not provided if "`eth_year'" == "" { local eth_year "eth_year" } if "`eth_month'" == "" { local eth_month "eth_month" } if "`eth_day'" == "" { local eth_day "eth_day" } // Validate new variable names capture confirm new variable `eth_year' if _rc { display as error "Option eth_year(): `eth_year' is not a valid new variable name or already exists." exit 198 } capture confirm new variable `eth_month' if _rc { display as error "Option eth_month(): `eth_month' is not a valid new variable name or already exists." exit 198 } capture confirm new variable `eth_day' if _rc { display as error "Option eth_day(): `eth_day' is not a valid new variable name or already exists." exit 198 } // New variables placeholders quietly { gen double `eth_year' = . gen double `eth_month' = . gen double `eth_day' = . } // Call mata to perform conversion mata: ethdate_compute("`temp_numeric_var_touse'", "`touse'", "`eth_year'", "`eth_month'", "`eth_day'") end ******************************************************************************** *** MATA function to convert Gregorian to Ethiopian dates ******************************************************************************** mata: void ethdate_compute(string scalar datevar, string scalar touse, string scalar ethyear, string scalar ethmonth, string scalar ethday) { real colvector days, years, months real scalar i, n // Read input data days = st_data(., datevar, touse) n = rows(days) // Initialize output vectors : Starting year (Tahsas 22, 1952) = January 01, 1960 years = J(n, 1, 1952) months = J(n, 1, 4) days = days :+ 22 // Main computation loop for (i = 1; i <= n; i++) { if (days[i] != .) { // Skip missing values while (days[i] > 30 | days[i] <= 0) { // Determine if current year is a leap year real scalar is_leap, year_days, pagume_days is_leap = mod(years[i], 4) == 3 year_days = is_leap ? 366 : 365 if (days[i] > year_days) { days[i] = days[i] - year_days years[i] = years[i] + 1 } else if (days[i] <= 0) { years[i] = years[i] - 1 is_leap = mod(years[i], 4) == 3 year_days = is_leap ? 366 : 365 days[i] = days[i] + year_days } else { days[i] = days[i] - 30 months[i] = months[i] + 1 if (months[i] == 13) { is_leap = mod(years[i], 4) == 3 pagume_days = is_leap ? 6 : 5 if (days[i] > pagume_days) { days[i] = days[i] - pagume_days months[i] = 1 years[i] = years[i] + 1 } } } } } } // Write results back to Stata st_store(., ethyear, touse, years) st_store(., ethmonth, touse, months) st_store(., ethday, touse, days) } end