c# - Manipulate data on list with date period grouping by date/month -


i have list of sales of services specific time period (activationdate through enddate). need generate sell report grouping month-year (eg april 2012). each month i'd show how full month of use , how many days.

my class:

 public class salemonth  {     public datetime monthyear { get; set; }//.tostring("y")      public int fullmonth { get; set; }     public int daysmonth { get; set; }     public string totalmonths { { return string.format("{0:n2}",                                    (((fullmonth * 30.5) + daysmonth) / 30.5)); } }  } 

what have tried:

using (companycontext db = new companycontext()) {    var salelist =  db.mysales.tolist();    datetime = salelist.min(s => s.activationdate),         = salelist.max(s => s.enddate);     (datetime currdate = from.adddays(-from.day + 1)                                 .addticks(-from.timeofday.ticks);                   currdate < to;                   currdate = currdate.addmonths(1))    {       var sm = new salemonth       {           monthyear = currdate,           fullmonth = 0,           daysmonth = 0       };        var monthsell = salelist.where(p => p.activationdate < currdate.addmonths(1)                                                || p.enddate > currdate);       foreach (var sale in monthsell)       {          if (sale.activationdate.month == sale.enddate.month              && sale.activationdate.year == sale.enddate.year)          {//eg 4/6/13 - 17/6/13              sm.daysmonth += (sale.enddate.day - sale.activationdate.day + 1);          }          else          {             if (sale.activationdate.year == currdate.year                    && sale.activationdate.month == currdate.month)                sm.daysmonth += (currdate.addmonths(1) - sale.activationdate).days;             else if (sale.enddate.year == currdate.year                    && sale.enddate.month == currdate.month)                sm.daysmonth += sale.enddate.day;             else if(sale.activationdate.date <= currdate                    && sale.enddate > currdate.addmonths(1))                sm.fullmonth++;           }                                       }        vm.salemonthlist.add(sm);    } } 

i have feeling i'm missing here , there must more elegant way it.

here picture showing sells , report generated them.

linq contain way group data. start taking @ statement:

// group year-month var rows = s in salelist     orderby s.monthyear     group s new { year = s.monthyear.year, month = s.monthyear.month }; 

the above statement take data , group year-month create main key each year-month combination , create group of corresponding salemonth items group.

when grasp that, next step use groups calculate whatever want calculate within each group. so, if looking total fullmonths , daysmonths each year-month, this:

var rowstotals = s in salelist     orderby s.monthyear     group s new { year = s.monthyear.year, month = s.monthyear.month } grp     select new     {         yearmonth = grp.key.year + " " + grp.key.month,         fullmonthtotal = grp.sum (x => x.fullmonth),         daysmonthtotal = grp.sum (x => x.daysmonth)     }; 

edit:

after looking again @ you're doing, think more efficient this:

// populate our class time period interested in var startdate = salelist.min (x => x.activationdate); var enddate = salelist.max (x => x.enddate);  list<salemonth> salesreport = new list<salemonth>(); for(var = new datetime(startdate.year, startdate.month, 1);      <= new datetime(enddate.year, enddate.month, 1);     = i.addmonths(1)) {     salesreport.add(new salemonth { monthyear = }); }  // loop through each month-year foreach(var sr in salesreport) {     // sales happen in month     var lastdaythismonth = sr.monthyear.addmonths(1).adddays(-1);     var sales = s in salelist         lastdaythismonth >= s.activationdate,          sr.monthyear <= s.enddate     select s;      // calculate number of days sale spans month     var nextmonth = sr.monthyear.addmonths(1);     var firstofnextmonth = sr.monthyear.addmonths(1).adddays(-1).day;     sr.daysmonth = sales.sum (x =>         (x.enddate < nextmonth ? x.enddate.day : firstofnextmonth) -             (sr.monthyear > x.activationdate ?               sr.monthyear.day : x.activationdate.day));      // how many sales occur on entire month     sr.fullmonth = sales.where (x => x.activationdate <= sr.monthyear &&                                  nextmonth < x.enddate).count (); } 

Comments