RaspberryIO/Unosquare.Swan.Lite/DateTimeSpan.cs
2019-12-04 17:10:06 +01:00

172 lines
4.1 KiB
C#

using System;
namespace Unosquare.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,
}
}
}