Is my equivalent of Excel's "EOMONTH" function correct? I am trying to create a function similar to Excel's EOMONTH function in C#. I have written the following, however, I am not entirely sure if the it achieves the equivalent functionality. Is my equivalent of Excel's "Eomonth" function correct and are my tests sufficient?

public static DateTime EOMonth(this DateTime dateTime, int months = 0)
{
    DateTime firstDayOfTheMonth = new DateTime(dateTime.Year, dateTime.Month, 1);
    return firstDayOfTheMonth.AddMonths(1 + months).AddDays(-1);
}


Tests

[Test]
public void EOMonth_For5jan2011WithNoAddedMonths_ReturnsLastDayOfJan() 
{
    var expectedDate = DateTime.Parse("31-Jan-2011");
    var currentDate = DateTime.Parse("5-Jan-2011");

    var result = currentDate.EOMonth();

    Assert.That(result, Is.EqualTo(expectedDate));
}

[Test]
public void EOMonth_For5jan2011With_1_AddedMonths_ReturnsLastDayOfFeb2011()
{
    var expectedDate = DateTime.Parse("28-Feb-2011");
    var currentDate = DateTime.Parse("5-Jan-2011");

    var result = currentDate.EOMonth(1);

    Assert.That(result, Is.EqualTo(expectedDate));
}

[Test]
public void EOMonth_For5jan2011WithNegative_1_AddedMonths_ReturnsLastDayOfFeb()
{
    var expectedDate = DateTime.Parse("31-Dec-2010");
    var currentDate = DateTime.Parse("5-Jan-2011");

    var result = currentDate.EOMonth(-1);

    Assert.That(result, Is.EqualTo(expectedDate));
}

 [Test]
 public void EOMonth_For28Feb2007_12_AddedMonths_ReturnsLastDayOfFeb2008()
 {
     var expectedDate = DateTime.Parse("29-Feb-2008");
     var currentDate = DateTime.Parse("28-Feb-2007");

     var result = currentDate.EOMonth(12);

     Assert.That(result, Is.EqualTo(expectedDate));
 }
For your implementation, why not use:

return ((new DateTime(dateTime.Year, dateTime.Month, 1)).AddMonths(1 + months).AddDays(-1));


To me, that's a little cleaner, but it might just be me. When I'm just creating an object to be returned, I'm not a fan of storing it in a variable. Instead, just return exactly what you mean to and be done with it.



For your test cases:

I'm not sure that it matters in this instance, since you are relying exclusively on built in methods, but I would create test cases around February and March for the various types of leap years. What if I specify February 29th on a non-leap year? Does it work for the different leap year conditions? I'd also create test cases around new years (December and January).