Get Date of every alternate Friday - c#

I am wondering if i can get the date of every alternate friday starting with 13th of April, 2012 to give it as a parameter to a stored procedure using c#, asp.net?
It should also be most recently passed date. Thank you!

Just set a DateTime with the date you want to start at, and then keep adding 14 days:
So to get every other Friday after 4/13 until the end of the year:
DateTime dt = new DateTime(2012, 04, 13);
while (dt.Year == 2012)
{
Console.WriteLine(dt.ToString());
dt = dt.AddDays(14);
}
More info after comment:
If you want the most recent alternate Friday since 2012/04/13, you can compute the number of days between now and 2012/04/13, take the remainder of that divided by 14, and subtract that many days from today's date:
DateTime baseDate = new DateTime(2012, 04, 13);
DateTime today = DateTime.Today;
int days = (int)(today - baseDate).TotalDays;
int rem = days % 14;
DateTime mostRecentAlternateFriday = today.AddDays(-rem);

You can easily make a generator method that would give you the set of fridays:
public IEnumerable<DateTime> GetAlternatingFridaysStartingFrom(DateTime startDate)
{
DateTime tempDate = new DateTime(startDate.year, startDate.Month, startDate.Day);
if(tempDate.DayOfWeek != DayOfWeek.Friday)
{
// Math may be off, do some testing
tempDate = tempDate.AddDays((7 - ((int)DayOfWeek.Friday - (int)tempDate.DayOfWeek) % 7);
}
while(true)
{
yield return tempDate;
tempDate = tempDate.AddDays(14);
}
}
Then, simply use some LINQ to determine how much you want:
var numberOfFridays = GetAlternatingFridaysStartingFrom(DateTime.Today).Take(10);

Why do you need a stored proc?
If you have a date that is Friday, why not just use AddDays(14) in a loop?
If you want to find the nearest Friday from a start date, just use this:
while(date.DayOfWeek != DayOfWeek.Friday)
{
date.AddDays(1);
}
Then use the 14 day loop to get every other Friday.

You can create simple method that will enumerate them like so:
public static IEnumerable<DateTime> GetAlternatingWeekDay(DateTime startingDate)
{
for (int i = 1; ; i++)
{
yield return startingDate.AddDays(14*i);
}
}
Which you can call like this:
DateTime startingDate = DateTime.Parse("2012-04-13");
foreach (var date in GetAlternatingWeekDay(startingDate).Take(10))
{
Console.WriteLine(date.ToString("R"));
}
Alternately, if you need to know the date for a given number of weeks out, you could use code like this:
DateTime date = DateTime.Parse("2012-04-13").AddDays(7 * numberOfWeeks);

Related

How to set DateTime to start/end of the day?

I want to calculate the start DateTime and end DateTime of the current week. First of all I created a class holding both information
internal class ReportTimeSpan
{
public DateTime From { get; set; }
public DateTime To { get; set; }
}
After that this is my calculation
public ReportTimeSpan GetTimeSpanForThisWeek()
{
int amountOfDays = GetAmountOfWeekDays();
int currentDayIndex = GetCurrentWeekDayIndex();
DateTime weekStart = DateTime.Now.AddDays(-currentDayIndex);
int differenceCurrentDayIndexToLastDayIndex = amountOfDays - currentDayIndex;
DateTime weekEnd = DateTime.Now.AddDays(differenceCurrentDayIndexToLastDayIndex);
return new ReportTimeSpan()
{
From = weekStart,
To = weekEnd
};
}
private int GetAmountOfWeekDays()
{
string[] dayNames = Enum.GetNames(typeof(DayOfWeek));
return dayNames.Length;
}
private int GetCurrentWeekDayIndex()
{
DayOfWeek dayOfWeek = DateTime.Now.DayOfWeek;
return (int)dayOfWeek;
}
}
The date of both values is correct, but the time is wrong.
The variable weekStart should have a time of "00:00:00"
The variable weekEnd should have a time of "23:59:59" (not sure about that)
Are there any methods I can use for this? (I don't want to use external packages)
I expect you want something like this:
weekStart = DateTime.Now.AddDays(-currentDayIndex).Date;
As Tim notes, you can simplify this to:
weekStart = DateTime.Today.AddDays(-currentDayIndex);
.Date will remove the time component, so you're just left with the date and a 00:00:00 time. .Today will return today's date without a time component.
For weekEnd, we should add the number of days in the week to weekStart, and then step back 1 tick to take it back into the previous day:
weekEnd = weekStart.AddDays(7).AddTicks(-1);
You could also use .AddMilliseconds(-1), .AddSeconds(-1), or whatever amount you require to safely be inside the previous day (some databases will have less than tick precision, etc.).
If you have some reason for using GetAmountOfWeekDays() then substitute 7 in the above with GetAmountOfWeekDays().
Depending on what you're using this for, you might be better off with an inclusive weekStart and an exclusive nextWeekStart comparison:
weekStart = DateTime.Now.AddDays(-currentDayIndex).Date;
nextWeekStart = weekStart.AddDays(7);
bool isInWeek = someDate >= weekStart && somedate < nextWeekStart;
weekStart = weekStart.Date;
weekEnd = weekEnd.AddHours(23).AddMinutes(59).AddSeconds(59).AddMilliseconds(999);
OR
weekStart = weekStart.Date;
weekEnd = weekEnd.AddHours(24).AddMilliseconds(-1);
OR
weekStart = weekStart.Date;
weekEnd = new DateTime(weekEnd .Year, weekEnd .Month, weekEnd .Day, 23, 59, 59);

How do I handle datetime with no day in a linq comparison?

I am given two dates as strings like this:
Beginning month: 10
Beginning year: 2010
Ending month: 01
Ending Year 2020
I want to query my entity and get everything that is equal or between these ranges.
So, I want everything from 10/2010 to 01/2020.
I have this code and I got stuck on how to convert the date correctly and the comparison:
dollartotals = (from x in se.AchBatches
where x.CompanyCode == company &&
DbFunctions.TruncateTime(x.DateTimeSubmitted) >=
// stuck here
select x.DollarTotal).Sum();
How do I handle the individual month/year strings and make a date comparison without a day?
Thanks for any assistance!
You want to check against the actual datetime submitted, not a truncated version of it.
The key is to build actual datetimes in advance, then just do a regular date window check.
Assume you have four strings as listed in your question:
//you might use TryConvert or a Try block here to validate your string data...
int beginYear = Integer.Convert(strBeginYear);
int beginMonth = Integer.Convert(strBeginMonth);
int endYear = Integer.Convert(strEndYear);
int endMonth = Integer.Convert(strEndMonth);
DateTime start = new DateTime(beginYear, beginMonth, 1);
DateTime endLimit = new DateTime(endYear, endMonth, 1).AddMonths(1);
dollartotals = (from x in se.AchBatches
where x.CompanyCode == company &&
x.DateTimeSubmitted >= start &&
x.DateTimeSubmitted < endLimit
select x.DollarTotal).Sum();
I want everything from 10/2010 to 01/2020.
Not sure if you want a DateTime sequence with every Tick between those dates, or every second, or every Day. Let's assume you want every Day: All Days from startDate.Date until and inclusive endDate.Date.
I use StartDate.Date, so if StartDate is 2020-02-05 13:20:14, then you still get February 5th 2020 at 00:00:00
IEnumerable<DateTime> GetDateRange(DateTime startDate, DateTime endDate)
{
DateTime lastDate = endDate.Date;
DateTime date = startDate.Date;
while (date <= lastDate)
{
yield return date;
date = date.AddDays(+1);
}
}
Usage:
var allDaysOfFebruary2020 = GetDateRange(new DateTime(2020, 01, 01),
new DateTime(2020, 02, 29));
You'll get the sequence from 1st February 2020 until and inclusive 29th February 2020.

Get DateTime of the next nth day of the month

If given a date and a variable n, how can I calculate the DateTime for which the day of the month will be the nth Date?
For example, Today is the 17th of June.
I would like a function that when provided 15 would return the DateTime for July 15.
A few more examples:
Today is Feb. 26: Function would return March 30 when provided 30.
Today is Dec. 28. Function would return Jan 4 when provided 4.
Today is Feb. 28. Function would return March 29 when provided 29, unless it was a leap year, in which case it would return Feb 29.
Why not just do?
private DateTime GetNextDate(DateTime dt, int DesiredDay)
{
if (DesiredDay >= 1 && DesiredDay <= 31)
{
do
{
dt = dt.AddDays(1);
} while (dt.Day != DesiredDay);
return dt.Date;
}
else
{
throw new ArgumentOutOfRangeException();
}
}
After many, many edits, corrections and re-writes, here is my final answer:
The method that follows returns a a DateTime representing the next time the day of number day comes up in the calendar. It does so using an iterative approach, and is written in the form of an extension method for DateTime objects, and thus isn't bound to today's date but will work with any date.
The code executes the following steps to get the desired result:
Ensure that the day number provided is valid (greater than zero and smaller than 32).
Enter into a while loop that keeps going forever (until we break).
Check if cDate's month works (the day must not have passed, and the month must have enough days in it).
If so, return.
If not, increase the month by one, set the day to one, set includeToday to true so that the first day of the new month is included, and execute the loop again.
The code:
static DateTime GetNextDate3(this DateTime cDate, int day, bool includeToday = false)
{
// Make sure provided day is valid
if (day > 0 && day <= 31)
{
while (true)
{
// See if day has passed in current month or is not contained in it at all
if ((includeToday && day > cDate.Day || (includeToday && day >= cDate.Day)) && day <= DateTime.DaysInMonth(cDate.Year, cDate.Month))
{
// If so, break and return
break;
}
// Advance month by one and set day to one
// FIXED BUG HERE (note the order of the two calls)
cDate = cDate.AddDays(1 - cDate.Day).AddMonths(1);
// Set includeToday to true so that the first of every month is taken into account
includeToday = true;
}
// Return if the cDate's month contains day and it hasn't passed
return new DateTime(cDate.Year, cDate.Month, day);
}
// Day provided wasn't a valid one
throw new ArgumentOutOfRangeException("day", "Day isn't valid");
}
The spec is a little bit unclear about to do when today is the dayOfMonth. I assumed it was it to return the same. Otherwise it would just be to change to <= today.Day
public DateTime FindNextDate(int dayOfMonth, DateTime today)
{
var nextMonth = new DateTime(today.Year, today.Month, 1).AddMonths(1);
if(dayOfMonth < today.Day){
nextMonth = nextMonth.AddMonths(1);
}
while(nextMonth.AddDays(-1).Day < dayOfMonth){
nextMonth = nextMonth.AddMonths(1);
}
var month = nextMonth.AddMonths(-1);
return new DateTime(month.Year, month.Month, dayOfMonth);
}
Stumbled upon this thread today while trying to figure out this same problem.
From my testing, the following seems to work well and the loop only needs two goes (I think? Maybe 3 max(?)) to get to the answer:
public static DateTime GetNearestSpecificDay(DateTime start, int dayNum)
{
if (dayNum >= 1 && dayNum <= 31)
{
DateTime result = start;
while (result.Day != dayNum)
result = dayNum > result.Day ? result.AddDays(dayNum - result.Day) : new DateTime(result.Month == 12 ? result.Year + 1 : result.Year, (result.Month % 12) + 1, 1);
return result;
}
else
return DateTime.Today;
}
Edit: As requested, here's a less compact version that walks through the logic step by step. I've also updated the original code to account for a required year change when we reach December.
public static DateTime GetNearestSpecificDay(DateTime start, int dayNum)
{
// Check if target day is valid in the Gregorian calendar
if (dayNum >= 1 && dayNum <= 31)
{
// Declare a variable which will hold our result & temporary results
DateTime result = start;
// While the current result's day is not the desired day
while (result.Day != dayNum)
{
// If the desired day is greater than the current day
if (dayNum > result.Day)
{
// Add the difference to try and skip to the target day (if we can, if the current month does not have enough days, we will be pushed into the next month and repeat)
result = result.AddDays(dayNum - result.Day);
}
// Else, get the first day of the next month, then try the first step again (which should get us where we want to be)
else
{
// If the desired day is less than the current result day, it means our result day must be in the next month (it obviously can't be in the current)
// Get the next month by adding 1 to the current month mod 12 (so when we hit december, we go to january instead of trying to use a not real 13th month)
// If result.Month is November, 11%12 = 11; 11 + 1 = 12, which rolls us into December
// If result.Month is December, 12%12 = 0; 0 + 1 = 1, which rolls us into January
var month = (result.Month % 12) + 1;
// Get current/next year.
// Since we are adding 1 to the current month, we can assume if the previous month was 12 that we must be entering into January of next year
// Another way to do this would be to check if the new month is 1. It accomplishes the same thing but I chose 12 since it doesn't require an extra variable in the original code.
// Below can be translated as "If last result month is 12, use current year + 1, else, use current year"
var year = result.Month == 12 ? result.Year + 1 : result.Year;
// Set result to the start of the next month in the current/next year
result = new DateTime(year, month, 1);
}
}
// Return result
return result;
}
else
// If our desired day is invalid, just return Today. This can be an exception or something as well, just using Today fit my use case better.
return DateTime.Today;
}
Fun little puzzle. I generated 100 DateTimes which represent the starting day of each month, then checked each month to see if it had the date we want. It's lazy so we stop when we find a good one.
public DateTime FindNextDate(int dayOfMonth, DateTime today)
{
DateTime yesterday = today.AddDays(-1);
DateTime currentMonthStart = new DateTime(today.Year, today.Month, 1);
var query = Enumerable.Range(0, 100)
.Select(i => currentMonthStart.AddMonths(i))
.Select(monthStart => MakeDateOrDefault(
monthStart.Year, monthStart.Month, dayOfMonth,
yesterday)
.Where(date => today <= date)
.Take(1);
List<DateTime> results = query.ToList();
if (!results.Any())
{
throw new ArgumentOutOfRangeException(nameof(dayOfMonth))
}
return results.Single();
}
public DateTime MakeDateOrDefault(
int year, int month, int dayOfMonth,
DateTime defaultDate)
{
try
{
return new DateTime(year, month, dayOfMonth);
}
catch
{
return defaultDate;
}
}

Difference between times entered as text

i am new to c# and i have been trying to create a code that shows the total number of hours worked..eg a person working from 8am to 4pm means he works 8 hrs a day.
i want a code that shows how many hours he worked.
i tried for loop but i am not getting it right..
please help me out
int from = Convert.ToInt32(frA.Text);
int to = Convert.ToInt32(toA.Text);
for (from = 0; from <= to; from++)
{
totalA.Text = from.ToString();
}
A loop isn't what you need here. You could use DateTime and a Timespan:
DateTime start = new DateTime(2013, 07, 04, 08,00, 00);
DateTime end = new DateTime(2013, 07, 04, 16,00, 00);
TimeSpan ts = end - start;
Console.Write(ts.Hours);
Here I create two DateTime objects for today (04/07/2013). One has the start time of 08:00 and the end time 16:00 (4pm).
The Timespan object ts subtracts these dates, you can then use the .Hours property.
You first have to convert the string to int, then you can initialize a TimeSpan struct:
int from, to;
if (int.TryParse(frA.Text, out from) && int.TryParse(toA.Text, out to))
{
if (to <= from)
MessageBox.Show("To must be greater than From.");
else
{
TimeSpan workingHours = TimeSpan.FromHours(to - from);
// now you have the timespan
int hours = workingHours.Hours;
double minutes = workingHours.TotalMinutes;
// ...
}
}
else
MessageBox.Show("Please enter valid hours.");
You don't really need the TimeSpan here, you could also use the int alone. Used it anyway to show that it allows to provide other properties like minutes or second.
If that inputs can be taken to DateTime, then you can do it like the following line of code
double totalHours = (DateTime.Now - DateTime.Now).TotalHours;

Function to determine first day of a month, last day of a month, etc.

I'm creating a scheduler and need to be able to do the following in C#:
Find the 1st Tuesday of June 2012
Find the last Friday of March 2008
Find every Saturday in January 2013
Find the 3rd Friday in July 2009
Find every Saturday over the next 3 months
Find every day in March 2018
The results should come back as DateTime or List<DateTime>.
Here are methods to find the first/last specified day of week in a given month:
public DateTime GetFirstDayOfWeekInMonth(int year, int month, DayOfWeek dayOfWeek)
{
DateTime dt = new DateTime(year, month, 1);
int first = (int)dt.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted < first)
wanted += 7;
return dt.AddDays(wanted - first);
}
public DateTime GetLastDayOfWeekInMonth(int year, int month, DayOfWeek dayOfWeek)
{
int daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month);
DateTime dt = new DateTime(year, month, daysInMonth);
int last = (int)dt.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted > last)
last += 7;
return dt.AddDays(wanted - last);
}
From those, you can easily find the answers to the other questions... just add 7 days to find the next occurence of the day you're looking for
EDIT: thinking more about it, it would be pretty handy to have that in the form of extension methods, such as :
Console.WriteLine("Next monday : {0}", DateTime.Today.Next(DayOfWeek.Monday));
Console.WriteLine("Last saturday : {0}", DateTime.Today.Previous(DayOfWeek.Saturday));
Here is the implementation :
public static class DateExtensions
{
public static DateTime Next(this DateTime from, DayOfWeek dayOfWeek)
{
int start = (int)from.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted < start)
wanted += 7;
return from.AddDays(wanted - start);
}
public static DateTime Previous(this DateTime from, DayOfWeek dayOfWeek)
{
int end = (int)from.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted > end)
end += 7;
return from.AddDays(wanted - end);
}
}
It's probably more flexible than the first methods I suggested... With that, you can easily do things like that :
// Print all Sundays between 2009/01/01 and 2009/03/31
DateTime from = new DateTime(2009, 1, 1);
DateTime to = new DateTime(2009, 3, 31);
DateTime sunday = from.Next(DayOfWeek.Sunday);
while(sunday <= to)
{
Console.WriteLine(sunday);
sunday = sunday.AddDays(7);
}
Inspired by this question it seemed like a fun thing to make something that allows you to treat dates as sequences and query them with LINQ. I've made a simple project that can be downloaded here from GitHub. Don't know if it was necessary to add it to source control as I doubt I'll be working on it, but had to upload it somewhere and uploading it to RapidShare seemed a little dodgy :)
Your first questions solved with my "Linq-to-DateTime":
/*
* 1. Find the 1st Tuesday of June 2012
2. Find the last Friday of March 2008
3. Find every Saturday in January 2013
4. Find the 3rd Friday in July 2009
5. Find every Saturday over the next 3 months
6. Find every day in March 2018
*/
var firstTuesday = (from d in DateSequence.FromYear(2012).June()
where d.DayOfWeek == DayOfWeek.Tuesday
select d).First();
var lastFriday = (from d in DateSequence.FromYear(2008).March()
where d.DayOfWeek == DayOfWeek.Friday
select d).Last();
var saturdays = (from d in DateSequence.FromYear(2013).January()
where d.DayOfWeek == DayOfWeek.Saturday
select d);
var thirdFriday = (from d in DateSequence.FromYear(2009).July()
where d.DayOfWeek == DayOfWeek.Friday
select d).Skip(2).First();
var nextSaturdays = (from d in DateSequence.FromDates(DateTime.Today, DateTime.Today.AddMonths(3))
where d.DayOfWeek == DayOfWeek.Saturday
select d);
var allDays = (from d in DateSequence.FromYear(2018).March()
select d);
Not shown in this example is that you can choose the granularity of your queries. Meaning that if you do this:
var days = (from d in DateSequence.FromYears(2001, 2090).AsYears()
where d.Year % 2 == 0
select d.Year).ToList();
You will iterate through the dates with an increment of a year. The default is AsDays() if you don't specify anything.
The project is pretty barebone, no commentary or unit tests, but I hope this can still help you. If not, then it was fun writing anyway :)
Here is an example on how to do the first day of a month.
public enum Month
{
January = 1,
Febuary = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12
}
public static Nullable<DateTime> FindTheFirstDayOfAMonth(DayOfWeek dayOfWeek, Month month, int year)
{
// Do checking of parameters here, i.e. year being in future not past
// Create a DateTime object the first day of that month
DateTime currentDate = new DateTime(year, (int)month, 1);
while (currentDate.Month == (int)month)
{
if (currentDate.DayOfWeek == dayOfWeek)
{
return currentDate;
}
currentDate = currentDate.AddDays(1);
}
return null;
}
You call it like
Nullable<DateTime> date = Program.FindTheFirstDayOfAMonth(DayOfWeek.Monday, Month.September, 2009);
So you get the idea. You will have to do various functions do get what you want to achieve.
YO YO YO - You guys are making this too hard:
int DaysinMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
When I wrote a scheduler I pretty much copied SQL Servers sysschedules table
http://msdn.microsoft.com/en-us/library/ms178644.aspx
Using things like Frequency Type, Frequency Interval, etc... really made it easy to compute the values in code, but I am guessing there is a sproc to do it for you. I am searching for that now.
Yes, the .NET Framework will support that without any problems ;)
But seriously - you should be able to write code that does that fairly easily. If not, ask a question when you get stuck, and we'll help out. But you won't need any external assemblies - just go with a standard C# class =)

Categories

Resources