The difference in the amounts in the range, sorted by days of travel per year

So, I have all these travel dates, starting from the date and date. I want to add all the days of the trip and sort them by year. However, if you travel for a period that spans two years, my code will reach the wrong amount :-(

Considering

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 

My code produces this. However, this makes an error:

 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 

the code

 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; } 

Help rate :)

+4
source share
3 answers

Assuming var stays = List<Stay>(); , you can try the following:

 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); }); 

The conclusion above:

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

If you write a helper method for dividing date ranges into several ranges, divided by year:

 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); } 

Then you can write a convenient Linq to complete your bets:

  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)}); 

This is the more general solution you requested because it will correctly handle TimeSpan daytime components (i.e. your ranges include the time of day).

+3
source

You do not need such a large code to calculate the days between two dates; you can rely on a much simpler / more accurate approach. For instance:

 DateTime date1 = new DateTime(2013, 1, 1); DateTime date2 = new DateTime(2015, 2, 2); int totDays = Math.Abs(date1.Subtract(date2).Days); 

Adapted to your specific situation:

 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); } 
+2
source

Source: https://habr.com/ru/post/1497025/


All Articles