将句点列表转换为c#中的日期列表

时间:2014-12-29 10:33:10

标签: c# linq generic-list

我有一个c#列表,其中包含使用cDates类的句点。

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解决方案?

3 个答案:

答案 0 :(得分: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;}
}

答案 1 :(得分: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

答案 2 :(得分: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();

否则,您需要展开{​​{1}}内的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