We can take our computation of the interval between two moments in time and combine it with the trick we developed for using the powers of mathematics to simplify multi-level comparisons to reduce the amount of work we impose upon the time/date engine.
static void PrintAge(DateTime bday, DateTime asof) { // Accumulate years without going over. int years = asof.Year - bday.Year; if (asof.Month*32 + asof.Day < bday.Month*32 + bday.Day) years--; DateTime t = bday.AddYears(years); // Accumulate months without going over. int months = asof.Month - bday.Month; if (asof.Day < bday.Day) months--; months = (months + 12) % 12; t = t.AddMonths(months); // Days are constant-length, woo-hoo! int days = (asof - t).Days; SC.WriteLine("{0} years, {1} months, {2} days", years, months, days); }
Observe that we avoided a call to the AddYears
method
(which is presumably rather complicated because years are variable-length)
by replacing it with a multi-level comparison
to determine whether the ending month/day falls later in the year than
the starting month/day. Since no month has 32 days, a multiplier of
32 is enough to avoid an overflow of the day into the month field
of the comparison key.
0 comments