2014-12-29 2 views
0

У меня есть список C#, содержащий периоды с использованием класса cDates.Преобразование списка периодов в список дат в C#

public class cDates 
{ 
    public Date PeriodStart {get;set;} 
    public Date PeriodEnd {get;set;} 
} 


2014/01/01 - 2014/04/30 
2014/05/01 - 2014/07/31 
2014/08/01 - 2014/09/30 

Возможно ли получить список дат, содержащих все даты в существующие периоды, что-то вроде List.

public class cSingleDate 
{ 
      public Date SingleDate {get;set;} 
} 

    2014/01/01 
    2014/01/02 
    2014/01/03 
    ... 
    2014/09/30 

Я попытался найти решение с использованием петель, но хочу узнать, есть ли более чистое решение. Может быть, решение Linq?

+1

Что такое 'Dates' типа? –

+0

@FelipeOriani typo – mko

+2

Не префикс своих классов с помощью «c»: [не использовать венгерскую нотацию.] (Http://msdn.microsoft.com/en-us/library/ms229045 (v = vs.110). aspx) – BCdotWEB

ответ

3

Вы можете использовать LINQ для этого:

[TestMethod] 
public void TestPeriods() 
{ 
    var periods = new[] 
        { 
         new Period(new DateTime(2014, 01, 01), new DateTime(2014, 04, 30)), 
         new Period(new DateTime(2014, 05, 01), new DateTime(2014, 07, 31)), 
         new Period(new DateTime(2014, 08, 01), new DateTime(2014, 09, 30)), 
        }; 

    var days = from period in periods 
       let numberOfDays = (period.LastDay - period.FirstDay).Days + 1 
       from day in Enumerable.Range(0, numberOfDays) 
       select period.FirstDay.AddDays(day); 

    var distinctDays = days.Distinct().ToArray(); 

    distinctDays.Should().Contain(new DateTime(2014, 01, 01)); 
    distinctDays.Should().Contain(new DateTime(2014, 02, 01)); 
    distinctDays.Should().Contain(new DateTime(2014, 04, 30)); 
    distinctDays.Should().NotContain(new DateTime(2014, 10, 01)); 
} 

public class Period 
{ 
     public Period(DateTime firstDay, DateTime lastDay) 
     { 
      this.FirstDay = firstDay; 
      this.LastDay = lastDay; 
     } 

     public DateTime FirstDay {get;set;} 
     public DateTime LastDay {get;set;} 
} 
2

Вы можете просто цикл по датам, а также добавить один день в PeriodStart до тех пор, как она меньше или равна PeriodEnd:

var dates = new List<cSingleDate>(); 
foreach(var date in cDates) 
{ 
    while(date.PeriodStart <= date.PeriodEnd) 
    { 
     dates.Add(new cSingleDate { SingleDate = date.PeriodStart }); 
     date.PeriodStart = date.PeriodStart.AddDays(1); 
    } 
} 

Если вы не хотите изменить cDates просто использовать временную переменную для хранения PeriodStart.

+0

это почти то же самое, что и я. Я искал больше решений linq. – mko

1

Есть два простых способа преобразования даты из Period класса в единый список дат. Вы можете либо расширить класс Period, чтобы дать вам даты и использовать linq, чтобы сгладить его, либо вы прочитали оба свойства с помощью linq. Если класс SingleDate действительно хранит дату и ничего больше, и если он не предоставляет каких-либо дополнительных функций, вы можете рассмотреть возможность просто извлечь даты.

// Test data. 
var periods = new[] 
{ 
    new Period(new DateTime(2014, 01, 01), new DateTime(2014, 04, 30)), 
    new Period(new DateTime(2014, 05, 01), new DateTime(2014, 07, 31)), 
    new Period(new DateTime(2014, 08, 01), new DateTime(2014, 09, 30)), 
}; 

Если вы можете сделать Period класс для реализации IEnumerable<DateTime> интерфейса и таким образом разгладить даты для вас, то простого SelectMany может быть использован:

var result1 = 
    periods 
    // The Period class will enumerate the dates for SelectMany: 
    .SelectMany(x => x) 
    // Uncomment this line if you want to encapsulate the date. 
    //.Select(x => new SingleDate() { Date = x })  
    .ToList(); 

В противном случае вам нужно сглаживать Period дату внутри SelectMany:

var resul2 = 
    periods 
    // Here SelectMany has to enumerate the dates: 
    .SelectMany(x => new[] 
    { 
     x.PeriodStart, 
     x.PeriodEnd 
    }) 
    // Uncomment this line if you want to encapsulate the date. 
    //.Select(x => new SingleDate() { Date = x }) 
    .ToList(); 

Period -класс, реализующий интерфейс IEnumerable<DateTime> перечислить даты:

public class Period : IEnumerable<DateTime> 
{ 
    public Period(DateTime firstDay, DateTime lastDay) 
    { 
     this.PeriodStart = firstDay; 
     this.PeriodEnd = lastDay; 
    } 

    public DateTime PeriodStart { get; set; } 

    public DateTime PeriodEnd { get; set; } 

    public IEnumerator<DateTime> GetEnumerator() 
    { 
     yield return PeriodStart; 
     yield return PeriodEnd; 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

SingleDate -класса без изменений (не нужно, если он не дает каких-либо дополнительных функциональных возможностей):

public class SingleDate 
{ 
    public DateTime Date { get; set; } 
} 
+0

Обновленный код и описание. – t3chb0t

Смежные вопросы