using System; namespace Unosquare.Swan { /// /// 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(Int32 years, Int32 months, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds) { this.Years = years; this.Months = months; this.Days = days; this.Hours = hours; this.Minutes = minutes; this.Seconds = seconds; this.Milliseconds = milliseconds; } /// /// Gets the years. /// /// /// The years. /// public Int32 Years { get; } /// /// Gets the months. /// /// /// The months. /// public Int32 Months { get; } /// /// Gets the days. /// /// /// The days. /// public Int32 Days { get; } /// /// Gets the hours. /// /// /// The hours. /// public Int32 Hours { get; } /// /// Gets the minutes. /// /// /// The minutes. /// public Int32 Minutes { get; } /// /// Gets the seconds. /// /// /// The seconds. /// public Int32 Seconds { get; } /// /// Gets the milliseconds. /// /// /// The milliseconds. /// public Int32 Milliseconds { get; } internal static DateTimeSpan CompareDates(DateTime date1, DateTime date2) { if(date2 < date1) { DateTime sub = date1; date1 = date2; date2 = sub; } DateTime current = date1; Int32 years = 0; Int32 months = 0; Int32 days = 0; Phase phase = Phase.Years; DateTimeSpan span = new DateTimeSpan(); Int32 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); TimeSpan 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, } } }