namespace Unosquare.Swan { using System; /// /// Represents a struct of DateTimeSpan to compare dates and get in /// separate fields the amount of time between those dates. /// /// Based on https://stackoverflow.com/a/9216404/1096693. /// public struct DateTimeSpan { /// /// Initializes a new instance of the struct. /// /// The years. /// The months. /// The days. /// The hours. /// The minutes. /// The seconds. /// The milliseconds. public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds) { Years = years; Months = months; Days = days; Hours = hours; Minutes = minutes; Seconds = seconds; Milliseconds = milliseconds; } /// /// Gets the years. /// /// /// The years. /// public int Years { get; } /// /// Gets the months. /// /// /// The months. /// public int Months { get; } /// /// Gets the days. /// /// /// The days. /// public int Days { get; } /// /// Gets the hours. /// /// /// The hours. /// public int Hours { get; } /// /// Gets the minutes. /// /// /// The minutes. /// public int Minutes { get; } /// /// Gets the seconds. /// /// /// The seconds. /// public int Seconds { get; } /// /// Gets the milliseconds. /// /// /// The milliseconds. /// public int Milliseconds { get; } internal static DateTimeSpan CompareDates(DateTime date1, DateTime date2) { if (date2 < date1) { var sub = date1; date1 = date2; date2 = sub; } var current = date1; var years = 0; var months = 0; var days = 0; var phase = Phase.Years; var span = new DateTimeSpan(); var officialDay = current.Day; while (phase != Phase.Done) { switch (phase) { case Phase.Years: if (current.AddYears(years + 1) > date2) { phase = Phase.Months; current = current.AddYears(years); } else { years++; } break; case Phase.Months: if (current.AddMonths(months + 1) > date2) { phase = Phase.Days; current = current.AddMonths(months); if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month)) current = current.AddDays(officialDay - current.Day); } else { months++; } break; case Phase.Days: if (current.AddDays(days + 1) > date2) { current = current.AddDays(days); var timespan = date2 - current; span = new DateTimeSpan( years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds); phase = Phase.Done; } else { days++; } break; } } return span; } private enum Phase { Years, Months, Days, Done, } } }