using System;
using Xunit;
namespace Fadd
{
/// <summary>
/// Calculates the number of months and days between two dates (and add the overlapping days).
/// </summary>
public struct MonthSpan
{
private int _days;
private int _months;
/// <summary>
/// Number of months
/// </summary>
public int Months
{
get { return _months; }
set { _months = value; }
}
/// <summary>
/// Number of days
/// </summary>
public int Days
{
get { return _days; }
set { _days = value; }
}
/// <summary>
/// Creates a monthspan between two dates
/// </summary>
/// <param name="from">from which date to calculate.</param>
/// <param name="to">end date.</param>
/// <returns>Number of months and days between the two dates.</returns>
public static MonthSpan Create(DateTime from, DateTime to)
{
int month = from.Month, year = from.Year;
MonthSpan span = new MonthSpan();
if (from.Day != 1)
{
// same month
if (to.Month == from.Month && to.Year == from.Year)
{
TimeSpan tspan = to - from;
span.Days = tspan.Days;
return span;
}
span.Days = DateTime.DaysInMonth(from.Year, from.Month) - from.Day;
++month;
if (month == 13)
{
month = 1;
++year;
}
}
while (year < to.Year || (year == to.Year && month < to.Month))
{
++month;
if (month == 12)
{
++year;
month = 1;
}
++span.Months;
}
if (to.Day != DateTime.DaysInMonth(to.Year, to.Month))
span.Days += to.Day;
else if (year == to.Year && month == to.Month)
span.Months += 1;
return span;
}
#if DEBUG
[Fact]
private static void TestOneMonth()
{
DateTime from = new DateTime(2008, 1, 1);
DateTime to = new DateTime(2008, 1, 31);
MonthSpan span = Create(from, to);
Assert.Equal(1, span.Months);
}
[Fact]
private static void Test1Month5Days()
{
DateTime from = new DateTime(2008, 1, 1);
DateTime to = new DateTime(2008, 2, 5);
MonthSpan span = Create(from, to);
Assert.Equal(1, span.Months);
Assert.Equal(5, span.Days);
}
[Fact]
private static void Test2Month20Days()
{
DateTime from = new DateTime(2008, 1, 1);
DateTime to = new DateTime(2008, 3, 20);
MonthSpan span = Create(from, to);
Assert.Equal(2, span.Months);
Assert.Equal(20, span.Days);
}
[Fact]
private static void TestYearLap()
{
DateTime from = new DateTime(2008, 10, 1);
DateTime to = new DateTime(2009, 1, 5);
MonthSpan span = Create(from, to);
Assert.Equal(2, span.Months);
Assert.Equal(5, span.Days);
}
[Fact]
private static void TestDaysOnly()
{
DateTime from = new DateTime(2008, 10, 20);
DateTime to = new DateTime(2008, 10, 25);
MonthSpan span = Create(from, to);
Assert.Equal(0, span.Months);
Assert.Equal(5, span.Days);
}
[Fact]
private static void TestDaysSpannedOnly()
{
DateTime from = new DateTime(2008, 10, 20);
DateTime to = new DateTime(2008, 11, 12);
MonthSpan span = Create(from, to);
Assert.Equal(0, span.Months);
Assert.Equal(23, span.Days);
}
#endif
}
}