How to show Month names instead of Month Number in View? - c#

How can I show month names in my view instead of month numbers?
Action Method:
public ActionResult MyPerformance()
{
int year = DateTime.Now.Year;
DateTime firstDay = new DateTime(year, 1, 1);
DateTime lastDay = new DateTime(year, 12, 31).AddDays(1).AddSeconds(-1);
var result = db.Chats
.Where(c => System.Data.Entity.DbFunctions.TruncateTime(c.MSTChatCreatedDateTime) >= firstDay &&
System.Data.Entity.DbFunctions.TruncateTime(c.MSTChatCreatedDateTime) <= lastDay)
.Select(x => new { x.MSTChatCreatedDateTime })
.ToList()
.GroupBy(c => new
{
Year = c.MSTChatCreatedDateTime.ToCleanDateTime().Year,
Month = c.MSTChatCreatedDateTime.ToCleanDateTime().Month
})
.Select(c => new ReportVM
{
Title = string.Format("{0}", c.Key.Month), //chart x Axis value.
ChatCountCreatdDate = c.Count() //chart y Axis value.
})
.ToList();
return View(result);
}
Data being reflected is correct in the View, but I am not able to render the month names in the view.
See the attached Image showing the month numbers.
Thank you!

You can format in "MMM" which display name, here is your code
public ActionResult MyPerformance()
{
int year = DateTime.Now.Year;
DateTime firstDay = new DateTime(year, 1, 1);
DateTime lastDay = new DateTime(year, 12, 31).AddDays(1).AddSeconds(-1);
var result = db.Chats
.Where(c => System.Data.Entity.DbFunctions.TruncateTime(c.MSTChatCreatedDateTime) >= firstDay &&
System.Data.Entity.DbFunctions.TruncateTime(c.MSTChatCreatedDateTime) <= lastDay)
.Select(x => new { x.MSTChatCreatedDateTime })
.ToList()
.GroupBy(c => new
{
Year = c.MSTChatCreatedDateTime.ToCleanDateTime().Year,
Month = c.MSTChatCreatedDateTime.ToCleanDateTime().Month
})
.Select(c => new ReportVM
{
Title = c.MSTChatCreatedDateTime.ToCleanDateTime().ToString("MMMM"), //chart x Axis value.
ChatCountCreatdDate = c.Count() //chart y Axis value.
})
.ToList();
return View(result);
}

Related

How can I display the count of Weekly BirthDate in c # chart?

var result = lst
.GroupBy(l => l.BirthDate)
.Select(cl => new
{
BirthDate = cl.First().BirthDate,
Count = cl.Count().ToString()
}).ToList();
DataTable dt = Utility.ConvertToDataTable(result);
chart2.DataSource = dt;
chart2.Name = "BirthDate";
chart2.Series["Series1"].XValueMember = "BirthDate";
chart2.Series["Series1"].YValueMembers = "Count";
this.chart2.Titles.Remove(this.chart1.Titles.FirstOrDefault());
this.chart2.Titles.Add("Weekly Enrollment Chart");
chart2.Series["Series1"].IsValueShownAsLabel = true;
This displays all the dates present in the datagridview.
I want to display the weekly Birthdate and count the number of births.
You can group by the week number in the year:
lst.GroupBy(b => {
var firstDayOfYear = new DateTime(b.BirthDate.Year, 1, 1);
// Calculate the days after which the first day
// of year appears so we can offset it when calculating week number
int daysAfterSunday = -1;
while(firstDayOfYear.DayOfWeek != DayOfWeek.Sunday) {
daysAfterSunday++;
firstDayOfYear = firstDayOfYear.AddDays(-1);
}
return (b.BirthDate.DayOfYear + daysAfterSunday)/7;
})
.Select(g => new { Week = g.Key, Count = g.Count(), BirthDates = g.Select(v => v.BirthDate) });
Then you can calculate the week start date from week number using the methods in this answer.

How to display each month, even if no data for this month

The query works fine, except it only pulls the value where a month has more then zero incident, for example if January had no value, then it doesn't show January. I would like to show all months.
var result = tIncidentReportings
.AsEnumerable()
.GroupBy(c => c.Date.ToString("MMM"))
.Select(g => new { Month = g.Key, Count = g.Count() })
.OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture));
The issue is you are going to have missing months for whatever months don't have any reports. You'll have to check to see which months don't have any and add them manually.
var result = tIncidentReportings
.AsEnumerable()
.GroupBy(c => c.Date.ToString("MMM"))
.Select(g => new { Month = g.Key, Count = g.Count() })
.OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture));
var months =
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.MonthGenitiveNames.Select(s => s.Substring(0,3)).ToList();
months.foreach(m => {
if(!results.Select(r => r.Month).Contains(m)){
results.Add(new {Month = m, Count = 0};
});
Something like that
Or a rewrite of:
var months = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.MonthGenitiveNames.Select(s => s.Substring(0,3)).ToList();
var reports = months.Select(m =>
new {
Month = m,
Count = tIncidentReportings.AsEnumerable().Where(i => i.Date.ToString("MMM") == m).Count()
}
).OrderBy(x => DateTime.ParseExact((x.Month).ToString(), "MMM", CultureInfo.InvariantCulture)).ToList();

Get List of weeks by giving year and month as parameter C#

I need list of weeks with starting and ending dates by giving int year and int month,
Example Result,
Week1 = 7/1/2012 to 7/1/2012
Week2 = 7/2/2012 to 7/8/2012
Week3 = 7/9/2012 to 7/15/2012
Week4 = 7/16/2012 to 7/22/2012
Week5 = 7/23/2012 to 7/29/2012
Week6 = 7/30/2012 to 7/31/2012
Something like this should work:
// using System.Globalization;
var calendar = CultureInfo.CurrentCulture.Calendar;
var firstDayOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
var weekPeriods =
Enumerable.Range(1, calendar.GetDaysInMonth(year, month))
.Select(d =>
{
var date = new DateTime(year, month, d);
var weekNumInYear = calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, firstDayOfWeek);
return new { date, weekNumInYear };
})
.GroupBy(x => x.weekNumInYear)
.Select(x => new { DateFrom = x.First().date, To = x.Last().date })
.ToList();
Of course you can change the Culture (here I have used the CurrentCulture).
check this one and edit according to your need
// Get the weeks in a month
DateTime date = DateTime.Today;
// first generate all dates in the month of 'date'
var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n));
// then filter the only the start of weeks
var weekends = (from d in dates
where d.DayOfWeek == DayOfWeek.Monday
select d).ToList();
foreach (var d in weekends)
{
Console.WriteLine(d);
}
Console.Write(weekends);
Console.ReadLine();
hope it help you.
you can also take a look here for other stuff HERE

How do I make this NHibernate QueryOver query return rows for empty groups

The following NHibernate QueryOver query is counting the number of applications for each month, within a given date range.
However, I don't get any results for months that don't have any applications in them but I want to actually have Count = 0 returned for those months.
So how would I change the query to return a row as well for months that don't have any applications in them?
DateTimeOffset endDate = DateTimeOffset.Now;
DateTimeOffset startDate = endDate.AddMonths(-12);
var result = Session.QueryOver<Application>()
.WhereRestrictionOn(c => c.SubmissionDate).IsBetween(startDate).And(endDate)
.SelectList(list => list
.Select(Projections.SqlGroupProjection(
"YEAR(SubmissionDate) As [Year]",
"YEAR(SubmissionDate)",
new[] { "YEAR" },
new IType[] { NHibernateUtil.Int32 }))
.Select(Projections.SqlGroupProjection(
"MONTH(SubmissionDate) As [Month]",
"MONTH(SubmissionDate)",
new[] { "MONTH" },
new IType[] { NHibernateUtil.Int32 }))
.SelectCount(x => x.Id))
.OrderBy(Projections.SqlFunction(
"YEAR",
NHibernateUtil.Int32,
Projections.Property<Application>(item => item.SubmissionDate))).Asc
.ThenBy(Projections.SqlFunction(
"MONTH",
NHibernateUtil.Int32,
Projections.Property<Application>(item => item.SubmissionDate))).Asc
.List<object[]>()
.Select(n => new
{
Year = n[0],
Month = n[1],
Count = (int)n[2]
}));
Update: taking your idea with DateTime.AddMonths() it gets even shorter
DateTime lastMonth = startdate;
var unionresults = result.SelectMany(r =>
{
var actualDate = new DateTime(r.Year, r.Month, 1);
var results = Enumerable.Repeat(1, Months)
.Select(i => lastMonth.AddMonths(i))
.TakeWhile(date => date < actualDate)
.Select(date => new { Year = date.Year, Month = date.Month, Count = 0 })
.Concat(new[] { r });
lastMonth = actualDate;
return results;
});
Original:
i think you have to add that data after the query. here an example using linq to fill in missing months
var result = <query>;
int lastMonth = 1;
var unionresults = result.SelectMany(r =>
{
var results = new[] { r }.AsEnumerable();
if (lastMonth > r.Month)
{
results = Enumerable.Range(lastMonth, 12 - lastMonth).Select(month => new { Year = r.Year, Month = month, Count = 0 })
.Concat(Enumerable.Range(1, r.Month).Select(month => new { Year = r.Year, Month = month, Count = 0 }))
.Concat(results);
}
else if (lastMonth < r.Month)
{
results = Enumerable.Range(lastMonth, r.Month - lastMonth)
.Select(month => new { Year = r.Year, Month = month, Count = 0 })
.Concat(results);
}
lastMonth = r.Month + 1;
if (lastMonth > 12)
{
lastMonth = 1;
}
return results;
});
It cannot be done with a few simple changes. The SQL query that is generated by your QueryOver() cannot count what does not exist in the first place.
You could probably do it with a UNION or a JOIN using a virtual/temporary table (depending on the DBMS) but that would make the query overly complicated.
I suggest adding a loop after your query that iterates through the list, copies the elements to a new list and adds any non-existing months to that new list. Something like this:
class YearMonthCount
{
public int Year { get; set; }
public int Month { get; set; }
public int Count { get; set; }
}
// Start and End dates
DateTime startDate = new DateTime(2011, 9, 1);
DateTime endDate = new DateTime(2012, 6, 1);
// this would be a sample of the QueryOver() result
List<YearMonthCount> result = new List<YearMonthCount>();
result.Add(new YearMonthCount { Year = 2011, Month = 10, Count = 2 });
result.Add(new YearMonthCount { Year = 2011, Month = 11, Count = 3 });
result.Add(new YearMonthCount { Year = 2012, Month = 1, Count = 4 });
result.Add(new YearMonthCount { Year = 2012, Month = 2, Count = 1 });
result.Add(new YearMonthCount { Year = 2012, Month = 4, Count = 1 });
result.Add(new YearMonthCount { Year = 2012, Month = 5, Count = 1 });
int i = 0;
List<YearMonthCount> result2 = new List<YearMonthCount>();
// iterate through result list, add any missing entry
while (startDate <= endDate)
{
bool addNewEntry = true;
// check to avoid OutOfBoundsException
if (i < result.Count)
{
DateTime listDate = new DateTime(result[i].Year, result[i].Month, 1);
if (startDate == listDate)
{
// entry is in the QueryOver result -> add this
result2.Add(result[i]);
i++;
addNewEntry = false;
}
}
if (addNewEntry)
{
// entry is not in the QueryOver result -> add a new entry
result2.Add(new YearMonthCount {
Year = startDate.Year, Month = startDate.Month, Count = 0 });
}
startDate = startDate.AddMonths(1);
}
This could probably be done more elegantly but it gets the job done.
Thanks to all the answers, this is how I ended up doing it:
DateTime endDate = DateTime.Now;
DateTime startDate = endDate.AddMonths(-Months);
var result = Session.QueryOver<Application>()
.WhereRestrictionOn(c => c.SubmissionDate).IsBetween(startDate).And(endDate)
.SelectList(list => list
.Select(Projections.SqlGroupProjection(
"YEAR(SubmissionDate) As [Year]",
"YEAR(SubmissionDate)",
new[] { "YEAR" },
new IType[] { NHibernateUtil.Int32 }))
.Select(Projections.SqlGroupProjection(
"MONTH(SubmissionDate) As [Month]",
"MONTH(SubmissionDate)",
new[] { "MONTH" },
new IType[] { NHibernateUtil.Int32 }))
.SelectCount(x => x.Id))
.List<object[]>()
.Select(n => new
{
Year = (int)n[0],
Month = (int)n[1],
Count = (int)n[2]
}).ToList();
var finalResult = result
.Union(
Enumerable.Range(0, Months - 1).Select(n => new
{
Year = startDate.AddMonths(n).Year,
Month = startDate.AddMonths(n).Month,
Count = 0
})
.Where(n => !result.Any(r => r.Year == n.Year && r.Month == n.Month)))
.OrderBy(n => n.Year).ThenBy(n => n.Month);

Split a period of time into multiple time periods

If i have a time period, lets say DateFrom and DateTo and I have a list of Dates, These dates will be the split dates. For example:
DateTime dateFrom = new DateTime(2012, 1, 1);
DateTime dateTo = new DateTime(2012, 12, 31);
List<DateTime> splitDates = new List<DateTime>
{
new DateTime(2012,2,1),
new DateTime(2012,5,1),
new DateTime(2012,7,1),
new DateTime(2012,11,1),
};
List<Tuple<DateTime, DateTime>> periods = SplitDatePeriod(dateFrom, dateTo, splitDates);
I want the result to be a list of periods, so for the previous example the result should be:
(01/01/2012 - 01/02/2012)
(02/02/2012 - 01/05/2012)
(02/05/2012 - 01/07/2012)
(02/07/2012 - 01/11/2012)
(02/11/2012 - 31/12/2012)
I have already wrote a method to do that:
List<Tuple<DateTime, DateTime>> SplitDatePeriod(DateTime dateFrom, DateTime dateTo, List<DateTime> splitDates)
{
var resultDates = new List<Tuple<DateTime, DateTime>>();
// sort split dates
List<DateTime> _splitDates = splitDates.OrderBy(d => d.Date).ToList();
DateTime _curDate = dateFrom.Date;
for (int i = 0; i <= _splitDates.Count; ++i)
{
DateTime d = (i < _splitDates.Count) ? _splitDates[i] : dateTo;
// skip dates out of range
if (d.Date < dateFrom.Date || d.Date > dateTo.Date)
continue;
resultDates.Add(Tuple.Create(_curDate, d));
_curDate = d.AddDays(1);
}
return resultDates;
}
The Question
It looks so ugly, Is there more neat and shorter way of doing this? using Linq maybe?
This is one that works and takes care of some edge cases also:
var realDates = splitDates
.Where(d => d > dateFrom && d < dateTo)
.Concat(new List<DateTime>() {dateFrom.AddDays(-1), dateTo})
.Select(d => d.Date)
.Distinct()
.OrderBy(d => d)
.ToList();
// now we have (start - 1) -- split1 -- split2 -- split3 -- end
// we zip it against split1 -- split2 -- split3 -- end
// and produce start,split1 -- split1+1,split2 -- split2+1,split3 -- split3+1,end
realDates.Zip(realDates.Skip(1), (a, b) => Tuple.Create(a.AddDays(1), b));
You can do it like this:
List<DateTime> split =
splitDates.Where(d => d >= dateFrom && d <= dateTo).ToList();
List<Tuple<DateTime, DateTime>> periods =
Enumerable.Range(0, split.Count + 1)
.Select(i => new Tuple<DateTime, DateTime>(
i == 0 ? dateFrom : split[i - 1].AddDays(1),
i == split.Count ? dateTo : split[i]
))
.ToList();
While L.B is correct and this probably belongs on Code Review, I felt like taking a crack at this:
Given Your First Code Block, the following code will do what you're asking for:
// List of all dates in order that are valid
var dateSegments = new [] { dateFrom, dateTo }
.Concat(splitDates.Where(x => x > dateFrom && x < dateTo))
.OrderBy(x => x)
.ToArray();
List<Tuple<DateTime, DateTime>> results = new List<Tuple<DateTime, DateTime>>();
for(var i = 0; i < dateSegments.Length - 1; i++)
{
results.Add(new Tuple<DateTime, DateTime>(dateSegments[i], dateSegments[i+1]));
}
If you put all the dates into a single list, then this should work:
var dates = new List<DateTime>
{
new DateTime(2012, 1, 1),
new DateTime(2012, 2, 1),
new DateTime(2012, 5, 1),
new DateTime(2012, 7, 1),
new DateTime(2012, 11, 1),
new DateTime(2012, 12, 31)
};
var z = dates.Zip(dates.Skip(1), (f, s) => Tuple.Create(f.Equals(dates[0]) ? f : f.AddDays(1), s));
List<DateTime> splitDates = GetSplitDates();
DateTime dateFrom = GetDateFrom();
DateTime dateTo = GetDateTo();
List<DateTime> edges = splitDates
.Where(d => dateFrom < d && d < dateTo)
.Concat(new List<DateTime>() {dateFrom, dateTo})
.Distinct()
.OrderBy(d => d)
.ToList();
//must be at least one edge since we added at least one unique date to this.
DateTime currentEdge = edges.First();
List<Tuple<DateTime, DateTime>> resultItems = new List<Tuple<DateTime, DateTime>>();
foreach(DateTime nextEdge in edges.Skip(1))
{
resultItems.Add(Tuple.Create(currentEdge, nextEdge));
currentEdge = nextEdge;
}
return resultItems;
I have Made it simple to get the Dates between the DateRange provided.
Model Object
public class DateObjectClass
{
public DateTime startDate { get; set; }
public DateTime endDate { get; set; }
}
Action :
public List<DateObjectClass> SplitDateRangeByDates(DateTime start,DateTime end)
{
List<DateObjectClass> datesCollection = new List<DateObjectClass>();
DateTime startOfThisPeriod = start;
while (startOfThisPeriod < end)
{
DateTime endOfThisPeriod =new DateTime(startOfThisPeriod.Year,startOfThisPeriod.Month,startOfThisPeriod.Day,23,59,59);
endOfThisPeriod = endOfThisPeriod < end ? endOfThisPeriod : end;
datesCollection.Add(new DateObjectClass() { startDate= startOfThisPeriod ,endDate =endOfThisPeriod});
startOfThisPeriod = endOfThisPeriod;
startOfThisPeriod = startOfThisPeriod.AddSeconds(1);
}
return datesCollection;
}

Categories