Get days of week by current week - c#

After searching through stack overflow, I cant seem to find a solution. I've put together a chart (Chart.js) and I need to grab days of the current week bind that to the chart and match any days date to one stored in my db thus brining back all data based on that date.
So if anyone could give me any pointers on fetching List from the current week, that would be awesome.
I hope this is clear enough please feel free to ask more questions. Sorry no code struggling to get started. For me DateTime is an absolute nightmare to work with.
Regards,

You can use the DayOfWeek property of DateTime:
new DateTime(2014,11,16).DayOfWeek
So... to deal with a list of dates, first, let's make a list of dates:
var startDate = DateTime.Today;
var endDate = startDate.AddDays(7);
//the number of days in our range of dates
var numDays = (int)((endDate - startDate).TotalDays);
List<DateTime> myDates = Enumerable
//creates an IEnumerable of ints from 0 to numDays
.Range(0, numDays)
//now for each of those numbers (0..numDays),
//select startDate plus x number of days
.Select(x => startDate.AddDays(x))
//and make a list
.ToList();
and get the days of the week:
List<string> myDaysOfWeek = myDates.Select(d => d.DayOfWeek.ToString()).ToList();
if you want the week to start on (say) the previous Monday, you could alter startDate as follows:
startDate = startDate
.AddDays(-(((startDate.DayOfWeek - DayOfWeek.Monday) + 7) % 7));
This works because we can treat the enumeration values of enum DayOfWeek as numbers, so we can subtract Monday(value 1) from Sunday(value 0), which gives -1... then we do a bit of a jiggle to wrap this value to 6 using modulo maths. If you subtract the resulting value (measured in days) from the start date, you end up on the previous Monday.

If you want to know the days of the current week, you need to:
Get the current day
Convert it to an integer
Subtract that many days from the current date. That gives you the date for Sunday.
Create a list, starting with Sunday.
So:
var now = DateTime.Now;
var currentDay = now.DayOfWeek;
int days = (int)currentDay;
DateTime sunday = now.AddDays(-days);
var daysThisWeek = Enumerable.Range(0, 7)
.Select(d => sunday.AddDays(d))
.ToList();

Related

First and Last Day of 4 Weeks in C# DateTime Objects

I'm trying to Get the First and Last Day of 4 Weeks based on the given Date.
For Example:
If the given Date is 8-Jan-2023 then the week start and end should be 1-Jan-2023 and 28-Jan-2023 respectively.
If the given Date is 10-Jan-2023 then the week start and end should be 1-Jan-2023 and 28-Jan-2023 respectively.
If the given Date is 30-Jan-2023 then the week start and end should be 29-Jan-2023 and 25-Jan-2023 respectively.
Basically, the use case depends on the very first input. If the first input is 15-Jan then the first 4 weeks are recorded in the database as 15-Jan to 11-Feb. In that case, 17-Jan belongs to that week
How to do this?
I'm getting the Start Day & end Date of the week as below:
public static DateTime FirstDayOfWeek(this DateTime dt)
{
var culture = Thread.CurrentThread.CurrentCulture;
var diff = dt.DayOfWeek - culture.DateTimeFormat.FirstDayOfWeek;
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-diff).Date;
}
public static DateTime LastDayOfFourWeeks(this DateTime dt) =>
dt.FirstDayOfWeek().AddDays(27);

c# adding correct month based on previous month

I am trying to add a month to a date and populate textboxes based on the previous month. For months that end on the 31st (and even February 28th) this works. But, if the previous month ended on the 30th and the next month ends on the 31st, it is either one day short or one day long. For example:
Previous start date: 4/1/2017
Previous end date: 4/30/2017
New start date: 5/1/2017
New end date: SHOULD BE 5/31/2017
Here is the code I have:
// Set the Start Date
DateTime dtNewStartDate;
dtNewStartDate = Convert.ToDateTime(txtRecentBeginDate.Text).AddMonths(1);
txtNewStartDate.Text = dtNewStartDate.ToString();
// Set the End Date
DateTime dtNewEndDate;
dtNewEndDate = Convert.ToDateTime(txtNewStartDate.Text).AddMonths(1);
txtNewEndDate.Text = dtNewEndDate.ToString();
This produces an end date of 6/1/2017 instead of 5/31/2017
EDIT: I was able to find what I was looking for from https://social.msdn.microsoft.com/Forums/en-US/218260ec-b610-4fa6-9d1b-f56f3438b721/how-to-get-the-last-day-of-a-particular-month?forum=Vsexpressvcs.
This solution accounts for leap years and getting the correct last day of the month for any circumstance. This is what I came up with:
// Set the End Date
int intYear = dtNewStartDate.Year;
int intMonth = dtNewStartDate.Month;
int intNumberOfDays = DateTime.DaysInMonth(intYear, intMonth);
DateTime dtNewEndDate = new DateTime(intYear, intMonth, intNumberOfDays);
txtNewEndDate.Text = dtNewEndDate.ToString();
You can just get the last day of the month for that month.
DateTime today = DateTime.Today;
DateTime endOfMonth = new DateTime(today.Year,
today.Month,
DateTime.DaysInMonth(today.Year,
today.Month));
This is what I typically do: Just take the year and month from the start date, create a new date based on that, add a month and subtract a day which ends up being the last day of the next month::
DateTime dtNewEndDate = new DateTime(dtNewStartDate.Year, dtNewStartDate.Month, 1)
.AddMonths(1)
.AddDays(-1);

Find a date from a specific list of date

I am a beginner in c # and I can not find the solution for my problem.
I am creating a personal project that allows me to send reminders, I have a date list and I need to do tasks between two specific dates in real life.
I found how to get the next date from today's date but I can't find how to get the previous one
Here is my sample code
void calc_x_date()
{
List<string> x_dates = new List<string>();
x_dates.Add("10/01/2017");
x_dates.Add("14/02/2017");
x_dates.Add("14/03/2017");
x_dates.Add("11/04/2017");
x_dates.Add("09/05/2017");
x_dates.Add("13/06/2017");
x_dates.Add("04/07/2017");
x_dates.Add("08/08/2017");
x_dates.Add("12/09/2017");
x_dates.Add("10/10/2017");
x_dates.Add("14/11/2017");
x_dates.Add("12/12/2017");
var allDates = x_dates.Select(DateTime.Parse).OrderBy(d => d).ToList();
var todayDate = DateTime.Today;
var nextDate = todayDate >= allDates.Last()
? allDates.Last()
: todayDate <= allDates.First()
? allDates.First()
: allDates.First(d => d >= todayDate);
string NextDate = nextDate.ToString(); // the closest next date from today
//string PreviousDate = // the closest previous date from today
}
Could someone explain me how to find my previous date please ?
Thanks in advance
I'd suggest using List<T>.BinarySearch: that will find the index of the date. If the index is 0 or more, then the exact date was found. If it's negative, then taking ~index will get you the index where the date would have been inserted.
Once you've got that information, it's easy to find the value at the previous index or the next index - but you should consider all the cases of:
Today is before all dates
Today is after all dates
Today is a date between the first and last date in the list, but isn't in the list
Today is equal to the first date
Today is equal to the last date
Today is equal to a date in the list which isn't the first or last date
As asides:
I would strongly encourage you to get in the habit of following .NET naming conventions as early as possible
I'd encourage you not to use strings to represent dates unless you really need to
If you're doing a lot of date/time work, you may find my Noda Time library easier to use correctly than DateTime
Here is a Linq approach
List<string> x_dates = new List<string>();
x_dates.Add("10/01/2017");
x_dates.Add("14/02/2017");
x_dates.Add("14/03/2017");
x_dates.Add("11/04/2017");
x_dates.Add("09/05/2017");
x_dates.Add("13/06/2017");
x_dates.Add("04/07/2017");
x_dates.Add("08/08/2017");
x_dates.Add("12/09/2017");
x_dates.Add("10/10/2017");
x_dates.Add("14/11/2017");
x_dates.Add("12/12/2017");
DateTime today = DateTime.Today;
IEnumerable<DateTime> dt_dates = x_dates.Select(DateTime.Parse);
DateTime prev = dt_dates.Where(x => x < today)
.OrderByDescending(x => x)
.First();
DateTime next = dt_dates.Where(x => x > today)
.OrderBy(x => x)
.First();
alternative solution
DateTime prev = dt_dates.Where(x => x < today).Max();
DateTime next = dt_dates.Where(x => x > today).Min();
Storing dates in string format works. It is however incredibly difficult to do date comparisons. You have to first cast it to numbers, handle the exceptions, etc.
C# has a DateTime object. You can store dates in this and ignore the time. DateTime objects can be compared using the < and > operators.
If you create a class with a start date and an end date, store these objects in a list(of tasks), would that solve your problem? You can also add a text of the task in a string to said object.

Parse out monthly items from a collection of DateTime objects

I previously asked this question to take a oollection of datetime objects and group them by dayOfweek and time
So just to recap: I take a collection of DateTime
List<DateTime> collectionOfDateTime = GetDateColletion();
and then grouping by dayofWeek and time of day by doing this
var byDayOfWeek = collectionOfDateTime.GroupBy(dt => dt.DayOfWeek + "-" + dt.Hour + "-" + dt.Minute);
So at this point, I have these grouped by week (consistent time) working perfectly.
I now have a new requirement to group by Month instead of by week. When i say "month", its not the same day of the month but something like "the first tuesday of each Month"
I am trying to figure out what "key" to use in a group by to group all items that fit that monthly logic (the first tuesday of the month, the second friday of each month, etc)
As an example lets say i had these dates to start out with;
var date1 = new DateTime(2013, 1, 4).AddHours(8); // This is the first Friday in Jan
var date2 = new DateTime(2013, 2, 1).AddHours(8); // This is the first Friday in Feb
var date3 = new DateTime(2013, 1, 5).AddHours(3); // This is the first Sat in Jan
var date4 = new DateTime(2013, 2, 2).AddHours(3); // This is the first Sat in Feb
var date5 = new DateTime(2013, 2, 2).AddHours(6);  // This is the first Sat in Feb - different time
If these were the dates that went into the original array, i need a groupby to end up with 3 groups.
The first group would have date1 & date2 in it
The second group would have date3 and date4 in it.
date5 would be on its own as it doesn't match any of the other groups given the different time
Can anyone suggest anyway to group by that criteria?
I think it's easier than it looks:
var byDayOfMonth = from d in dates
let h = (d.Day / 7) + 1
group d by new { d.DayOfWeek, h } into g
select g;
Local variable h = (d.Day / 7) + 1 sets which DayOfWeek within that month it actually is.
I run it for test and received 2 groups, exactly the same as in your example. Keys for that groups are:
{ DayOfWeek = Friday, h = 1 }
{ DayOfWeek = Saturday, h = 1 }
What means, there are groups for 'First Friday of month' and 'First Saturday of month'.
You can easily extend grouping key by d.Hour and/or d.Minute if you like:
var byDayOfMonth = from d in dates
let h = (d.Day / 7) + 1
group d by new { d.DayOfWeek, h, d.Hour, d.Minute } into g
select g;
Results (keys only):
{ DayOfWeek = Friday, h = 1, Hour = 8, Minute = 0 }
{ DayOfWeek = Saturday, h = 1, Hour = 3, Minute = 0 }
{ DayOfWeek = Saturday, h = 1, Hour = 6, Minute = 0 }
There is probably an easier way to do this but this is what's come to me:
I gather from your question that you need to group everything from "the first Tuesday of February until the first Monday of March" etc. such that you get these "month" spans that are a variable number of days - depending on the month in which they start. If so then you really need to break this down into ranges using the day of the year so:
Group by the First Wednesday of the Month 2013
Group 0 (0-1)
All DayOfYear between 0 and 1 2013
Group 1 (2-36)
The first Wednesday of the month: January is DayOfYear 2.
The first Wednesday of the month: February is DayOfYear 37.
etc.
So the first range is a function f such that f(32) = 1 (DayOfYear is 32) because it falls in the range 2 to 37. This f is an indexed collection of ranges, finding the item in the collection that a given DayOfYear falls into, and returning that item's index as the group number.
You can dynamically build this table by getting your min and max dates from GetDateCollection to determine the overall range. Because the logic surrounding dates is a pretty complex topic in of itself I'd fall back on a library like NodaTime (specifically the arithmetic documentation), start with the min date, advance day by day until I found the first qualifying day (i.e., "first Monday of the month") and create a range 0 to that day - 1 as group 0 and push that onto an indexed collection (ArrayList likely). Then loop from that date using LocalDate.PlusWeeks(1) until the month changes, constructing a new range and pushing that range onto the same indexed collection.
Each time you cross into a new year you'll have to add 365 (or 366 if the previous year is a leap year) to your DayOfYear as you build your indexed collection since DayOfYear resets each year.
Now you've got a collection of ranges that acts as a table that groups days into the desired units based on their DayOfYear.
Write a function that traverses the table comparing the DayOfYear (+ [365|366] * x where x is the # of years the date you are comparing is from your min year) of a given date against the items in the collection until you locate the range that day falls within, and return that index of that item as the group number. (Alternatively each range could be a Func<DateTime,bool> that returns true if the provided DateTime falls in that range.)
An alternative data structure to the collection of ranges would be an array of ushort with length equal to all the days from min to max dates in your date range, and the value for each day their assigned group number (calculated with ranges, as above). This will perform faster for grouping, though the performance may not be noticeable if you're working with a smaller dataset (only a few hundred dates).
To group by using Linq maybe this code will help you:
List<DateTime> collectionOfDateTime = GetDateColletion();
collectionOfDateTime.GroupBy(s => Convert.ToInt16(s.DayOfWeek) & s.Hour & s.Minute);

Exact c# result of sql datediff

I'm trying to get the number of days (calculated byu datediff) in sql and the number of days in c# (calculated by DateTime.now.Substract) to be the same, but they return different results....
//returns 0
int reso = DateTime.Now.Subtract(expirationDate).Days;
vs
//returns 1
dateDiff(dd,getDate(),ExpirationDate)
In both cases, ExpirationDate is '10/1/2011 00:00:00', and the code and the DB are sitting on the same server. I want the return int to be the same. I suspect I'm missing something stupid... ideas??
dateDiff(dd,getDate(),ExpirationDate) Is doing a days comparison. DateTime.Now.Subtract(expirationDate).Days is doing a date and time
For example
SELECT dateDiff(dd,'10/1/2011 23:59:00' , '10/2/2011') returns one day even when only one minute apart.
If you want the same in C# you need to remove the time component
e.g.
DateTime dt1 = new DateTime(2011,10,1, 23,59,0);
DateTime dt2 = new DateTime(2011,10,2, 0,0,0);
Console.WriteLine((int) dt2.Subtract(dt1.Subtract(dt1.TimeOfDay)));
So in your case it would be something like
DateTime CurrentDate = DateTime.Now;
int reso = CurrentDate.Subtract(CurrentDate.TimeOfDay).Subtract(DateTime.expirationDate).Days;
I haven't tested it but I would not do
DateTime.Now.Subtract(DateTime.Now.Subtract.TimeOfDay)
Because the second call to Now wouldn't be guaranteeing to be the same as first call to Now
In any case Stealth Rabbi's answer seems more elegant anyway since you're looking for a TimeSpan not a DateTime
10/1/2011 is less than 1 day away from DateTime.Now. Since you're getting back a TimeSpan and then applying Days to it, you're getting back a TimeSpan that is < 1 day. So it'll return 0 Days.
Instead, just use the Date component of those DateTimes and it'll correctly report the number of days apart - like this:
DateTime now = DateTime.Now;
DateTime tomorrow = new DateTime(2011, 10, 1);
var val = (tomorrow.Date - now.Date).Days;
This will yield you 1 day.
I'm assuming you want the number of Total days, not the number of days from the largest previous unit. You'd want to use the TotalDays property. Also, you may find it easier to use the minus operator to do a subtraction
DateTime d1 = DateTime.Now;
DateTime d2 = new DateTime(2009, 1, 2);
TimeSpan difference = d1 - d2;
Console.WriteLine(difference.TotalDays); // Outputs (today):1001.46817997424

Categories