Sorting from earliest to latest date - c#

How to loop every month's first date.
public struct stat{
public DateTime date;
}
I have a List<stat> that have a date property. I want to get the lowest and newest one by sorting. the first element is older and last is newer one.
I can easily got the first and second by order by.
What I want is get 1st date of every month in the between of both first (oldest ) and newest.
string ret = "";
List<DateTime> dates = new List<DateTime>();
int breaker = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
stats = stats.OrderBy(x => x.Date).ToList();
DateTime old = stats.First().Date;
DateTime #new = stats.Last().Date;
int diffdays = #new.Subtract(old).Days;
DateTime loopd = DateTime.Now;
for (int i = 0; i < diffdays; i = i + breaker)
{
loopd = loopd.AddDays(-breaker);
dates.Add(loopd);
if (loopd < old)
Console.WriteLine("date" + old);
}
for (int j = 0; j < dates.Count; j++)
{
if (j == 0)
{
DateTime ld= dates[0];
stats.SelectMany(x => x.Date < #new && x.Date > dates[j]);
}
}

I want to get the lowest and newest one by sorting
I assume lowest means oldest.
stat oldest = stats.OrderBy(s => s.date).FirstOrDefault();
stat newest = stats.OrderByDescending(s => s.date).FirstOrDefault();
you could also use
stats.OrderBy(s => s.date).LastOrDefault();
to get the newest.

you could use something like this:
List<stat> statList = new List<stat>();
...
var selectedItem = statList
.OrderBy(item => item.date)
.Select(l => l.last());
or you could use OrderByDecending() instead

Related

Loop through current month to next month in c#

I am facing a problem, logic written in my program is below
DataSet dslsip = mAE_Repo.FetchLastDayCustEmailsEquity_SIP_Content();
var ressip = (from r in dslsip.Tables[0].AsEnumerable() select r.Field<string>("emailid")).ToList();
var resdate = (from r in dslsip.Tables[0].AsEnumerable() select r.Field<DateTime>("a_confirmdatetime")).ToList();
//var datetime = DateTime.Now;
//List<string> date = new List<string>();
//List<DateTime> date = new List<DateTime>();
if (!ReferenceEquals(resdate,null) && resdate.Count>0)
{
for (int i = 0; i < resdate.Count()-1; i++)
{
if (resdate[i].Month == DateTime.Now.Month || resdate[i].Month < DateTime.Now.Month)
{
//Logic should write here
//var das = DateTime.Now.AddMonths(1).ToString("MM");
//var datet = resdate[i].AddMonths(1).ToString("MM");
}
}
}
In the above code 'resdate' variable I'm fetching the list of the dates
And the concept is I should add the month (current next month) Ex: {05-07-2021 00:00:00} I should add the (current month is 9 and next month is 10) so it should be {05-10-2021 00:00:00}
I'm not sure how to add the month only.
I'm new to coding.
Please help me in this.
Use AddMonths() function, example:
new DateTime(DateTime.Now.AddMonths(1).Year,
DateTime.Now.AddMonths(1).Month,
d.Day);
Output:
10/5/2021 12:00:00 AM
10/1/2021 12:00:00 AM
You need to change Month from date list. So, you can do it by using AddMonths() API. Used below Sample :
if (resdate[i].Month == DateTime.Now.Month || resdate[i].Month < DateTime.Now.Month)
{
//Logic should write here
var datet = new DateTime(resdate[i].Year, DateTime.Now.AddMonths(1).Month, resdate[i].Day, resdate[i].Hour, resdate[i].Minute, resdate[i].Second);
}
Here we modified only month data As you wanted.

Linq Overlapped date range checking in single collection

Class TimeRange{
private DateTime StartDate{get; set;}
private DateTime EndDate{get; set;}
}
List<TimeRange> TimeRangeList = new List<TimeRange>(){
new TimeRange(){StartDate = new DateTime(2050, 1, 1),
EndDate = new DateTime(2050, 1, 10)},
new TimeRange(){StartDate = new DateTime(2050, 2, 1),
EndDate = new DateTime(2050, 2, 10)},
//This item will triggered the overlap validation failed
new TimeRange(){StartDate = new DateTime(2050, 1, 5),
EndDate = new DateTime(2050, 1, 9)},
},
}
so after I checked out the similar topic, I still can't figured out the algorithm of checking the overlapped date range.
This is quite simple in SQL, according to Checking for date overlap across multiple date range objects
I just need to compare two date range like this
SELECT COUNT(*)
FROM Table1
WHERE Table1.StartDate < 'endCheckDate'
AND Table1.EndDate > 'startCheckDate'
I found it is difficult to do in Linq, how do we compare all items in one collection within? of cause we can use foreach in just loop the collection just like comparing two list, but how is it work in select?
actually I'm doing something like this
for (int i = 0; i < TimeRangeList .Count(); ++i)
{
var item = TimeRangeList[i];
for (int y = i + 1; y < TimeRangeList.Count(); ++y)
{
var item2 = TimeRangeList[y];
if (IsOverLapped(item, item2))
{
// this is overlapped
};
}
}
private bool IsOverLapped(dynamic firstObj, dynamic secondObj)
{
return secondObj.StartDate <= firstObj.EndDate && firstObj.StartDate <= secondObj.EndDate;
}
Is there a more elegant way to do without looping?
so my questions is how do we compare one single list for each items itself by linq?
A simple brute force idea:
bool overlap = TimeRangeList
.Any(r => TimeRangeList
.Where(q => q != r)
.Any(q => q.EndDate >= r.StartDate && q.StartDate <= r.EndDate) );
If I look at your SQLcode, it seems that you have a Table1 object which is a sequence of similar objects, let's say of class Table1Row. Every Table1Row has at least two DateTime properties, a StartDate and an EndDate. Furthermore you have two DateTime objects: startCheckDate and endCheckDate.
You want to count all elements in your Table1 that have a StartDate smaller than startCheckDate and an EndDate larger than endCheckDate
Written as an extension function of IQueryable:
public static int CountOverlapping(this IQueryable<Table1Row> table1,
DateTime startCheckDate,
DateTime endCheckDate)
{
return table1
.Where (row => row.StartDate < startCheckDate && row.EndDate > endCheckDate)
.Count();
}
Usage:
DateTime startCheckDate = ...
DateTime endCheckDate = ...
IQueryable<Table1Row> table1 = ...
int nrOfOverlapping = table1.CountOverlapping(startCheckDate, endCheckDate);
Simple comme bonjour?

Count row only by date without time using Entity Framework

Check the CountEmailChart carefully. Here I am taking input of DateTime which is fully formatted date with time. But the problem is I want to compare only the date, not time, on Entity Framework below to count number of rows. Can anyone tell me how I can do this?
Controller code:
public int CountEmailChart(DateTime date, int campaignID)
{
int count = dbcontext.CampaignEmails
.Count(x => x.DateSigned == date && x.CampaignID == campaignID);
return count;
}
Karan's answer is correct but resulting query won't use an index for DateSigned. If a such index exist (or combined index for CampaignID and DateSigned columns) you may prefer this approach:
var startDate = date.Date;
var endDate = date.Date.AddDay(1);
int count = dbcontext.CampaignEmails.Count(x => x.CampaignID == campaignID && x.DateSigned >= startDate && x.DateSigned < endDate);
Try like this. .Date property on DateTime object will return only Date part.
If you are using Entity Framework 6 then.
date = date.Date;
int count = dbcontext.CampaignEmails.Count(x => DbFunctions.TruncateTime(x.DateSigned) == date.Date && x.CampaignID == campaignID);
Else
date = date.Date;
int count = dbcontext.CampaignEmails.Count(x => EntityFunctions.TruncateTime(x.DateSigned) == date.Date && x.CampaignID == campaignID);

Parallel.For with date time

OK this code is a bit meta but it roughly explains how i have it now and what i want to achieve.
specialObject{
DateTime date;
int number;
}
var startDate = Lowest date in the list;
var endDate = Hightest date int the list;
List<SpecialObject> objs = (list from database where date > startDate and date < endDate)
//A list with alot of dates and numbers, most of the dates are the same. List contains roughly 1000 items, but can be more and less.
for(var date = startDate; date < endDate; date = date.AddDay(1){
listItem = objs.Where(x => x.Day = date).Sum(x => x.alotOfNUmbers);
}
Now since i don't care what day i calculate first, i thought i could do this.
Parallel.For(startDate, endDate, day => {
listItem = objs.Where(x => x.Day = date).Sum(x => x.alotOfNUmbers);
}
But how do i make it step dates ?
You can make a Range and iterate over it with Parallel.ForEach :
// not tested
var days = Enumerable
.Range(0, (endDate-startDate).Days) // check the rounding
.Select(i => startDate.AddDays(i));
Parallel.ForEach(days, day => ....)
Alternatively, you could use PLinq over the original source, probably faster. Roughly:
// not tested
var sums = objs.AsParallel().GroupBy(x => x.date).Select(g => g.Sum(i => i.number));
All the overloads of Parallel.For take two integer variables for start and end. I also don't see any version which would support something like a step so you can't just use the tick count of a DateTime as the loop variable.
But it should be easy to use a Parallel.ForEach instead, when you create an IEnumerable<DateTime> as the source sequence.
var source = Enumerable.Range(0, (endDate - startDate).Days)
.Select(t => startDate.AddDays(t));
Add +1 to the count parameter if the endDate is inclusive.
Ok after a few days search i figured if i placed all days in an array and "whiled" through it. It gives a pretty good result. With code easy to read
var start = new DateTime(2014, 09, 09);
var end = new DateTime(2014, 10, 01);
var listOfDays = new List<DateTime>();
int i = 0;
for (var day = start; day < end; day = day.AddDays(1))
{
listOfDays.Add(day);
}
Parallel.ForEach(listOfDays.ToArray(), currentDay =>
{
for (var d = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 0, 0, 0); d < new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 23, 59, 59); d = d.AddSeconds(5))
{
var str = "Loop: " + i + ", Date: " + d.ToString();
Console.WriteLine(str);
}
i++;
});
Console.Read();

All Sundays in month, this month has no Sundays yet,issue

I have this code, it failed because thisMonthSundays are empty:
public ActionResult TradeUKKPISearchesData() //show dropdownlist in the view
{
var now = DateTime.Now;
var lastMonth = now.AddMonths(-1);
var thisMonthSundays = GetDatesOfSundays(now.Year, now.Month).OrderByDescending(x => x.Date);
var lastMonthSundays = GetDatesOfSundays(lastMonth.Year, lastMonth.Month).OrderByDescending(x => x.Date); //problem here, must add some sort of check here?
var sundaysToTakeFromLastMonth = 4;
var sundays = thisMonthSundays.Concat(lastMonthSundays.Skip(Math.Max(0, lastMonthSundays.Count() - sundaysToTakeFromLastMonth)).Take(sundaysToTakeFromLastMonth));
var allSundaysInThisMonth = new SundaysInMonthViewModel
{
AllSundays = sundays.Select(x => new SelectListItem
{
Value = x.ToString("dd/MM/yyyy"),
Text = x.ToString("dd/MM/yyyy"),
})
};
var selectedSunday = new SundaysInMonthViewModel
{
SelectedSunday = thisMonthSundays.Where(x => x <= now).Last() //failed here
};
return View(allSundaysInThisMonth);
}
private IEnumerable<DateTime> GetDatesOfSundays(int year, int month)
{
var ci = CultureInfo.InvariantCulture;
for (int i=1; i <= ci.Calendar.GetDaysInMonth(year, month); i++)
{
var date = new DateTime(year, month, i);
if ((date.DayOfWeek == DayOfWeek.Sunday) && (date <= DateTime.Now))
{
yield return date; //skips all for this month
}
}
}
I need to fix this, please help with ideas?
thanks
As the Octobar month do not have SUnday so far, the variable SelectedSunday is empty....
You can use LastOrDefault() instead :
SelectedSunday = thisMonthSundays.Where(x => x <= now).LastOrDefault() ;
Note : The Default value for DateTime Type is DateTime.Min which is 1/1/0001 12:00:00 AM.
There are some mistakes in your code here.
Using var is not something you want to do everywhere.
You should never use arbitrary values in your functions. Instead of checking that the days are prior to today, you should add a limit parameter to your function and pass DateTime.Now
on the call.
Your function is already returning all the Sundays of a given month that are prior to today. Your Linq Request is just a replication of code and will return the whole collection every-time.
Since today is 10-01 and that we are Monday, there is no Sundays on October prior to today. This is why your collection is empty.

Categories

Resources