using System; namespace Swan { /// <summary> /// 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. /// </summary> public struct DateTimeSpan { /// <summary> /// Initializes a new instance of the <see cref="DateTimeSpan"/> struct. /// </summary> /// <param name="years">The years.</param> /// <param name="months">The months.</param> /// <param name="days">The days.</param> /// <param name="hours">The hours.</param> /// <param name="minutes">The minutes.</param> /// <param name="seconds">The seconds.</param> /// <param name="milliseconds">The milliseconds.</param> 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; } /// <summary> /// Gets the years. /// </summary> /// <value> /// The years. /// </value> public Int32 Years { get; } /// <summary> /// Gets the months. /// </summary> /// <value> /// The months. /// </value> public Int32 Months { get; } /// <summary> /// Gets the days. /// </summary> /// <value> /// The days. /// </value> public Int32 Days { get; } /// <summary> /// Gets the hours. /// </summary> /// <value> /// The hours. /// </value> public Int32 Hours { get; } /// <summary> /// Gets the minutes. /// </summary> /// <value> /// The minutes. /// </value> public Int32 Minutes { get; } /// <summary> /// Gets the seconds. /// </summary> /// <value> /// The seconds. /// </value> public Int32 Seconds { get; } /// <summary> /// Gets the milliseconds. /// </summary> /// <value> /// The milliseconds. /// </value> 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, } } }