我有一个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 解决方案?
您可以使用 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;}
}
您可以循环访问日期,并向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
。
有两种简单的方法可以将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();
否则,您需要在SelectMany
内展平Period
日期:
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
-class 而不进行更改(如果它不提供任何其他功能,则不需要它):
public class SingleDate
{
public DateTime Date { get; set; }
}