comecme
comecme

Reputation: 6386

Calculate date persons becomes a certain age

I'm trying to calculate the date a person turns 18, taking into account leap years.

One might think that just adding 18 years to a date is enough:

birthDay.AddYears(18);

But if the birthday is February 29, 2000, this leads to february 28, 2018. I believe the correct answer would have to be March 1, 2018.

I found a way to do it, but I wonder if there isn't a simpler way.

birthday.AddDays(-1).AddYears(18).AddDays(1);

I would think an answer to this question would already exist on StackOverflow, but all my searches only turn up questions about calculating age on a specific date.

I don't think my question is a duplicate of Behavior of DateTime.AddYears on leap year as that one only explains why AddYears works as it does. It does not contain code to perform the calculation.

I found a quora article stating that the official date you turn 18 is different in New Sealand from the UK.

Upvotes: 1

Views: 274

Answers (1)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186678

I suggest hiding the logic (rounding up to 1 Mar instead of rounding down to 28 Feb) into an extension method:

public static partial class DateTimeExtensions {
  public static DateTime AddYearsUp(this DateTime value, int amount) {
    // Business as usual: neither days are leap days or both days are leap days
    if (value.Month != 2 || value.Day != 29 || DateTime.IsLeapYear(value.Year + amount))
      return value.AddYears(amount);

    // We want 29 Feb to be turned into 1 Mar (not 28 Feb)
    return new DateTime(value.Year + amount, 3, 1, 
                        value.Hour, value.Minute, value.Second, value.Millisecond);
  }
}

Then use the method implemented:

var result = birthDay.AddYearsUp(18); 

Please, notice, that you current logic

birthday.AddDays(-1).AddYears(18).AddDays(1);

is not correct; the counter example is

// 1 Mar 1998
var birthday = new DateTime(1998, 3, 1);

// Expected:  1 Mar 2016
// Actual:   29 Feb 2016
var result = birthday.AddDays(-1).AddYears(18).AddDays(1);

Upvotes: 1

Related Questions