I have data starting from date 01/02/2011 and get updated every day.
i want to format data using week starting from date 01/02/2011.
I have entities
public DateTime? MeasurementDate { get; set; }
FORMAT OF DATE:2011-02-01 00:00:00.0000000
Which gives me date from database ..
I want to group data in linq BY Week?
Can You help me?
If you're using Linq-To-Entities you can do:
source.GroupBy(x => SqlFunctions.DatePart("ww", x.MeasurementDate));
Use the GetWeekOfYear method of the Calendar class
var dt = new List<DateTime?> { /*...*/ };
var dfi = DateTimeFormatInfo.CurrentInfo;
var ordered = dt
.Where(x => x.HasValue)
.OrderBy(x => dfi.Calendar.GetWeekOfYear(x.Value, CalendarWeekRule.FirstDay, DayOfWeek.Monday));
Or you can get the date of the first day in the week then group by that date.
To get the date of the first day in the week.
you can use this code:
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = dt.DayOfWeek - startOfWeek;
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-1 * diff).Date;
}
}
then you can group by the first date of the week like this:
source.GroupBy(i => i.MeasurementDate.StartOfWeek(DayOfWeek.Monday));
reference
Related
I have to select and group by because I need to get the average and sum of some items, my problem is first of all the group by is based on month(m_date.Month) so inside the group by I don't have access to year anymore, my second problem is what if I want to have other properties from statisticsDaily class in my query? with this query I only have access to grouped by fields, look at below:
var rslt = await (from d in db.statMonth.Include(f=>f.MasterData).Where(d=>d.m_turbine_id == IPAddress.Parse(id) && d.m_date >= frm)
group d by d.m_date.Month into g
select new statisticsDaily
{
Date = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key),
Production = g.Sum(s => s.m_energy_prod),
m_wind_speed = g.Average(s => s.m_wind_speed),
Availability = g.Average(s => s.m_availability),
}
).OrderBy(s=>s.Date).ToListAsync();
my statsticDaily class is :
public class statisticsDaily
{
public string Date { get; set; }
public Nullable<float> Production { get; set; }
public Nullable<float> m_wind_speed { get; set; }
public Nullable<float> Availability { get; set; }
public string Comments { get; set; }
public string TurbineId { get; set; }
public string Countries { get; set; }
}
This is exactly how group by works. If you need to access Year too so you need to group by Month and Year together:
var rslt = await (from d in db.statMonth.Include(f=>f.MasterData).Where(d=>d.m_turbine_id == IPAddress.Parse(id) && d.m_date >= frm)
group d by new { d.m_date.Month, d.m_date.Year} into g
select new statisticsDaily
{
Year = g.Key.Year// We can access Year now since we grouped by Year as well
Date = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key.Month),
Production = g.Sum(s => s.m_energy_prod),
m_wind_speed = g.Average(s => s.m_wind_speed),
Availability = g.Average(s => s.m_availability),
}
).OrderBy(s=>s.Date).ToListAsync();
See: Using group by on multiple columns
On the other, You can access to list of other properties as g.ToList() when you group by items. See: LINQ Group By and select collection
Every StatMonth has a property m_Date. Your GroupBy makes groups of StatMonths that have equal value for m_Date.Month.
So the StatMonth with an m_Date in February 2019 will be in the same Group as all StatMonth with an m_Date in Februari 2020 and Februari 2018.
You wrote:
...so inside the group by I don't have access to year anymore,
It depend on what you want to do with the Year.
Do you want to make groups of StatMonths with m_Date in the same month of the same year? So do you want to make a group of StatMonths of 2019-02, 2019-03, 2019-04, ..., 2020-02, 2020-03, etc?
Or do you want to make a February group of sub groups: the 2019 sub group, the 2020 sub group, etc. And similarly a March group with 2019 sub group, 2020 sub group.
If you look at the generic method syntax of GroupBy, you'll see the following:
var result = db.StatMonths
.Where(...)
.GroupBy(
// parameter KeySelector: I want to make Groups of StatMonths that have the
// same value for this key:
statMonth => ... // this will be the key,
// for example: groups with same Year/Month combination of m_Date
statMonth => new
{
Year = statMonth.m_Date.Year,
Month = statMonth.m_Date.Month,
},
// parameter resultSelector, for every Key, and all StatMonths that have this key
// make one new object:
(yearMonthCombination, statMonthsWithThisYearMonthCombination) => new ...
}
So in parameter resultSelector, you get the key, and all items that have this key. So if you need groups with same year/month combination, create a key as above. If you want to make groups with the same month for all years, and subgroups per year:
// parameter keySelector: make groups with same month, for all year:
statMonth => stathMonth.m_Date.Month,
// parameter resultSelector: take the key and all statMonths with this key to make a new
(month, statMonthsWithThisMonth) => new
{
Month = month,
SubGroups = statMonthsWithThisMonth.GroupBy(
// make subgroups with same Year,
// all statMonths in this group already have the same month
statMonth => statMonth.m_Date.Year,
// parameter resultSelector: use the year, and all statMonths of the group
// with this year
(year, statMonthisWithThisYear) => new
{
Year = year,
... // other statMonth
})
})
You didn't say what you wanted to do other than in your example, so I don't know whether it is better to make a sequence of groups with same year/month combination or a sequence with same month of sub groups with same year.
IMHO the later makes it more difficult to see what happens without adding much functionality.
I am using Linq to retrive 1 year worth of data from sql server based on a ID. Then I have to iterate through all the rows and convert the Timestamp to epoch format but it is taking too long to do so. What is the optimized way of doing that?
dt = DateTime.Now.AddMonths(-12);
var allData = obj.tableName.Where(m => m.AssetId == id&& m.CreatedDateTime >
dt).OrderBy(m => m.CreatedDateTime);
foreach (var eachDataRow in allData){
double date = ToUnixEpoch(eachDataRow.CreatedDateTime);
//then save date in an array
}
The above sample code is doing eerything correctly but taking over 30 secs to finish the job. I have around 200000 data points.
Should I not use linq? what is the best way to do this?
Linq is for querying, not for working. System.Threading.Tasks.Parallel provides support for parallel loops and regions. I think this is what you're searching for:
static void Main(string[] args)
{
IQueryable<MyClass> tmp = new List<MyClass>().AsQueryable<MyClass>();
Parallel.ForEach(tmp, ConvertIfNeeded); // here the magic is happening. Put in your list and the method to be run
}
public class MyClass // some dummy-class to work with
{
public DateTime CreatedDateTime { get; set; }
}
static readonly DateTime dt = DateTime.Now.AddMonths(-12);
public static void ConvertIfNeeded(MyClass t) // static function to be used in out parallel work
{
if (t.CreatedDateTime > dt)
t.CreatedDateTime = ToUnitEpoch(t.CreatedDateTime);
}
System.Threading.Tasks.Parallel#MSDN
guys!
I have a small issue with LINQ (Im total beginer in this topic). Maybe it is some desing mistake, but let you decide it.
I'm coding a Windows Store App, which is kind a calendar. It has a Day object. Because of the semantic zoom (and some groupping hack), I put this Day into a wrapper class, named as Month.
After loading all data, and after getting the current data, I want to extract from this structure the current Day object.
Here is the important code:
public class Day
{
public int nr { get; set; }
...
}
public class Month
{
public string Title {get;set;}
public List<Day> Days{get;set;}
}
Later I have this:
List<Month> Months;
It is correctly filled with lists of days. Now comes the tricky part:
Day Today = Months.Find( ??? )
I had some idea, but none of them was statisfying...
So, the question is:
How can I select an item from a multiple list hierarchy in LINQ?
(List<List<Day>>, and one condition must met in each list (Day.nr and Month.nr))
Create an Enum for every month:
public enum NamesOfMonths
{
January = 1,
February = 2,
// so on and so forth
}
Now, you can use it to find the correct Month, and eventually the correct Day.
var dayToday = DateTime.Now.Day;
var monthToday = DateTime.Now.Month;
Day Today = Months.Find(m => m.Title.Equals(((NamesOfMonths)monthToday).ToString()))
.Days.Where(d => d.Nr == dayToday).FirstOrDefault();
I think you're looking for SelectMany:
var days = months.SelectMany(m => m.Days); // Gets all the days in those months
var today = days.Where(d => /* some condition goes here */);
I have a datetime field in a database which when retrieved should only display the date without the time. Can you please let me know how to do it? Here is the query I wrote:
var queryProductEventCustomers = (from r in DbContext.ProductEventCustomers
from s in DbContext.CustomerProducts
where r.Customers_Id == customerID && r.Customers_Id
== s.Customers_Id && s.Products_Id == productID
select new
{
r.Id,
r.Customers_Id,
r.StartTime
The starttime is a datetime field. So, can you please let me know how to do it?
Use the Short Date format:
r.StartTime.ToString("d", DateTimeFormatInfo.InvariantInfo)
http://msdn.microsoft.com/en-us/library/az4se3k1.aspx
The link shows you how to work with all standard date and time formats.
Use the ToShortDateString() method on DateTime.
select new
{
Id = r.Id,
Customers_Id = r.Customers_Id,
Date = r.StartTime.ToShortDateString()
}
Just choose the date portion:
select new
{
Id = r.Id,
Cust_id = r.Customers_Id,
Date = r.StartTime.Date
}
Try this
select new
{
ID = r.Id,
CustomerID = r.Customers_Id,
StartDate = r.StartTime.ToString("dd/MM/yyyy")
}
I am tring to get a list of dates from my db that will eventually be used to populate a calendar. Each 'calendar event' has a start date & end date, i need to get all dates between & including the start & end date.
i am stuck on the WHERE statement, as i am not sure what to use for this
public List<EventFeed> GetCalendarDates()
{
return (from eventsList in GetEventsList()
select new EventFeed()
{
//EventDate = todo
}).ToList();
}
UPDATE
just to be clear, if i have a calendar event called foobar which starts on 22/08/2010 and ends on 24/08/2010, then i want my list return:
22/08/2010,
23/08/2010,
24/08/2010
thanks
kb
I had to do something similar recently, I used a Func<> to extract the dates from the range and used the result in the linq query.
I have added the same Func to your Linq query below. You didn't specify the name of the object that is returned by GetEventsList() so just replace the EventItem type for the first type parameter in the Func<> with whatever type you need.
public static List<EventFeed> GetCalendarDates()
{
Func<EventItem, List<DateTime>> extractEventDates = eventItem =>
{
var dates = new List<DateTime>();
for (var date = eventItem.StartDate;
date <= eventItem.EndDate;
date = date.AddDays(1))
{
dates.Add(date);
}
return dates;
};
return (from eventItem in GetEventsList()
from eventDate in extractEventDates(eventItem)
select new EventFeed
{
EventDate = eventDate
}).ToList();
}
You mean you want to select all the events that started on or after start date and ended on or before end date!
If yes, then this will help
var query = from #event in events
where #event.Start.Date >= startDate.Date
&& #event.End.Date <= endDate.Date
select #event;