Run code if a full year has elasped

I want to send an email to a user every year based on the date on which their account was created.

I currently have code for checking if a number of months have passed since they last logged in and was wondering if it could be modified, the code is shown below:

public static int GetMonthsBetween(DateTime from, DateTime to)
{
    if (from > to) return GetMonthsBetween(to, from);

    var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));

    if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
    {
        return monthDiff - 1;
    }
    else
    {
        return monthDiff;
    }
}

if (GetMonthsBetween(lastLoginDate, currentDate) >= 4)

I only want send the email when a full year has elapsed since the creation date, how do I go about doing this?

Jon Skeet
people
quotationmark

It seems to me that the right approach is to change your design - instead of asking for the months between one date and another, you should add the relevant number of months to your original DateTime. You don't need a helper method for that at all:

if (lastLoginDate.AddMonths(4) >= currentDate)

Or for a year:

if (lastLoginDate.AddYears(1) >= currentDate)

There's no type in .NET representing a "period" of days, months etc - you might want to consider my Noda Time library for that. At that point you could have:

private static readonly Period LoginExpiredPeriod = ...;

...

// Assuming lastLoginDate and currentDate are LocalDate values
if (lastLoginDate + period >= currentDate)
{
    ...
}

You need to be aware of the impact of months and years being variable length though - for example, "Feb 29th 2016 + 1 year" is Feb 28th 2017 in Noda Time... but you may want to use March 1st 2017, for example. Be careful, basically.

people

See more on this question at Stackoverflow