C# 时间跨度的总和差异,按每年的旅行天数排序

C# 时间跨度的总和差异,按每年的旅行天数排序,c#,.net,datetime,timespan,C#,.net,Datetime,Timespan,所以我有所有这些旅行日期,从日期到日期。我想把所有的旅行天数加起来,然后按年份分类。但是,如果一次旅行持续两年,我的代码将达到错误的总和:-( 给定 我的代码生成了这个。但是,它犯了一个错误: Year Total days 2001 32 2002 137 2003 60 2009 334 2010 32 2013 365 2014 398 <---- here is a case where my code is wrong

所以我有所有这些旅行日期,从日期到日期。我想把所有的旅行天数加起来,然后按年份分类。但是,如果一次旅行持续两年,我的代码将达到错误的总和:-(

给定

我的代码生成了这个。但是,它犯了一个错误:

Year    Total days
2001    32
2002    137
2003    60
2009    334
2010    32
2013    365
2014    398        <---- here is a case where my code is wrong

Sum     1358
年总天数
2001    32
2002    137
2003    60
2009    334
2010    32
2013    365

2014 398计算两个日期之间的天数不需要这么大的代码;可以使用更简单/更准确的方法。例如:

DateTime date1 = new DateTime(2013, 1, 1);
DateTime date2 = new DateTime(2015, 2, 2);

int totDays = Math.Abs(date1.Subtract(date2).Days);
适应您的具体情况:

int[] days = new int[Math.Abs(date1.Year - date2.Year) + 1];
int curYear = 0;
if (date1.Year != date2.Year)
{
    if(date1.Year > date2.Year)
    {
        DateTime temp = date1;
        date1 = date2;
        date2 = temp;
    }
    int curYearNo = date1.Year - 1;
    curYear = -1;
    do
    {
        curYearNo = curYearNo + 1;
        curYear = curYear + 1;
        if (curYearNo < date2.Year)
        {
            days[curYear] = Math.Abs(new DateTime(curYearNo, 1, 1).Subtract(new DateTime(curYearNo, 12, 31)).Days) + 1; //Without +1 it would output 364/365 (because of not including both 1st January and 31st December)
        }
        else
        {
            days[curYear] = Math.Abs(new DateTime(curYearNo, 1, 1).Subtract(date2).Days);
        }
    } while (curYearNo < date2.Year);
}
else
{
    days[curYear] = Math.Abs(date1.Subtract(date2).Days);
}
int[]天=新的int[Math.Abs(date1.Year-date2.Year)+1];
int curYear=0;
如果(日期1.Year!=日期2.Year)
{
如果(日期1.Year>日期2.Year)
{
DateTime temp=date1;
date1=date2;
日期2=温度;
}
int curo=date1.Year-1;
curYear=-1;
做
{
curdeargeno=curdeargeno+1;
curYear=curYear+1;
如果(当前日期<日期2.年)
{
days[curYear]=Math.Abs(new DateTime(curdeargho,1,1)。减去(new DateTime(curdeargho,12,31))。days)+1;//如果不加1,它将输出364/365(因为不包括1月1日和12月31日)
}
其他的
{
days[curYear]=Math.Abs(新日期时间(curyearo,1,1)。减去(日期2)。days);
}
}而(curo
如果您编写了一个助手方法,将日期范围拆分为按年份划分的几个范围:

IEnumerable<Tuple<DateTime,DateTime>> 
    SplitDateRangeByYear(DateTime fromDate, DateTime toDate)
{
    var start = fromDate;
    for(var y = fromDate.Year; y < toDate.Year; ++y)
    {
        var nextYear = y + 1;
        var nextYearStartDate = new DateTime(nextYear, 1, 1);
        yield return Tuple.Create(start, nextYearStartDate);
        start = nextYearStartDate;
    }
    yield return Tuple.Create(start, toDate);
}

这是您所要求的更通用的解决方案,因为它将正确处理子天时间跨度组件(即,您的范围包括一天中的时间)。

假设
var stays=List();
,您可以尝试以下方法:

var days = stays.SelectMany(s =>
        Enumerable
            .Range(0, (s.ToDate - s.FromDate).Days + 1)
            .Select(d => s.FromDate.AddDays(d)))
    .GroupBy(d => d.Year)
    .Select(s => new { Year = s.Key, TotalDays = s.Count() })
    .ToList();

days.ForEach(d =>
{
    Console.WriteLine("{0} {1}", d.Year, d.TotalDays);
});
上面的输出是:

2001 32
2002 137
2003 60
2009 334
2010 32
2013 365
2014 365
2015 33

你考虑过使用LINQ的Sum()方法吗?不,我没有。实际上我从来没有使用过这个方法。该读了:)是的,但结果必须按年份排序。您的代码只提供2013年1月1日至2015年2月2日之间的天数。其中有多少天是在2013年、2014年和2015年?@kabforks我已经在你的评论中回答了你的问题,“这里是我的代码错误的案例”。还提出了一种更简单的解决问题的方法。如果你想知道每年的天数,你可以编辑一下;我会马上做。@kabforks那里有一个示例代码,根据我提出的想法存储每年的天数。谢谢你的努力:-)。@kabforks没问题。实际上没有太多的努力,这正是我想要表达的观点:)(我确实纠正了几次,因为我在并行处理其他事情时做得很快)。我不太喜欢LINQ,但我必须承认其他答案似乎都很好。谢谢,我一定会试试这个!我收到一个错误:“无法从用法推断方法‘IEnumerable System.Linq.Enumerable.SelectMany(此IEnumerable,Func)’的类型参数。请尝试显式指定类型参数。”我的错误!日期是否存储为DateTime?不是时间跨度。我加了一个“.Value”,它成功了。现在我必须编译并部署这个恐龙;-)。我不太清楚这段代码是如何工作的,但它似乎做得非常优雅。谢谢
    var yearlyTotals = stays
        .SelectMany(s => SplitDateRangeByYear(s.FromDate, s.ToDate))
        .GroupBy(x => x.Item1.Year)
        .Select(g => new{
                Year = g.Key, 
                NumDays= g.Sum(x => (x.Item2 - x.Item1).TotalDays)});
var days = stays.SelectMany(s =>
        Enumerable
            .Range(0, (s.ToDate - s.FromDate).Days + 1)
            .Select(d => s.FromDate.AddDays(d)))
    .GroupBy(d => d.Year)
    .Select(s => new { Year = s.Key, TotalDays = s.Count() })
    .ToList();

days.ForEach(d =>
{
    Console.WriteLine("{0} {1}", d.Year, d.TotalDays);
});
2001 32
2002 137
2003 60
2009 334
2010 32
2013 365
2014 365
2015 33