2010-10-08 5 views
7

я следующий фрагмент кода, который я использую, чтобы получить отдельные даты между двумя датами:Создать массив месяцев между двумя датами

DateTime[] output = Enumerable.Range(0, 1 + endDate.Subtract(startDate).Days) 
    .Select(offset => startDate.AddDays(offset)) 
    .ToArray(); 

Однако в следующем разделе

endDate.Subtract(startDate).Days 

не имеет .Months, чтобы вернуть месяцы в диапазоне дат.

Например, если я даю 1/1/2010 и 6/1/2010, я ожидаю, что вернусь 01.01.2010, 02.02.2010, 01.03.2010, 4/1/2010, 5/1/2010 и 6/1/2010.

Любые идеи?

+0

Как будет работать «Месяц»? Как он узнает, какой месяц месяца использовать? После вычитания вы просто остаетесь с TimeSpan, который нейтрален по дате и, следовательно, ничего не знает о том, какие месяцы использовать. –

+0

Возможный дубликат [Разница в месяцах] (http: // stackoverflow.com/questions/1525990/разница в месяцах) –

+0

'.Days' возвращает ** количество дней ** в интервале, а не фактические дни. Как вы определяете, что «* месяц между двумя датами»? В этом месяце месяц ** не менее 1 дня **? В течение месяца ** ** в промежутке? Также как вам нужно представлять месяц, используя структуру 'DateTime'? - как 1-го числа месяца? – CyberDude

ответ

25

Попробуйте это:

static IEnumerable<DateTime> monthsBetween(DateTime d0, DateTime d1) 
{ 
    return Enumerable.Range(0, (d1.Year - d0.Year) * 12 + (d1.Month - d0.Month + 1)) 
        .Select(m => new DateTime(d0.Year, d0.Month, 1).AddMonths(m)); 
} 

Это включает в себя как месяц начала и окончания месяца. Это находит, сколько месяцев есть, а затем создает новый DateTime на основе d0 года и месяца. Это означает, что месяцы похожи на yyyy-MM-01. Если вы хотите, чтобы оно включало время и день d0, вы можете заменить new DateTime(d0.Year, d0.Month, 1).AddMonths(m) на d0.AddMonths(m).

Я вижу, что вам нужен массив, в этом случае вы просто используете monthsBetween(..., ...).ToArray() или ставите .ToArray() внутри метода.

0

Это вы что искали? Требование очень неоднозначно.

DateTime[] calendarMonthBoundaries = Enumerable.Range(0, 1 + endDate.Subtract(startDate).Days) 
    .Select(offset => startDate.AddDays(offset)) 
    .Where(date => date.Day == 1) 
    .ToArray(); 
1

Вы можете перечислить приращений месяцев с:

private static IEnumerable<DateTime> ByMonths(DateTime startDate, DateTime endDate) 
{ 
    DateTime cur = startDate; 

    for(int i = 0; cur <= endDate; cur = startDate.AddMonths(++i)) 
    { 
    yield return cur; 
    } 
} 

, а затем вызвать ToArray() на том, что если вы хотите массив. Это разумно полезно иметь ценности, которые, вероятно, будут тем, что нужно; например если вы начинаете на 31 января м вы получите следующий 28 февр й (или 29-го на високосные годы), затем 31 мар ул, а затем 30 апреля го и так далее.

+0

DateTime [] months = ByMonths ({30/01/2013 12:00:00 AM}, {4/04/2013 12:00:00 AM}). ToArray(); Это возвращает только 3 месяца (jan, feb, mar), апрель отсутствует. –

+0

@DaveLucre Я не уверен, что это плохо, потому что я не уверен, что требование в вопросе рассматривает «между». В этом случае, безусловно, можно было бы внести поправки в апреле, я просто не знаю, следует ли это делать. –

3

Поскольку мне просто нужен год и месяц между двумя датами, я немного изменил Лассе Эспехольта. предположим: d0 = 2012-11-03

d1 = 2013-02-05

Результат будет выглядеть примерно так:

2012-11

2012-12

2013-01

2013-02

private List<Tuple<int,int>> year_month_Between(DateTime d0, DateTime d1) 
    { 
     List<DateTime> datemonth= Enumerable.Range(0, (d1.Year - d0.Year) * 12 + (d1.Month - d0.Month + 1)) 
         .Select(m => new DateTime(d0.Year, d0.Month, 1).AddMonths(m)).ToList(); 
    List<Tuple<int, int>> yearmonth= new List<Tuple<int,int>>(); 

     foreach (DateTime x in datemonth) 
     { 
      yearmonth.Add(new Tuple<int, int>(x.Year, x.Month)); 
     } 
     return yearmonth; 
    } 
Смежные вопросы