Difference between dates in Months and Days I've written a function that returns how many Months and Days are between two dates. I want to respect calendar month boundaries, but I'm ignoring time as it's not relevant for my needs.

I've got the following, but I feel like I'm missing thing I can do to optimize it/refactor it. So I'm looking for additional eyes to help me review this.

//As opposed to TimeSpan ^_^
public readonly struct CalendarSpan 
{
    public CalendarSpan(int months, int days)
    {
        Months = months;
        Days = days;
    }
    public readonly int Months;
    public readonly int Days;
}

public static CalendarSpan DifferenceInMonthsAndDays(DateTime startDate, DateTime endDate)
{
    //Ensuring that the larger of two dates is the latter argument 
    if (startDate &gt; endDate)
        return DifferenceInMonthsAndDays(endDate, startDate);

    //Start with getting the difference in months
    var months = 12 * (endDate.Year - startDate.Year) + endDate.Month - startDate.Month;

    int days;
    //Add the difference in months to the smaller of the two dates
    var addedMonths = startDate.AddMonths(months);
    if (addedMonths &lt;= endDate)
        //So long as we can avoid negative numbers, just do the simple math
        days = endDate.Day - addedMonths.Day;
    else
    {
        //Otherwise, backoff by 1 months, and use the built in Subtract logic to get the number of days between the two dates
        months--;
        addedMonths = startDate.AddMonths(months);
        days = endDate.Subtract(addedMonths).Days;
    }

    return new CalendarSpan(months, days);
}


UPDATE
I have been trying to get unit tests for this, and I honestly don't know why I ever attempted this. It is NOT an easy or straight forward thing to do at all.
Insert obligatory meme of Homer disappearing into the hedges
Last answer deleted (instead of substantially revising).

Notes (see comments in code)


CalendarSpan signed (date1 > date2 => negative span)
Extension overload of DateTime.Add() taking CalendarSpan argument
Unit test approach (see Main() which iterates positive and negative differences, using DateTime functions to check integrity of results)  


`

using System;

namespace DateDiff
{
  static class Program
  {
    public readonly struct CalendarSpan 
    {
      public CalendarSpan(int months, int days)
      {
        Months = months;
        Days = days;
      }
      public readonly int Months;
      public readonly int Days;
    }

    //  Maintains sign-consistency, i.e. if l &gt; r returned value components are positive and if l &lt; r negative
    public static CalendarSpan MonthDaysDifference(this DateTime l, DateTime r)
    {
      var mDiff = l.Month - r.Month + 12 * (l.Year - r.Year);

      var dDiff = (l - r.AddMonths(mDiff)).Days;
      if (dDiff == 0 //  no day, the span is a whole number of months
          || l &gt; r &amp;&amp; dDiff &gt; 0 //  day and month differences ...
          || l &lt; r &amp;&amp; dDiff &lt; 0) //  ... have the same sign
        return new CalendarSpan(mDiff, dDiff);
      //  Signs differ
      var dSign = Math.Sign(dDiff);
      var mSign = Math.Sign(mDiff);
      //  It doesn't matter which sign is which, we adjust months in the correct direction
      mDiff += dSign;
      //  and recalculate days
      return new CalendarSpan(mDiff, (l - r.AddMonths(mDiff)).Days);
    }

    public static DateTime Add(this DateTime dt, CalendarSpan span)
    {
      return dt.AddMonths(span.Months).AddDays(span.Days);
    }

    //  Included to suggest how to test
    static void Main(string[] args)
    {
      for (int i = 0; i &lt; 1000; i++)
      {
        var date1 = new DateTime(2017, 12, 25).AddDays(i);
        for (int j = 0; j &lt; 1000; j++)
        {
          var date2 = new DateTime(2019, 01, 01).AddDays(j);
          var dateDiff = date1.MonthDaysDifference(date2);
          //var dateDiff2 = MonthDaysDifference(date1,date2);//just checking
          if (date2.Add(dateDiff) != date1)
          {
            Console.WriteLine($"ERROR: {date1:yyyy-MM-dd} - {date2:yyyy-MM-dd} = {dateDiff.Months} months + {dateDiff.Days} days");
            Console.WriteLine("Any key to exit");
            Console.ReadKey();
            return;
          }
          Console.WriteLine($"{date1:yyyy-MM-dd} - {date2:yyyy-MM-dd} = {dateDiff.Months} months + {dateDiff.Days} days");
        }
      }
    }
  }
}