c# - 提取一个期间内的子期间

标签 c# .net datetime intervals

给定一个从 StartingDateEndingDate 的时间段。 我想获取从给定 StartingMonthEndingMonth 开始的该时间段内的间隔。

示例:

StartingMonth = april (4) 
EndingMonth = november (11)

期间:

Period A : StartingDate =  (2014, 03, 01); EndingDate = (2015, 02, 28);
Period B : StartingDate =  (2014, 07, 01); EndingDate = (2015, 06, 30);
Period C : StartingDate =  (2014, 01, 01); EndingDate = (2015, 12, 31);

会返回:

Period A : 1 sub-period = (2014, 4, 1) - (2014, 11, 30)
Period B : 2 sub-periods = (2014, 7, 1) - (2014, 11, 30) ; (2015, 4, 1) - (2015, 6, 30)
Period C : 2 sub-periods = (2014, 4, 1) - (2014, 11, 30) ; (2015, 4, 1) - (2015, 11, 30)

我已经尝试过这个(似乎是困难的方法并且不能管理多个子周期): 使用 LINQ 可能是一种更简单的方法?

if (StartingDate.Month < startingMonth && EndingDate.Month < endingMonth)
{
    periods.Add(new PeriodInterval
    {
        StartDate = new DateTime(StartingDate.Year, startingMonth, 1), 
        EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
    });
}

if (StartingDate.Month > startingMonth && EndingDate.Month > endingMonth)
{
     periods.Add(new PeriodInterval
    {
       StartDate = new DateTime(StartingDate.Year, startingMonth, 1), 
       EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
     });
}

if (StartingDate.Month < startingMonth && EndingDate.Month > endingMonth)
{
    periods.Add(new PeriodInterval
    {
        StartDate = new DateTime(StartingDate.Year, startingMonth, 1), 
        EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
    });                   
}

if (StartingDate.Month > startingMonth && EndingDate.Month < endingMonth)
{
    periods.Add(new PeriodInterval
    {
        StartDate = new DateTime(StartingDate.Year, startingMonth, 1), 
        EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
    });                    
}

这个想法是返回红色周期内的蓝色周期: The idea is to returns the blue periods within the red period

最佳答案

class Discount
{
    public int DiscountID { get; set; } //You will need some Key field if you are storing these in a database.
    public DateTime issueDate { get; set; }
    public DateTime expirationDate { get; set; }

    public List<PeriodInterval> intervals { get; set; }

    public Discount(DateTime IssueDate, DateTime ExpirationDate)
    {
        issueDate = IssueDate;
        expirationDate = ExpirationDate;
        intervals = new List<PeriodInterval>();
    }

    public void AddInterval(DateTime StartDate, DateTime EndDate)
    {
        intervals.Add(new PeriodInterval() { 
            StartMonth=StartDate.Month,
            StartDay=StartDate.Day,
            EndMonth=EndDate.Month,
            EndDay=EndDate.Day
        });
    }
    public List<Period> GetPeriods()
    {
        List<Period> periods=new List<Period>();
        int yearCount = expirationDate.Year-issueDate.Year+1; //+1: Run at least one year against the periods.
        for (int i = 0; i < yearCount; i++)
        {
            //Loop through all the years and add 'Periods' from all the PeriodInterval info.
            foreach (PeriodInterval pi in intervals)
            {
                var period = pi.GetPeriod(issueDate, expirationDate, i);
                if (period != null)
                    periods.Add(period);
            }
        }
        return periods;
    }
}
class Period
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}
class PeriodInterval
{
    public int PeriodIntervalID { get; set; } //You will need some Key field if you are storing these in a database.
    public int DiscountID { get; set; } //Foreign Key to Discount. This is alsof for database storage.

    public int StartMonth { get; set; }
    public int StartDay { get; set; }

    public int EndMonth { get; set; }
    public int EndDay { get; set; }

    public Period GetPeriod(DateTime issueDate, DateTime expirationDate, int Year)
    {
        DateTime PeriodStart = new DateTime(issueDate.AddYears(Year).Year, StartMonth, StartDay);
        DateTime PeriodEnd = new DateTime(issueDate.AddYears(Year).Year, EndMonth, EndDay);

        PeriodStart=new DateTime(Math.Max(PeriodStart.Ticks, issueDate.Ticks)); //Limit period to the max of the two start dates.
        PeriodEnd = new DateTime(Math.Min(PeriodEnd.Ticks, expirationDate.Ticks)); //Limit period to the min of the two end dates.

        if(PeriodEnd>PeriodStart) //If a valid period
        {
            return new Period()
            {
                StartDate = PeriodStart,
                EndDate = PeriodEnd
            };
        }
        //Default Return Null
        return null;
    }
}

我构建了一个控制台应用程序来测试这一点:

static void Main(string[] args)
{
    List<Discount> Discounts = new List<Discount>();

    Discount d1 = new Discount(new DateTime(2014, 3, 1), new DateTime(2015, 02, 28));
    Discount d2 = new Discount(new DateTime(2014, 7, 1), new DateTime(2015, 06, 30));
    Discount d3 = new Discount(new DateTime(2014, 01, 1), new DateTime(2015, 12, 31));

    Discounts.Add(d1);
    Discounts.Add(d2);
    Discounts.Add(d3);

    foreach (Discount d in Discounts)
    {
        d.AddInterval(new DateTime(2014, 4, 1), new DateTime(2014, 11, 30));

        Console.WriteLine("IssueDate:{0} ExpirationDate:{1}", d.issueDate, d.expirationDate);
        foreach (Period p in d.GetPeriods())
        {
            Console.WriteLine("Start:{0} End:{1}", p.StartDate, p.EndDate);
        }
    }

    Console.ReadLine();
}

打印出来的内容如下:

Results

关于c# - 提取一个期间内的子期间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24656848/

相关文章:

c# - Microsoft 图表控件 - 每当我使用财务公式时,大红色 X(坏)

c# - 文件拖放事件处理程序中的 MessageBox 导致 Windows 资源管理器卡住

c# - 使用编码从 XML 字符串中获取字节数组

python - 在时间戳/日期时间/日期时间64类型的列上运行groupby时如何正确使用pandas agg函数?

sql - SQL SERVER 2008 R2 中无效日期的 DATE 与 DATETIME 转换

c# - 我可以同时为 Amazon S3 存储桶中的所有对象设置过期 header 吗?

c# - C#计算两个多边形交点的简单方法

.net - c# 全双工异步命名管道 .NET

c++ - boost::locale::date_time 的陷阱

c# - 访问汽车属性中的支持字段