在 c# 中将周期列表转换为日期列表

本文关键字:列表 转换 日期 周期 | 更新日期: 2023-09-27 18:35:29

我有一个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 解决方案?

在 c# 中将周期列表转换为日期列表

您可以使用 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; }
}