How to get difference between two dates in Year/Month/Week/Day?

This is actually quite tricky. A different total number of days can result in the same result. For example:

  • 19th June 2008 to 19th June 2010 = 2 years, but also 365 * 2 days

  • 19th June 2006 to 19th June 2008 = 2 years, but also 365 + 366 days due to leap years

You may well want to subtract years until you get to the point where you’ve got two dates which are less than a year apart. Then subtract months until you get to the point where you’ve got two dates which are less than a month apart.

Further confusion: subtracting (or adding) months is tricky when you might start with a date of “30th March” – what’s a month earlier than that?

Even further confusion (may not be relevant): even a day isn’t always 24 hours. Daylight saving anyone?

Even further confusion (almost certainly not relevant): even a minute isn’t always 60 seconds. Leap seconds are highly confusing…

I don’t have the time to work out the exact right way of doing this right now – this answer is mostly to raise the fact that it’s not nearly as simple as it might sound.

EDIT: Unfortunately I’m not going to have enough time to answer this fully. I would suggest you start off by defining a struct representing a Period:

public struct Period
{
    private readonly int days;
    public int Days { get { return days; } }
    private readonly int months;
    public int Months { get { return months; } }
    private readonly int years;
    public int Years { get { return years; } }

    public Period(int years, int months, int days)
    {
        this.years = years;
        this.months = months;
        this.days = days;
    }

    public Period WithDays(int newDays)
    {
        return new Period(years, months, newDays);
    }

    public Period WithMonths(int newMonths)
    {
        return new Period(years, newMonths, days);
    }

    public Period WithYears(int newYears)
    {
        return new Period(newYears, months, days);
    }

    public static DateTime operator +(DateTime date, Period period)
    {
        // TODO: Implement this!
    }

    public static Period Difference(DateTime first, DateTime second)
    {
        // TODO: Implement this!
    }
}

I suggest you implement the + operator first, which should inform the Difference method – you should make sure that first + (Period.Difference(first, second)) == second for all first/second values.

Start with writing a whole slew of unit tests – initially “easy” cases, then move on to tricky ones involving leap years. I know the normal approach is to write one test at a time, but I’d personally brainstorm a bunch of them before you start any implementation work.

Allow yourself a day to implement this properly. It’s tricky stuff.

Note that I’ve omitted weeks here – that value at least is easy, because it’s always 7 days. So given a (positive) period, you’d have:

int years = period.Years;
int months = period.Months;
int weeks = period.Days / 7;
int daysWithinWeek = period.Days % 7;

(I suggest you avoid even thinking about negative periods – make sure everything is positive, all the time.)

Leave a Comment