28

I would like to know when given start and end dates, how can the months and year(s) between the two dates be retrieved.

Eg: Start Date: '1/1/2011'(mm/dd/yyyy) and End date :'11/30/2011'. The months and year to be retrieved are January,2011; February,2011; March,2011; and so on till November,2011

Mandar Pande
  • 12,250
  • 16
  • 45
  • 72
user1594760
  • 297
  • 1
  • 3
  • 3
  • 8
    This sounds like a homework question. The idea is that you work this one out for yourself. If you have any specific issues with what ever solution you come up with then I'll be glad to help. – Colin Mackay Aug 13 '12 at 08:28
  • Duplicate : http://stackoverflow.com/questions/1525990/difference-in-months – h1ghfive Aug 13 '12 at 08:33
  • 1
    @h1ghfive - no, it's not a duplicate of that one – PHeiberg Aug 13 '12 at 08:34
  • Possible duplicate of [easy way to loop over months and years from a given date](https://stackoverflow.com/questions/19827148/easy-way-to-loop-over-months-and-years-from-a-given-date) – Huseyin Yagli Oct 04 '17 at 13:53

9 Answers9

61

Here we go

public static IEnumerable<(string Month, int Year)> MonthsBetween(
        DateTime startDate,
        DateTime endDate)
{
    DateTime iterator;
    DateTime limit;

    if (endDate > startDate)
    {
        iterator = new DateTime(startDate.Year, startDate.Month, 1);
        limit = endDate;
    }
    else
    {
        iterator = new DateTime(endDate.Year, endDate.Month, 1);
        limit = startDate;
    }

    var dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
    while (iterator <= limit)
    {
        yield return (
            dateTimeFormat.GetMonthName(iterator.Month), 
            iterator.Year
        );

       iterator = iterator.AddMonths(1);
    }
}

And obviously you call it like this

var startDate = DateTime.ParseExact("01/01/2011", "MM/dd/yyyy");
var endDate = DateTime.ParseExact("11/30/2011", "MM/dd/yyyy");

var months = MonthsBetween(startDate, endDate);

The results should be something like

{
    {  "January", 2011  },
    {  "February", 2011  },
    {  "March", 2011  },
    {  "April", 2011  },
    {  "May", 2011  },
    {  "June", 2011  },
    {  "July", 2011  },
    {  "August", 2011  },
    {  "September", 2011  },
    {  "October", 2011  },
    {  "November", 2011  },
}

The month names being dependent on your culture which, I think, is exactly what you asked for, right?

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • we can improve this answer as using Tuple Values 'C# 7.0' method signature IEnumerable<(string Month, int Year)> MonthsBetween(DateTime startDate,DateTime endDate) and return as yield return ( dateTimeFormat.GetMonthName(iterator.Month),iterator.Year ); – Al-Hanash Moataz Aug 16 '20 at 05:16
  • 2
    @Al-HanashMoataz, it does make the code a little simpler but, remember that this will now use `System.ValueTuple` under the hood, the values have switched from properties to fields and are still called `Item1` and `Item2`, "under the hood". – Jodrell Mar 22 '21 at 17:35
30

You can start off with a while loop where the start date is less than or equal to the end date

Within it pull out the relevant Month and year part from the start date and store them (maybe you have a concrete class or a as a ), then increment the start date by 1 month using AddMonths(1)

//something on these lines 
while(startdate <= enddate)
{
// pull out month and year
startdate = startdate.AddMonths(1);
}
V4Vendetta
  • 37,194
  • 9
  • 78
  • 82
  • 1
    This really should be the chosen answer. Literally 2 lines of code vs. the chosen answer of many more. – Ricky Dec 13 '17 at 15:58
  • How is this not the chosen answer? Simple and clean. – Daniel Marín Apr 12 '18 at 14:49
  • @DanielMarin, while this answer demonstrates how to write a loop. It doesn't return, yield, list or build anything, its just a loop, functionally a no-op. The OP asks for a sequence or list of month names coupled with years. – Jodrell Apr 25 '18 at 07:43
  • 2
    it is necessary that the startdate starts on day 1, otherwise the dates (for example) between 01/20/2018 and 02/10/2018 will only return one month – enraged Nov 21 '18 at 11:38
8

You can use Enumerable.Range function to get the month and year between two dates,

var start = new DateTime(2011, 1, 1);
var end = new DateTime(2011, 11, 30);

var diff = Enumerable.Range(0, 13).Select(a => start.AddMonths(a))
           .TakeWhile(a => a <= end)
           .Select(a => String.Concat(a.ToString("MMMM") + ", " + a.Year));
Metin Atalay
  • 1,375
  • 18
  • 28
Pankajya
  • 109
  • 1
  • 5
  • Thanks ,bro . I use this style { .Select(e => e.ToString("yyyyMM"));} – Metin Atalay Nov 08 '17 at 07:32
  • 2
    incorrect if end.Day2011-2-1 will result in (2011-1). should compare with the lastdate in month of the end date. .TakeWhile(a => a <= end.AddDays(DateTime.DaysInMonth(end.Year,end.Month)-end.Day)) – phiree Dec 27 '17 at 09:36
4

Use this formula :

((date1.Year - date2.Year) * 12) + date1.Month - date2.Month

And u get the number of months .

Use this in an appropriate way and you will crack it.

Welcome to Stackoverflow , Here Hardwork is your part and giving thinking lines for that is for the fraternity to do when you have a problem.

bhuvin
  • 1,382
  • 1
  • 11
  • 28
  • The months need to be checked so the lower month is subtracted from the higher month, cannot assume first month is always greater than second month. – Mr. Mr. Aug 13 '12 at 08:36
  • 1
    @Monkieboy - You are right but ,Dude this is a seed , The dev learns when shakes hands with problems , So let him figure out things . – bhuvin Aug 13 '12 at 08:39
1
for(DateTime date = fromDate; date <= toDate; date.AddMonths(1))
{
    //Do something with "date"
    //DateTime.ParseExact(date, "MM/dd/yyyy")
}
Mark McGookin
  • 932
  • 1
  • 16
  • 39
0

This function return list of months between two dates

public static IEnumerable<dynamic> MonthsBetween(
    DateTime startDate,
    DateTime endDate)
{
    DateTime iterator;
    DateTime limit;

    if (endDate > startDate)
    {
        iterator = new DateTime(startDate.Year, startDate.Month, 1);
        limit = endDate;
    }
    else
    {
        iterator = new DateTime(endDate.Year, endDate.Month, 1);
        limit = startDate;
    }

    var dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
    while (iterator <= limit)
    {
        
        var firstDayOfMonth = new DateTime(iterator.Year, iterator.Month, 1);
        var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

        yield return new {
            Label = dateTimeFormat.GetMonthName(iterator.Month),
            Code = iterator.Year+"-"+iterator.Month,
            FirstDay = firstDayOfMonth,
            LastDay = lastDayOfMonth
        };

        iterator = iterator.AddMonths(1);
    }
}
0
private HashSet<string> GetMonths(DateTime start, DateTime end)
    {
        var totalMonths = ((end.Year - start.Year) * 12) + (end.Month - start.Month) + 1;
        var diff = Enumerable.Range(0, totalMonths).Select(a => start.AddMonths(a))
                   .TakeWhile(a => a <= end)
                   .Select(a => a.ToString("MMM")).ToHashSet();

        return diff;
    }
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 24 '22 at 03:57
0
        List<string> month= new List<string>();
        while (startDateValue <= endDateValue)
        {
            
            month.AddRange(new List<string>{ startDateValue.ToString("MMMM") }); 
            startDateValue = startDateValue.AddMonths(1); 
        }
BOB_STRONG
  • 11
  • 3
-1

You can utilize Linq by employing Enumerable.Range(startIndex, endIndex).
Example below:

    private string[] GetMonthsBetweenDates(DateTime deltaDate, int TotalMonths)
{
    var monthsBetweenDates = Enumerable.Range(0, TotalMonths)
                                       .Select(i => deltaDate.AddMonths(i))
                                       .OrderBy(e => e)
                                       .AsEnumerable();

    return monthsBetweenDates.Select(e => e.ToString("MMM")).ToArray();
}

The code above should produce the following results, assuming the current month is November.

Nov
Dec
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Simba
  • 489
  • 6
  • 7