所以我拥有所有这些旅行日期,从日期到目前为止。我想把所有的旅行日加起来,然后按年份排序。但是,如果一次旅行超过两年,我的代码将达到错误的总和:-(
鉴于
From date To date Number of days
01.01.2001 01.02.2001 32
01.01.2002 01.02.2002 32
01.05.2002 01.08.2002 93
20.12.2002 01.03.2003 72
01.02.2009 01.02.2010 366
01.01.2013 02.02.2015 763
Sum 1358
我的代码生成了这个。但是,它犯了一个错误:
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
代码
var dates = new Dictionary<int, int>();
var stays = GetStays();
var returnString = "Year, Total days<br><br>";
foreach (var stay in stays)
{
var totalTravelDays = stay.ToDate.Value.AddDays(1) - stay.FromDate;
var currentYear = stay.FromDate.Value.Year;
var nextYear = stay.FromDate.Value.AddYears(1).Year;
var nextYearDate = new DateTime(stay.FromDate.Value.Year, 1, 1).AddYears(1);
var daysInThisYear = new TimeSpan?();
var daysInNextYear = new TimeSpan?();
if (stay.FromDate.Value.Year != stay.ToDate.Value.Year)
{
daysInThisYear = nextYearDate - stay.FromDate;
daysInNextYear = totalTravelDays - daysInThisYear;
}
else
{
daysInThisYear = totalTravelDays;
daysInNextYear = new TimeSpan(0);
}
if (dates.ContainsKey(currentYear))
dates[currentYear] += daysInThisYear.Value.Days;
else
dates[currentYear] = daysInThisYear.Value.Days;
if (dates.ContainsKey(nextYear))
dates[nextYear] += daysInNextYear.Value.Days;
else
dates[nextYear] = daysInNextYear.Value.Days;
}
帮助赞赏:)
答案 0 :(得分:4)
假设var stays = List<Stay>();
,你可以试试这个:
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
答案 1 :(得分:3)
如果您编写辅助方法将日期范围拆分为按年划分的多个范围:
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);
}
然后你可以写一些方便的Linq来做你的出价:
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)});
这是您要求的更通用的解决方案,因为它将正确处理子日TimeSpan组件(即您的范围包括一天中的时间)。
答案 2 :(得分:2)
您不需要如此大的代码来计算两个日期之间的天数;你可以依靠更简单/更准确的方法。例如:
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);
}