I have been trying to find the 5th week date of a day in a month like 5th week Monday date, 5th week Tue date, Wed... and so on based on the date from the same month. This date could belong to any week of same month.
I tried like
DateTime MonthEventDate=05/01/2016; //Date format in dd/MM/yyyy format
DayOfWeek EventDay="Sunday"; //For Example i want to find 5th Sunday in January Month, but days too will change everytime based on user selection
string SelectedWeek="5"; //Here i'm getting the week in which i need to find the given date i.e, 5th Monday or Tuesday & so on
if (SelectedWeek == "5")
{
//Here i tried to add number of days to my initial day to find 5th day date, but every time its returning next month value
MonthEventDate = MonthEventDate.AddDays((EventDay < MonthEventDate.DayOfWeek ? 31 : 28) + EventDay - MonthEventDate.DayOfWeek);
}
I know the logic is wrong but i want to get date of 5th day of the week, and if that day is not present, return 0. Looking for some guidance
Note: Here Month will change based on User Input, so how to return Date of fifth day, if it exist in the given month
This should give you the 5th day (if there is one) ...
DateTime dayInMonth = DateTime.Now;
DayOfWeek dayToFind = DayOfWeek.Friday;
var fifth= Enumerable.Range(1, DateTime.DaysInMonth(dayInMonth.Year, dayInMonth.Month))
.Select(day => new DateTime(dayInMonth.Year, dayInMonth.Month, day))
.Where(day => day.DayOfWeek == dayToFind)
.Skip(4)
.FirstOrDefault();
Extending #Soner Gönül's answer. In input you put required day of week, required month and required year. On output you get date of same day of week in fifth weeks, or null
public DateTime? FifthDay(DayOfWeek dayOfWeek, byte monthNum, int year)
{
if (monthNum > 12 || monthNum < 1)
{
throw new Exception("Month value should be between 1 and 12");
}
var searchDate = new DateTime(year, monthNum, 1);
var weekDay = searchDate.DayOfWeek;
if (weekDay == dayOfWeek)
{
searchDate = searchDate.AddDays(28);
}
for (DateTime d = searchDate; d < d.AddDays(7); d = d.AddDays(1))
{
if (d.DayOfWeek == dayOfWeek)
{
searchDate = searchDate.AddDays(28);
break;
}
}
if (searchDate.Month == monthNum)
return searchDate;
return null;
}
You can use a simple math like this (no validations included)
static DateTime? FindDate(int year, int month, DayOfWeek dayOfWeek, int weekOfMonth = 5)
{
var baseDate = new DateTime(year, month, 1);
int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;
var date = baseDate.AddDays(firstDateOffset + 7 * (weekOfMonth - 1));
return date.Month == month ? date : (DateTime?)null;
}
I think the code is self explanatory. The only trick that probably needs explanation is the line
int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;
which handles the case when let say the month starts in Friday and you asked for Monday, and is a short equivalent of
int firstDateOffset = (int)dayOfWeek - (int)baseDate.DayOfWeek;
if (firstDateOffset < 0) firstDateOffset += 7;
Usage in your example
var monthEventDate = FindDate(2016, 1, DayOfWeek.Sunday, 5);
You can refer this demo code
int requiredDay = 5; //Day number i.e 0-6(Sunday to SaturDay)
DateTime day = new DateTime(2016, 1, 1); //Month,year,Date
if (DateTime.DaysInMonth(day.Year, day.Month) > 28)
{
//Get the first day name of the month
int firstMonthDay = (int)day.DayOfWeek;
int offset=0;
//Number of days from the first day for the required day
if (firstMonthDay <= requiredDay)
offset = requiredDay - firstMonthDay;
else
offset = 7 - firstMonthDay + requiredDay;
//
DateTime firstoccurence = day.AddDays((double)offset);
DateTime fifthOccurence = firstoccurence.AddDays(28);
if (fifthOccurence.Month == firstoccurence.Month)
MessageBox.Show(fifthOccurence.ToString());
else
MessageBox.Show("No 5th Occurence for this day");
}
I want to calculate the number of weeks within a month.
The first week of January 2014 starting from the first Monday is the 6th. So, January has 4 weeks.
The first week of March 2014 starting from the first Monday is the 3rd. So, March has 5 weeks.
I want to know how many weeks there are in a month counting from the first Monday, not the first day.
How do I do this?
I have this code but it is used to get week number of the month for specific dates.
public int GetWeekNumberOfMonth(DateTime date)
{
date = date.Date;
DateTime firstMonthDay = new DateTime(date.Year, date.Month, 1);
DateTime firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
if (firstMonthMonday > date)
{
firstMonthDay = firstMonthDay.AddMonths(-1);
firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
}
return (date - firstMonthMonday).Days / 7 + 1;
}
Try this:
Get the number of days in the current month, and find the first day. For each day in the month, see if the day is a Monday, if so, increment the value.
public static int MondaysInMonth(DateTime thisMonth)
{
int mondays = 0;
int month = thisMonth.Month;
int year = thisMonth.Year;
int daysThisMonth = DateTime.DaysInMonth(year, month);
DateTime beginingOfThisMonth = new DateTime(year, month, 1);
for (int i = 0; i < daysThisMonth; i++)
if (beginingOfThisMonth.AddDays(i).DayOfWeek == DayOfWeek.Monday)
mondays++;
return mondays;
}
You can use it like this with the current date:
Console.WriteLine(MondaysInMonth(DateTime.Now));
Output:
4
or with any month you choose:
Console.WriteLine(MondaysInMonth(new DateTime(year, month, 1)))
Just correction to Cyral code :
i must start from 0 as he is using AddDays method .
Reason :the above example returns 5 for NOV and 4 for DEC which is wrong..
Edited code :
public static int MondaysInMonth(DateTime thisMonth)
{
int mondays = 0;
int month = thisMonth.Month;
int year = thisMonth.Year;
int daysThisMonth = DateTime.DaysInMonth(year, month);
DateTime beginingOfThisMonth = new DateTime(year, month, 1);
for (int i = 0; i < daysThisMonth; i++)
if (beginingOfThisMonth.AddDays(i).DayOfWeek == DayOfWeek.Monday)
mondays++;
return mondays;
}
I tried to use that code, but in some cases it didn't work. So I found this code on MSDN.
public static int MondaysInMonth(this DateTime time)
{
//extract the month
int daysInMonth = DateTime.DaysInMonth(time.Year, time.Month);
var firstOfMonth = new DateTime(time.Year, time.Month, 1);
//days of week starts by default as Sunday = 0
var firstDayOfMonth = (int)firstOfMonth.DayOfWeek;
var weeksInMonth = (int)Math.Ceiling((firstDayOfMonth + daysInMonth) / 7.0);
return weeksInMonth;
}
I created it like a extension method, so I can use like that:
var dateTimeNow = DateTime.Now;
var weeks = dateTimeNow.MondaysInMonth();
The faster method without looping
private static double GetDaysCount(DateTime sampleDate, int DayOfWeekToMatch)
{
int FirstDayOfMonth = (int)(new DateTime(sampleDate.Year, sampleDate.Month, 1).DayOfWeek);
int FirstOccurrenceOn = 0;
if (FirstDayOfMonth < DayOfWeekToMatch)
FirstOccurrenceOn = DayOfWeekToMatch - FirstDayOfMonth + 1;
else
FirstOccurrenceOn = (7 - FirstDayOfMonth) + DayOfWeekToMatch + 1;
int totalDays = DateTime.DaysInMonth(sampleDate.Year, sampleDate.Month);
return Math.Ceiling((totalDays - FirstOccurrenceOn) / 7.0f);
}
Given a date (of type DateTime), how do I find the 3rd Friday in the month of that date?
I'm going to repeat my answer from here with one little addition.
The language-agnostic version:
To get the first particular day of the month, start with the first day of the month: yyyy-mm-01. Use whatever function is available to give a number corresponding to the day of the week; in C# this would be DateTime.DayOfWeek. Subtract that number from the day you are looking for; for example, if the first day of the month is Wednesday (3) and you're looking for Friday (5), subtract 3 from 5, leaving 2. If the answer is negative, add 7. Finally add that to the first of the month; for my example, the first Friday would be the 3rd.
To get the last Friday of the month, find the first Friday of the next month and subtract 7 days.
To get the 3rd Friday of the month, add 14 days to the first Friday.
I haven't tested this, but since the third Friday can't possibly occur before the 15th of the month, create a new DateTime, then just increment until you get to a Friday.
DateTime thirdFriday= new DateTime(yourDate.Year, yourDate.Month, 15);
while (thirdFriday.DayOfWeek != DayOfWeek.Friday)
{
thirdFriday = thirdFriday.AddDays(1);
}
I followed User:Mark Ransom's algorithm and wrote a generalized day finder. For example to get the 3rd friday of december 2013,
int thirdFriday = DayFinder.FindDay(2013, 12, DayOfWeek.Friday, 3);
And here is the function definition. It doesn't have any iterative loops, so its efficient.
public class DayFinder
{
//For example to find the day for 2nd Friday, February, 2016
//=>call FindDay(2016, 2, DayOfWeek.Friday, 2)
public static int FindDay(int year, int month, DayOfWeek Day, int occurance)
{
if (occurance <= 0 || occurance > 5)
throw new Exception("Occurance is invalid");
DateTime firstDayOfMonth = new DateTime(year, month, 1);
//Substract first day of the month with the required day of the week
var daysneeded = (int)Day - (int)firstDayOfMonth.DayOfWeek;
//if it is less than zero we need to get the next week day (add 7 days)
if (daysneeded < 0) daysneeded = daysneeded + 7;
//DayOfWeek is zero index based; multiply by the Occurance to get the day
var resultedDay = (daysneeded + 1) + (7 * (occurance - 1));
if (resultedDay > (firstDayOfMonth.AddMonths(1) - firstDayOfMonth).Days)
throw new Exception(String.Format("No {0} occurance(s) of {1} in the required month", occurance, Day.ToString()));
return resultedDay;
}
}
Probably best to abstract this to a method to do any date/day combination:
(Extension Method)
public static bool TryGetDayOfMonth(this DateTime instance,
DayOfWeek dayOfWeek,
int occurance,
out DateTime dateOfMonth)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
if (occurance <= 0 || occurance > 5)
{
throw new ArgumentOutOfRangeException("occurance", "Occurance must be greater than zero and less than 6.");
}
bool result;
dateOfMonth = new DateTime();
// Change to first day of the month
DateTime dayOfMonth = instance.AddDays(1 - instance.Day);
// Find first dayOfWeek of this month;
if (dayOfMonth.DayOfWeek > dayOfWeek)
{
dayOfMonth = dayOfMonth.AddDays(7 - (int)dayOfMonth.DayOfWeek + (int)dayOfWeek);
}
else
{
dayOfMonth = dayOfMonth.AddDays((int)dayOfWeek - (int)dayOfMonth.DayOfWeek);
}
// add 7 days per occurance
dayOfMonth = dayOfMonth.AddDays(7 * (occurance - 1));
// make sure this occurance is within the original month
result = dayOfMonth.Month == instance.Month;
if (result)
{
dateOfMonth = dayOfMonth;
}
return result;
}
Results:
DateTime myDate = new DateTime(2013, 1, 1)
DateTime dateOfMonth;
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 1, out dateOfMonth)
// returns: true; dateOfMonth = Sunday, 1/6/2013
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 4, out dateOfMonth)
// returns: true; dateOfMonth = Sunday, 1/27/2013
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 5, out dateOfMonth)
// returns: false;
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 1, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/2/2013
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 4, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/23/2013
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 5, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/30/2013
// etc
Old post, but I found remarkably few decent answers online for this surely quite common problem! Mark Ransom's answer should be the last word on this algorithm-wise, but here is a C# helper class (in this case I think clearer than extensions) for anyone who wants a quick answer to the common problems of "first day of week in month", "xth day of week in month" and "last day of week in month".
I modified it to return DateTime.MinValue if the Xth day of the week falls outside the provided month rather than wrapping to the next month, because that to me seems more useful.
I've thrown in a LINQPad-runnable example program too.
void Main()
{
DayOfWeek dow = DayOfWeek.Friday;
int y = 2014;
int m = 2;
String.Format("First {0}: {1}", new object[] { dow, DateHelper.FirstDayOfWeekInMonth(y, m, dow) }).Dump();
"".Dump();
String.Format("Last {0}: {1}", new object[] { dow, DateHelper.LastDayOfWeekInMonth(y, m, dow) }).Dump();
"".Dump();
for(int i = 1; i <= 6; i++)
String.Format("{0} #{1}: {2}", new object[] { dow, i, DateHelper.XthDayOfWeekInMonth(y, m, dow, i) }).Dump();
}
public class DateHelper
{
public static DateTime FirstDayOfWeekInMonth(int year, int month, DayOfWeek day)
{
DateTime res = new DateTime(year, month, 1);
int offset = -(res.DayOfWeek - day);
if (offset < 0)
offset += 7;
res = res.AddDays(offset);
return res;
}
public static DateTime LastDayOfWeekInMonth(int year, int month, DayOfWeek day)
{
DateTime dt = new DateTime(year, month, 1).AddMonths(1);
DateTime res = FirstDayOfWeekInMonth(dt.Year, dt.Month, day);
res = res.AddDays(-7);
return res;
}
public static DateTime XthDayOfWeekInMonth(int year, int month, DayOfWeek day, int x)
{
DateTime res = DateTime.MinValue;
if (x > 0)
{
res = FirstDayOfWeekInMonth(year, month, day);
if (x > 1)
res = res.AddDays((x - 1) * 7);
res = res.Year == year && res.Month == month ? res : DateTime.MinValue;
}
return res;
}
}
Prints:
First Friday: 07/02/2014 00:00:00
Last Friday: 28/02/2014 00:00:00
Friday #1: 07/02/2014 00:00:00
Friday #2: 14/02/2014 00:00:00
Friday #3: 21/02/2014 00:00:00
Friday #4: 28/02/2014 00:00:00
Friday #5: 01/01/0001 00:00:00
Friday #6: 01/01/0001 00:00:00
Slightly more optimized version:
DateTime Now = DateTime.Now;
DateTime TempDate = new DateTime(Now.Year, Now.Month, 1);
// find first friday
while (TempDate.DayOfWeek != DayOfWeek.Friday)
TempDate = TempDate.AddDays(1);
// add two weeks
TempDate = TempDate.AddDays(14);
This is a version that uses LINQ and functional programming style.
It works like this.
First, take all of the days of the month. Then select only the ones of the right day (Friday). Finally take the nth (3rd) entry and return.
// dt: The date to start from (usually DateTime.Now)
// n: The nth occurance (3rd)
// weekday: the day of the week to look for
public DateTime GetNthWeekdayOfMonth(DateTime dt, int n, DayOfWeek weekday)
{
var days = Enumerable.Range(1, DateTime.DaysInMonth(dt.Year, dt.Month)).Select(day => new DateTime(dt.Year, dt.Month, day));
var weekdays = from day in days
where day.DayOfWeek == weekday
orderby day.Day ascending
select day;
int index = n - 1;
if (index >= 0 && index < weekdays.Count())
return weekdays.ElementAt(index);
else
throw new InvalidOperationException("The specified day does not exist in this month!");
}
My reasoning goes like this
the 15th is the first possible "third Friday" (1,8,15)
therefore we're looking for the first Friday on or after the 15th
DayOfWeek is an enumeration starting with 0 for Sunday
Therefore you have to add an offet of 5-(int)baseDay.DayOfWeek to the 15th
Except that the above offset can be negative, which we fix by adding 7, then doing modulo 7.
In code:
public static DateTime GetThirdFriday(int year, int month)
{
DateTime baseDay = new DateTime(year, month, 15);
int thirdfriday = 15 + ((12 - (int)baseDay.DayOfWeek) % 7);
return new DateTime(year, month, thirdfriday);
}
Since there are only 7 possible results, you could also do this:
private readonly static int[] thirdfridays =
new int[] { 20, 19, 18, 17, 16, 15, 21 };
public static int GetThirdFriday(int year, int month)
{
DateTime baseDay = new DateTime(year, month, 15);
return thirdfridays[(int)baseDay.DayOfWeek];
}
I pass this the DateTime for the start of the month I am looking at.
private DateTime thirdSunday(DateTime timeFrom)
{
List<DateTime> days = new List<DateTime>();
DateTime testDate = timeFrom;
while (testDate < timeFrom.AddMonths(1))
{
if (testDate.DayOfWeek == DayOfWeek.Friday)
{
days.Add(testDate);
}
testDate = testDate.AddDays(1);
}
return days[2];
}
I know of no clean/built in way of doing this. But it's not too hard to code up:
DateTime now = DateTime.Now;
for (int i = 0; i < 7; ++i)
{
DateTime d = new DateTime(now.Year, now.Month, i+1);
if (d.DayOfWeek == DayOfWeek.Friday)
{
return d.AddDays(14);
}
}
public DateTime GetThirdThursday(DateTime now)
{
DateTime ThirdThursday;
now = DateTime.Now;
string wkday;
DateTime firstday = new DateTime(now.Year, now.Month, 1);
ThirdThursday = firstday.AddDays(15);
// ThirdThursday = now.AddDays((now.Day - 1) * -1).AddDays(14);
wkday = ThirdThursday.DayOfWeek.ToString();
while (wkday.CompareTo("Thursday") < 0)
{
ThirdThursday.AddDays(1);
}
return ThirdThursday;
}
Late to the game but here's my solution to add DateTime extension functionality which accounts for the January to December issue when subtracting occurrence values and accounts for if the occurrence is 5 - which in my case should return the last occurrence which would either be number 4 or 5 depending on where the day lands in the month:
public static DateTime NthOf(this DateTime CurDate, int Occurrence, DayOfWeek Day)
{
//Last day of month if 5 - return last day.
if (Occurrence == 5)
{
return LastDayOfMonth(CurDate, Day);
}
var fday = new DateTime(CurDate.Year, CurDate.Month, 1, CurDate.Hour, CurDate.Minute, CurDate.Second);
var firstoccurrence = fday.DayOfWeek == Day ? fday : fday.AddDays(Day - fday.DayOfWeek);
// CurDate = 2011.10.1 Occurance = 1, Day = Friday >> 2011.09.30 FIX.
if (firstoccurrence.Month < CurDate.Month)
{
Occurrence = Occurrence + 1;
} else if (firstoccurrence.Month == 12 && CurDate.Month == 1)
{
Occurrence = Occurrence + 1;
}
return firstoccurrence.AddDays(7 * (Occurrence - 1));
}
public static DateTime LastDayOfMonth(this DateTime CurDate, DayOfWeek Day)
{
DateTime EndOfMonth = new DateTime(CurDate.Year, CurDate.Month, 1).AddMonths(1).AddDays(-1);
while (EndOfMonth.DayOfWeek != Day)
{
EndOfMonth = EndOfMonth.AddDays(-1);
}
return EndOfMonth;
}
The you can call your method with something like this:
Console.WriteLine(DateTime.Now.NthOf(3, DayOfWeek.Friday).ToString());
This would return the third Friday of the current month and log it to the console as a string value. It extends from DateTime nicely and does not require any usage of a static helper class or any additional moving parts.
int numday = 0;
int dayofweek = 5; //friday
DateTime thirdfriday;
for (int i = 0; i < (date.AddMonths(1) - date).Days && numday <3; i++)
{
if ((int)date.AddDays(i).DayOfWeek == dayofweek)
{
numday++;
}
if (numday == 3)
{
thirdfriday = date.AddDays(i);
}
}
Sorry to jump in late on this... Might help someone else tho.
Begin rant: Loops, yuck. Too much code, yuck. Not Generic Enough, yuck.
Here's a simple function with a free overload.
public DateTime DateOfWeekOfMonth(int year, int month, DayOfWeek dayOfWeek, byte weekNumber)
{
DateTime tempDate = new DateTime(year, month, 1);
tempDate = tempDate.AddDays(-(tempDate.DayOfWeek - dayOfWeek));
return
tempDate.Day > (byte)DayOfWeek.Saturday
? tempDate.AddDays(7 * weekNumber)
: tempDate.AddDays(7 * (weekNumber - 1));
}
public DateTime DateOfWeekOfMonth(DateTime sender, DayOfWeek dayOfWeek, byte weekNumber)
{
return DateOfWeekOfMonth(sender.Year, sender.Month, dayOfWeek, weekNumber);
}
Your usage:
DateTime thirdFridayOfMonth = DateOfWeekOfMonth(DateTime.Now, DayOfWeek.Friday, 3);
Here's my algorithm:
Find the number of days until the upcoming Friday.
Initialize a counter and set it to 1. Subtract seven days from the date returned from [1], then compare the month from the date returned against the date returned from (1).
If the months are not equal, return the counter from [2].
If the months are equal, recurse into [2] and add 1 to the counter created in [2].
The counter will give you the nth Friday of the month for that date (or its upcoming Friday).
Following works great, no validation for occurrence is provided. You can find any nth day for the given date month either from start or last. Provide minus occurrence value if you are looking for from the last.
public static DateTime GetDayOfMonth(DateTime dateValue, DayOfWeek dayOfWeek, int occurance)
{
List<DateTime> dayOfWeekRanges = new List<DateTime>();
//move to the first of th month
DateTime startOfMonth = new DateTime(dateValue.Year, dateValue.Month, 1);
//move startOfMonth to the dayOfWeek requested
while (startOfMonth.DayOfWeek != dayOfWeek)
startOfMonth = startOfMonth.AddDays(1);
do
{
dayOfWeekRanges.Add(startOfMonth);
startOfMonth = startOfMonth.AddDays(7);
} while (startOfMonth.Month == dateValue.Month);
bool fromLast = occurance < 0;
if (fromLast)
occurance = occurance * -1;
if (fromLast)
return dayOfWeekRanges[dayOfWeekRanges.Count - occurance];
else
return dayOfWeekRanges[occurance - 1];
}
Here is my two cents...
An optimized solution without unnecessary loops or tests :
public static DateTime ThirdFridayOfMonth(DateTime dateTime)
{
int day = dateTime.Day;
return dateTime.AddDays(21 - day - ((int)dateTime.DayOfWeek + 37 - day) % 7);
}
I wrote extended version of #justcoding121's code that can get from the last day of the month. I don't know this algorithm is right, but it works so far.
public static int? GetNthDayOfWeekInMonth(int year, int month, DayOfWeek dow, int weekNumOfMonth)
{
if (weekNumOfMonth < -5 || weekNumOfMonth == 0 || weekNumOfMonth > 5)
throw new ArgumentOutOfRangeException("weekNumOfMonth", $"must be between 1~5 or -1~-5. ({weekNumOfMonth})");
int daysOfMonth = DateTime.DaysInMonth(year, month);
if (weekNumOfMonth > 0)
{
var firstDay = new DateTime(year, month, 1);
var firstDayOfTargetDOW = (int)dow - (int)firstDay.DayOfWeek;
if (firstDayOfTargetDOW < 0)
firstDayOfTargetDOW += 7;
var resultedDay = (firstDayOfTargetDOW + 1) + (7 * (weekNumOfMonth - 1));
if (resultedDay > daysOfMonth)
return null;
return resultedDay;
}
else
{
var lastDay = new DateTime(year, month, daysOfMonth);
var firstDayOfTargetDOW = (int)lastDay.DayOfWeek - (int)dow;
if (firstDayOfTargetDOW < 0)
firstDayOfTargetDOW += 7;
var resultedDay = firstDayOfTargetDOW + (7 * (Math.Abs(weekNumOfMonth) - 1));
if (resultedDay > daysOfMonth)
return null;
return (daysOfMonth - resultedDay);
}
}
usage
Assert.AreEqual(02, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, 1));
Assert.AreEqual(30, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, -1));
I know this post is old. I have this solution, trying to find a more clean code. #unclebob
public static DateTime FindTheNthDay(
int year, int month, DayOfWeek day, int occurrence)
{
var startDate = new DateTime(year, month, 1);
while(startDate.DayOfWeek != day)
{
startDate = startDate.AddDays(1);
}
var nDays = 7 * (occurrence - 1);
var result = startDate.AddDays(nDays);
return result;
}
> FindTheNthDay(2006, 11, DayOfWeek.Friday, 4)
[11/24/2006 12:00:00 AM]
> FindTheNthDay(2005, 11, DayOfWeek.Friday, 4)
[11/25/2005 12:00:00 AM]
> FindTheNthDay(2004, 11, DayOfWeek.Friday, 4)
[11/26/2004 12:00:00 AM]
> FindTheNthDay(2003, 11, DayOfWeek.Friday, 4)
[11/28/2003 12:00:00 AM]
> FindTheNthDay(1983, 11, DayOfWeek.Friday, 4)
[11/25/1983 12:00:00 AM]
> FindTheNthDay(1978, 11, DayOfWeek.Friday, 4)
[11/24/1978 12:00:00 AM]
> FindTheNthDay(1972, 11, DayOfWeek.Friday, 4)
[11/24/1972 12:00:00 AM]
public static bool IsThirdWednesday(DateTime inputDate)
{
DateTime firstDayOfMonth = new DateTime(inputDate.Year, inputDate.Month, 1);
DateTime firstDayOfNextMonth = firstDayOfMonth.AddMonths(1);
int wednesdayCount = 0;
while(firstDayOfMonth < firstDayOfNextMonth)
{
if (firstDayOfMonth.DayOfWeek == DayOfWeek.Wednesday)
wednesdayCount++;
if (wednesdayCount == 3)
{
if (inputDate == firstDayOfMonth)
return true;
else
return false;
}
firstDayOfMonth = firstDayOfMonth.AddDays(1);
}
return false;
}
As the title says, given the year and the week number, how do I get the month number?
edit: if a week crosses two months, I want the month the first day of the week is in.
edit(2): This is how I get the week number:
CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
I'm just trying to do the reverse.
If you assume that the first day of your definition of week is the same day as the 1st day of the year, then this will work:
int year = 2000;
int week = 9;
int month = new DateTime(year, 1, 1).AddDays(7 * (week - 1)).Month;
Obviously, a true answer would depend on how you define the first day of the week, and how you define how a week falls into a month when it overlaps more than one.
This is what I ended up doing:
static int GetMonth(int Year, int Week)
{
DateTime tDt = new DateTime(Year, 1, 1);
tDt.AddDays((Week - 1) * 7);
for (int i = 0; i <= 365; ++i)
{
int tWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
tDt,
CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
if (tWeek == Week)
return tDt.Month;
tDt = tDt.AddDays(1);
}
return 0;
}
I would have preferred something simpler, but it works :)
Wouldn't it also depend on the day of the week?
this should be able to help
public int getMonth(int weekNum, int year)
{
DateTime Current = new DateTime(year, 1, 1);
System.DayOfWeek StartDOW = Current.DayOfWeek;
int DayOfYear = (weekNum * 7) - 6; //1st day of the week
if (StartDOW != System.DayOfWeek.Sunday) //means that last week of last year's month
{
Current = Current.AddDays(7 - (int)Current.DayOfWeek);
}
return Current.AddDays(DayOfYear).Month;
}
Another problem you could face is that most years do not start at the beginning of a week, which shifts everything.
Assumptions:
Sunday is the first day of the week.
Partial week still counts as week 1
Outputs beginning and ending month as integer array.
public int[] getMonth(int weekNum, int year)
{
DateTime StartYear = new DateTime(year, 1, 1);
System.DayOfWeek StartDOW = StartYear.DayOfWeek;
DateTime DayOfYearWeekStart = default(DateTime);
DateTime DayOfYearWeekEnd = default(DateTime);
int x = 0;
if ((StartDOW == System.DayOfWeek.Sunday)) {
DayOfYearWeekStart = StartYear.AddDays((weekNum - 1) * 7);
DayOfYearWeekEnd = DayOfYearWeekStart.AddDays(6);
} else {
for (x = 0; x <= 7; x += 1) {
if (StartYear.AddDays(x).DayOfWeek == DayOfWeek.Sunday) {
break; // TODO: might not be correct. Was : Exit For
}
}
if (weekNum == 1) {
DayOfYearWeekStart = StartYear;
DayOfYearWeekEnd = StartYear.AddDays(x - 1);
} else if (weekNum > 1) {
DayOfYearWeekStart = StartYear.AddDays(((weekNum - 2) * 7) + x);
DayOfYearWeekEnd = DayOfYearWeekStart.AddDays(6);
}
}
int[] Month = new int[2];
Month[0] = DayOfYearWeekStart.Month;
Month[1] = DayOfYearWeekEnd.Month;
return Month;
}
You cant. You need at least the day on which the 1st week starts (or when the week starts), to get an accurate answer.
You cant. A week may start in one month and end in another.
I think you're assuming that a "week" is any group of 7 sequential days. It isn't. Given Year(2008), Week(5), you could be in either January or Febuary, depending on when your "week" starts.
In .NET 3.0 and later you can use the ISOWeek-Class.
public static int MonthOfFirstDay(int year, int week)
{
return ISOWeek.ToDateTime(year, week, DayOfWeek.Monday).Month;
}
Note that the year might not fit, as the first week of a year can already start in end of December the year before. For instance the first week of 2020 started on Monday 2019-12-30.
// Calculate the week number according to ISO 8601
public static int Iso8601WeekNumber(DateTime dt)
{
return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
// ...
DateTime dt = DateTime.Now;
// Calculate the WeekOfMonth according to ISO 8601
int weekOfMonth = Iso8601WeekNumber(dt) - Iso8601WeekNumber(dt.AddDays(1 - dt.Day)) + 1;