Saving View generated variables to my database - c#

I am creating an MVC application and do not want to use external Libraries. I need to populate a specific week with the related dates and this will change weekly, I want to then save the date with the relevant person and project information for that date to my database. I believe i need to give an Id to the relevant table tag, but I do not know how to do this. Can somebody please point me in the right direction?
I have created the Models and auto generated the Controllers and views, I am still editing the Views and realized that I have this problem. I have figured out how to populate the days for the specific week, but do not know how to implement it in MVC.
var currentWeek = Convert.ToInt32(Console.ReadLine());
var newWeek = GetDateFromWeekNumberAndDayOfWeek(currentWeek);
for (int i = 0; i < 7; i++)
{
var weekDays = newWeek.AddDays(i);
if (weekDays.DayOfWeek != DayOfWeek.Sunday && weekDays.DayOfWeek != DayOfWeek.Saturday)
{
Console.WriteLine("Day " + (i + 1) + " " + weekDays.ToString("dddd, dd MMMM yyyy"));
}
}
Console.ReadLine();
}
static DateTime GetDateFromWeekNumberAndDayOfWeek(int weekNumber)
{
DateTime jan1 = new DateTime(DateTime.Now.Year, 1, 1);
int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
// Use first Thursday in January to get first week of the year as it will never be in Week 52/53
DateTime firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekNumber;
// As we're adding days to a date in Week 1, we need to subtract 1 in order to get the right date for week #1
if (firstWeek <= 1)
{
weekNum -= 1;
}
// Using the first Thursday as starting week ensures that we are starting in the right year then we add number of weeks multiplied with days
var result = firstThursday.AddDays(weekNum * 7);
// Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
//addition use -4 to get Sunday as first day
return result.AddDays(-4);
}

Related

Given a Year and a Week number, how can I get the first date in that week, in .Net? [duplicate]

Anyone know an easy way to get the date of the first day in the week (monday here in Europe). I know the year and the week number? I'm going to do this in C#.
I had issues with the solution by #HenkHolterman even with the fix by #RobinAndersson.
Reading up on the ISO 8601 standard resolves the issue nicely. Use the first Thursday as the target and not Monday. The code below will work for Week 53 of 2009 as well.
public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
// Use first Thursday in January to get first week of the year as
// it will never be in Week 52/53
DateTime firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekOfYear;
// As we're adding days to a date in Week 1,
// we need to subtract 1 in order to get the right date for week #1
if (firstWeek == 1)
{
weekNum -= 1;
}
// Using the first Thursday as starting week ensures that we are starting in the right year
// then we add number of weeks multiplied with days
var result = firstThursday.AddDays(weekNum * 7);
// Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
return result.AddDays(-3);
}
I like the solution provided by Henk Holterman. But to be a little more culture independent, you have to get the first day of the week for the current culture ( it's not always monday ):
using System.Globalization;
static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
int firstWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(jan1, CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);
if (firstWeek <= 1)
{
weekOfYear -= 1;
}
return firstMonday.AddDays(weekOfYear * 7);
}
The easiest way is probably to find the first Monday of the year, and then add the relevant number of weeks. Here's some sample code. It assumes a week number starting at 1, by the way:
using System;
class Test
{
static void Main()
{
// Show the third Tuesday in 2009. Should be January 20th
Console.WriteLine(YearWeekDayToDateTime(2009, DayOfWeek.Tuesday, 3));
}
static DateTime YearWeekDayToDateTime(int year, DayOfWeek day, int week)
{
DateTime startOfYear = new DateTime (year, 1, 1);
// The +7 and %7 stuff is to avoid negative numbers etc.
int daysToFirstCorrectDay = (((int)day - (int)startOfYear.DayOfWeek) + 7) % 7;
return startOfYear.AddDays(7 * (week-1) + daysToFirstCorrectDay);
}
}
Personally I'd take advantage of the culture info to get the day of the week and loop down to the culture's first day of the week. I'm not sure if I'm explaining it properly, here's an example:
public DateTime GetFirstDayOfWeek(int year, int weekNumber)
{
return GetFirstDayOfWeek(year, weekNumber, Application.CurrentCulture);
}
public DateTime GetFirstDayOfWeek(int year, int weekNumber,
System.Globalization.CultureInfo culture)
{
System.Globalization.Calendar calendar = culture.Calendar;
DateTime firstOfYear = new DateTime(year, 1, 1, calendar);
DateTime targetDay = calendar.AddWeeks(firstOfYear, weekNumber);
DayOfWeek firstDayOfWeek = culture.DateTimeFormat.FirstDayOfWeek;
while (targetDay.DayOfWeek != firstDayOfWeek)
{
targetDay = targetDay.AddDays(-1);
}
return targetDay;
}
Good news! A pull request adding System.Globalization.ISOWeek to .NET Core was just merged and is currently slated for the 3.0 release. Hopefully it will propagate to the other .NET platforms in a not-too-distant future.
You should be able to use the ISOWeek.ToDateTime(int year, int week, DayOfWeek dayOfWeek) method to calculate this.
You can find the source code here.
According to ISO 8601:1988 that is used in Sweden the first week of the year is the first week that has at least four days within the new year.
So if your week starts on a Monday the first Thursday any year is within the first week.
You can DateAdd or DateDiff from that.
using Fluent DateTime http://fluentdatetime.codeplex.com/
var year = 2009;
var firstDayOfYear = new DateTime(year, 1, 1);
var firstMonday = firstDayOfYear.Next(DayOfWeek.Monday);
var weeksDateTime = 12.Weeks().Since(firstMonday);
The free Time Period Library for .NET includes the ISO 8601 conform class Week:
// ----------------------------------------------------------------------
public static DateTime GetFirstDayOfWeek( int year, int weekOfYear )
{
return new Week( year, weekOfYear ).FirstDayStart;
} // GetFirstDayOfWeek
This one worked for me, it also have the advantage of expecting a cultureinfo as parameter to test the formula with different cultures. If empty, it gets the current culture info... valid values are like: "it", "en-us", "fr", ... ando so on.
The trick is to subtract the week number of the first day of the year, that may be 1 to indicate that the first day is within the first week. Hope this helps.
Public Shared Function FirstDayOfWeek(ByVal year As Integer, ByVal weekNumber As Integer, ByVal culture As String) As Date
Dim cInfo As System.Globalization.CultureInfo
If culture = "" Then
cInfo = System.Globalization.CultureInfo.CurrentCulture
Else
cInfo = System.Globalization.CultureInfo.CreateSpecificCulture(culture)
End If
Dim calendar As System.Globalization.Calendar = cInfo.Calendar
Dim firstOfYear As DateTime = New DateTime(year, 1, 1, calendar)
Dim firstDayWeek As Integer = calendar.GetWeekOfYear(firstOfYear, cInfo.DateTimeFormat.CalendarWeekRule, cInfo.DateTimeFormat.FirstDayOfWeek)
weekNumber -= firstDayWeek
Dim targetDay As DateTime = calendar.AddWeeks(firstOfYear, weekNumber)
Dim fDayOfWeek As DayOfWeek = cInfo.DateTimeFormat.FirstDayOfWeek
While (targetDay.DayOfWeek <> fDayOfWeek)
targetDay = targetDay.AddDays(-1)
End While
Return targetDay
End Function
Here is a method that is compatible with the week numbers that Google Analytics, and also the same numbering scheme we used internally at Intel, and which I'm sure is also used in a lot of other contexts.
// Google Analytics does not follow ISO standards for date.
// It numbers week 1 starting on Jan. 1, regardless what day of week it starts on.
// It treats Sunday as the first day of the week.
// The first and last weeks of a year are usually not complete weeks.
public static DateTime GetStartDateTimeFromWeekNumberInYear(int year, uint weekOfYear)
{
if (weekOfYear == 0 || weekOfYear > 54) throw new ArgumentException("Week number must be between 1 and 54! (Yes, 54... Year 2000 had Jan. 1 on a Saturday plus 53 Sundays.)");
// January 1 -- first week.
DateTime firstDayInWeek = new DateTime(year, 1, 1);
if (weekOfYear == 1) return firstDayInWeek;
// Get second week, starting on the following Sunday.
do
{
firstDayInWeek = firstDayInWeek.AddDays(1);
} while (firstDayInWeek.DayOfWeek != DayOfWeek.Sunday);
if (weekOfYear == 2) return firstDayInWeek;
// Now get the Sunday of whichever week we're looking for.
return firstDayInWeek.AddDays((weekOfYear - 2)*7);
}
I tried some codes above and some have small mistakes, when you try different years with different starting days of week you will see them, I took the code of Jon Skeet, fix it and it works, very simple code.
Public Function YearWeekDayToDateTime(ByVal year As Integer, ByVal weekDay As Integer, ByVal week As Integer) As DateTime
' weekDay, day you want
Dim startOfYear As New DateTime(year, 1, 1)
Dim startOfYearFixDay As Integer
If startOfYear.DayOfWeek <> DayOfWeek.Sunday Then
startOfYearFixDay = startOfYear.DayOfWeek
Else
startOfYearFixDay = 7
End If
Return startOfYear.AddDays((7 * (week)) - startOfYearFixDay + weekDay)
End Function
Assuming the week number starts at 1
DateTime dt = new DateTime(YearNumber, 1, 1).AddDays((WeekNumber - 1) * 7 - (WeekNumber == 1 ? 0 : 1));
return dt.AddDays(-(int)dt.DayOfWeek);
This should give you the first day in any given week. I haven't done a lot of testing on it, but looks like it works. It's smaller solution than most other's I found on the web, so wanted to share.
Lightly changed Mikael Svenson code. I found the week of the first monday and appropriate change the week number.
DateTime GetFirstWeekDay(int year, int weekNum)
{
Calendar calendar = CultureInfo.CurrentCulture.Calendar;
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
int firstMondayWeekNum = calendar.GetWeekOfYear(firstMonday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
DateTime firstWeekDay = firstMonday.AddDays((weekNum-firstMondayWeekNum) * 7);
return firstWeekDay;
}
Week 1 is defined as being the week that starts on a Monday and contains the first Thursday of the year.
To convert in both directions, see here: Wikipedia article on ISO week dates
I improved a little on Thomas' solution with an override:
public static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
return Timer.FirstDateOfWeekOfMonth(year, 1, weekOfYear);
}
public static DateTime FirstDateOfWeekOfMonth(int year, int month,
int weekOfYear)
{
DateTime dtFirstDayOfMonth = new DateTime(year, month, 1);
//I also commented out this part:
/*
if (firstWeek <= 1)
{
weekOfYear -= 1;
}
*/
Otherwise the date was preceding by one week..
Thank you Thomas, great help.
I used one of the solutions but it gave me wrong results, simply because it counts Sunday as a first day of the week.
I changed:
var firstDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber - 1) * 7);
var lastDay = firstDay.AddDays(6);
to:
var lastDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber) * 7);
var firstDay = lastDay.AddDays(-6);
and now it is working as a charm.
The proposed solution is not complete - it only works for CalendarWeekRule.FirstFullWeek. Other types of week rules do not work. This can be seen using this test case:
foreach (CalendarWeekRule rule in Enum.GetValues(typeof(CalendarWeekRule)))
{
for (int year = 1900; year < 2000; year++)
{
DateTime date = FirstDateOfWeek(year, 1, rule);
Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, rule, DayOfWeek.Monday) == 1);
Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(-1), rule, DayOfWeek.Monday) != 1);
}
}
I have made a refined version of the proposed solution that is a simpler and parametrises the firstDayOfWeek:
public static DateTime GetFirstDayOfWeek(int year, int week, DayOfWeek firstDayOfWeek)
{
return GetWeek1Day1(year, firstDayOfWeek).AddDays(7 * (week - 1));
}
public static DateTime GetWeek1Day1(int year, DayOfWeek firstDayOfWeek)
{
DateTime date = new DateTime(year, 1, 1);
// Move towards firstDayOfWeek
date = date.AddDays(firstDayOfWeek - date.DayOfWeek);
// Either 1 or 52 or 53
int weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFullWeek, firstDayOfWeek);
// Move forwards 1 week if week is 52 or 53
date = date.AddDays(7 * System.Math.Sign(weekOfYear - 1));
return date;
}
this is my solution when we want to calculate a date given year, week number and day of the week.
int Year = 2014;
int Week = 48;
int DayOfWeek = 4;
DateTime FecIni = new DateTime(Year, 1, 1);
FecIni = FecIni.AddDays(7 * (Week - 1));
if ((int)FecIni.DayOfWeek > DayOfWeek)
{
while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(-1);
}
else
{
while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(1);
}
I simplified the code Mikael Svensson provided which is correct for many countries in Europe.
public static DateTime FirstDateOfWeekIso8601(int year, int week)
{
var firstThursdayOfYear = new DateTime(year, 1, 1);
while (firstThursdayOfYear.DayOfWeek != DayOfWeek.Thursday)
{
firstThursdayOfYear = firstThursdayOfYear.AddDays(1);
}
var startDateOfWeekOne = firstThursdayOfYear.AddDays(-(DayOfWeek.Thursday - DayOfWeek.Monday));
return startDateOfWeekOne.AddDays(7 * (week - 1));
}
I have written and tested the following code and is working perfectly fine for me. Please let me know if anyone face trouble with this, I have posted a question as well in order to get the best possible answer. Someone may find it useful.
public static DateTime GetFirstDateOfWeekByWeekNumber(int year, int weekNumber)
{
var date = new DateTime(year, 01, 01);
var firstDayOfYear = date.DayOfWeek;
var result = date.AddDays(weekNumber * 7);
if (firstDayOfYear == DayOfWeek.Monday)
return result.Date;
if (firstDayOfYear == DayOfWeek.Tuesday)
return result.AddDays(-1).Date;
if (firstDayOfYear == DayOfWeek.Wednesday)
return result.AddDays(-2).Date;
if (firstDayOfYear == DayOfWeek.Thursday)
return result.AddDays(-3).Date;
if (firstDayOfYear == DayOfWeek.Friday)
return result.AddDays(-4).Date;
if (firstDayOfYear == DayOfWeek.Saturday)
return result.AddDays(-5).Date;
return result.AddDays(-6).Date;
}
Currently, there is no C# class that correctly handles ISO 8601week numbers. Even though you can instantiate a culture, look for the closest thing and correct that, I think it is better to do the complete calculation yourself:
/// <summary>
/// Converts a date to a week number.
/// ISO 8601 week 1 is the week that contains the first Thursday that year.
/// </summary>
public static int ToIso8601Weeknumber(this DateTime date)
{
var thursday = date.AddDays(3 - date.DayOfWeek.DayOffset());
return (thursday.DayOfYear - 1) / 7 + 1;
}
/// <summary>
/// Converts a week number to a date.
/// Note: Week 1 of a year may start in the previous year.
/// ISO 8601 week 1 is the week that contains the first Thursday that year, so
/// if December 28 is a Monday, December 31 is a Thursday,
/// and week 1 starts January 4.
/// If December 28 is a later day in the week, week 1 starts earlier.
/// If December 28 is a Sunday, it is in the same week as Thursday January 1.
/// </summary>
public static DateTime FromIso8601Weeknumber(int weekNumber, int? year = null, DayOfWeek day = DayOfWeek.Monday)
{
var dec28 = new DateTime((year ?? DateTime.Today.Year) - 1, 12, 28);
var monday = dec28.AddDays(7 * weekNumber - dec28.DayOfWeek.DayOffset());
return monday.AddDays(day.DayOffset());
}
/// <summary>
/// Iso8601 weeks start on Monday. This returns 0 for Monday.
/// </summary>
private static int DayOffset(this DayOfWeek weekDay)
{
return ((int)weekDay + 6) % 7;
}

How to Find 5th or ending date of a particular day in a month based on date of the same month

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");
}

Getting Week number of year starting from April

I'm currently using this snippet:
private string GetCurrentWeek()
{
// Return a string to be used in the TextBox control on the Main Form
DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
int Year = DateTime.Now.Year;
int Month = DateTime.Now.Month;
int Day = DateTime.Now.Day;
DateTime Date1 = new DateTime(Year, Month, Day);
Calendar cal = dfi.Calendar;
return cal.GetWeekOfYear(Date1, dfi.CalendarWeekRule, dfi.FirstDayOfWeek).ToString();
}
To get the current week of the year. Which returns as expected. Though. This is starting from January. Which is doing what the code says. Though, I'm ideally looking for it to start from April. So week 1 would start on the 6th of April and Week 52 would be on April 5th (just like the UK Tax Year). I have sought the internet and google (perhaps using wrong keywords) but I'm unable to discover how to perform this task using C#
I'm assuming you want week 1 to begin on April 6th always, and be 7 days long, rather than having some rule like "Weeks always start on Mondays". Basically this is just a matter of:
Working out which tax year you're in
Finding the start of that tax year
Subtracting that date from the current date
Dividing the result by 7
For example:
DateTime today = DateTime.Today;
int taxYear = today.Month > 4 || today.Month == 4 && today.Day >= 6
? today.Year : today.Year - 1;
DateTime taxYearStart = new DateTime(taxYear, 4, 6);
TimeSpan elapsedTaxYear = today - taxYearStart;
int days = elapsedTaxYear.Days;
int taxYearWeek = (days / 7) + 1;
Of course, you could also use Noda Time:
// Usually inject this, using SystemClock.Instance for production
IClock clock = ...;
// For the UK, use DateTimeZoneProviders.Tzdb["Europe/London"];
DateTimeZone zone = ...;
// This will be simpler in Noda Time 2.0 with ZonedClock
LocalDate today = clock.Now.InZone(zone).LocalDateTime.Date;
int taxYear = today.Month > 4 || today.Month == 4 && today.Day >= 6
? today.Year : today.Year - 1;
LocalDate taxYearStart = new LocalDate(taxYear, 4, 6);
int days = Period.Between(taxYearStart, today, PeriodUnits.Days).Days;
int taxYearWeek = (days / 7) + 1;

Get Day For Previous Month

I have a what seems like simple date issue and I just can't wrap my head around trying to get it efficiently... I basically need to get the previous months date for a specific day.
For example: If today is the 3rd Thursday of the month, I want to get the 3rd Thursday's date of last month. Its important that its based of the number of the day...ie: First Monday, 4th Friday, 2nd Wednesday, etc.
What's the best way to get this done?
BTW...If there is not an equivalent previous months day that is fine. I can handle that. Also, currently I am counting the number or days ("Mondays", "Tuesdays", etc) manually to figure this out. I was just hoping there is a more elegant way to do it.
Here's what I would do:
static DateTime? GetLastMonthSameNthDayOfWeek(DateTime date)
{
int nth = (date.Day-1) / 7; // returns 0 if 1st, 1 if 2nd...
var prevMonthDay = date.AddMonths(-1);
// find the first date of month having the same day of week
var d = new DateTime(prevMonthDay.Year, prevMonthDay.Month, 1);
while(d.Day <= 7)
{
if (d.DayOfWeek == date.DayOfWeek)
break;
d = d.AddDays(1);
}
// go to nth day of week
d = d.AddDays(7 * nth);
// if we have passed the current month, there's no nth day of week
if (d.Month != prevMonthDay.Month)
return null;
return d;
}
Usage example:
// 3rd wednesday of August 2012
var a = new DateTime(2012, 8, 15);
var aPrev = GetLastMonthSameNthDayOfWeek(a);
// aPrev = July 18th 2012 (i.e. the 3rd wednesday of July 2012)
// 5th wednesday of August 2012
var b = new DateTime(2012, 8, 15);
var bPrev = GetLastMonthSameNthDayOfWeek(b);
// bPrev = null, because there's no 5th wednesday of July 2012
N.B. :
getting the ordinal position of the day of week inside a month is really easy:
int nth = ((date.Day-1) / 7) + 1; // 1 -> 1st, 2 -> 2nd, 3 -> 3rd ...
As I couldn't find a built-in way, I've written this simple extension method for DateTime, check it out:
public static class DateTimeExtension
{
public static DateTime GetPositionalDate(this DateTime BaseDate, DayOfWeek WeekDay, int position)
{
if (position < 1)
{
throw new Exception("Invalid position");
}
else
{
DateTime ReturnDate = new DateTime(BaseDate.Year, BaseDate.Month, BaseDate.Day);
int PositionControl = 1;
bool FoundDate = false;
while(ReturnDate.DayOfWeek != WeekDay)
{
ReturnDate = ReturnDate.AddDays(1);
}
while (!FoundDate && PositionControl <= position)
{
PositionControl++;
if (PositionControl == position)
{
FoundDate = true;
}
else
{
ReturnDate = ReturnDate.AddDays(7);
}
}
if (FoundDate)
{
return ReturnDate;
}
else
{
throw new Exception("Date not found");
}
}
}
}
Usage:
DateTime lastMonth = DateTime.Now.GetPositionalDate(DayOfWeek.Sunday, 2);
Regards
There is no, by default, a way that .Net understand this specific logic for dates. So using the following, you can get what you're looking for:
var now = DateTime.Now.Date;
Use DateTime.AddMonth(-1) to get last month.
Use DateTime.AddDays(now.Days * -1 + 1) to get the first of the month.
Use DateTime.DayOfWeek to determine the day and subtract or add days as necessary
Ok, what you can do is determine the day of the week of the first day of the month last month, take the difference between the day of the week you want and that day of the week, then add 7 * the weeks you want (less one week)...
// Let's get the 3rd Friday of last month:
// get starting date
DateTime date = new DateTime();
// get first day of last month
DateTime firstOfLastMonth = date.AddMonths(-1).AddDays(-1 * (date.Day + 1));
// subtract out the day of the week (get the previous Sunday, even if it is last month)
DateTime justBeforeMonth = firstOfLastMonth.AddDays((int)firstOfLastMonth.DayOfWeek);
// Add in the DayOfWeek number we are looking for
DateTime firstFridayOfMonth = justBeforeMonth.AddDays(DayOfWeek.Friday);
// if we are still in last month, add a week to get into this month
if (firstFridayOfMonth.Month != date.AddMonth(-1).Month) { firstFridayOfMonth.AddDays(7); }
// add in 2 weeks to get the third week of the month
DateTime thirdFridayOfMonth = firstFridayOfMonth.AddDays(14);
Here's the solution I came up with. If the day doesn't exist (e.g. 8th Saturday), GetDate() will return null:
{
DateTime lastMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1);
DateTime? date = GetDate(lastMonth.Month, lastMonth.Year, DayOfWeek.Thursday, 2);
}
private static DateTime? GetDate(int month, int year, DayOfWeek dayOfWeek, int which)
{
DateTime firstOfMonth = new DateTime(year, month, 1);
DateTime date;
for (date = firstOfMonth; date.DayOfWeek != dayOfWeek; date = date.AddDays(1))
;
date = date.AddDays(7 * (which - 1));
return date.Month == month && date.Year == year ? (DateTime?)date : null;
}

calulate month from week no

i am getting week no from database need to calculate which week of the month it is.
for ex:
week no = 7 month = 2
week no 11 month = 3
How to calculate it??
Just to add on i also have the year value with the week no.
Ok, I'll have a go, but it's not very pretty:
public int MonthOfWeek( int week, int year, CalendarWeekRule, weekrule, DayOfWeek firstDayOfWeek)
{
GregorianCalendar gc = new GregorianCalendar();
for( DateTime dt = new DateTime(year, 1, 1); dt.Year == year; dt = dt.AddDays(1))
{
if( gc.GetWeekOfYear( dt, System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday) == week ){
return dt.Month;
}
}
return -1;
}
This takes into consideration the culture specific rules for generating weeks. If a week is split between two months it will return the first month it encounters.
So in Norway, I would call this with CalendarWeekRule.FirstFourDayWeek and DayOfWeek.Monday for correct results.
Calculate a date from weeknumber:
Calculate date from week number
Get the WeekOfMonth:
Calculate week of month in .NET
Assuming that you are looking for the month in the given year:
var dtYearStart = new DateTime(DateTime.Now.Year, 1, 1);
CultureInfo defaultCultureInfo = CultureInfo.CurrentCulture;
// Check for the starting date of the initial week.
int diff = dtYearStart.DayOfWeek - defaultCultureInfo.DateTimeFormat.FirstDayOfWeek;
if (diff < 0)
{
diff += 7;
}
dtYearStart = dtYearStart.AddDays(-1 * diff).Date;
int weekNo = 15;
DateTime dtWeekBased = dtYearStart.AddDays((weekNo-1) * 7);
string strMonth = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(dtWeekBased.Month);
Using DateTime, you can multiply week number by 7, get the total days passed on the year, add those days to 31/12/yyyy-1 and the get the month from the resulting DateTime.
I hope this to be useful to you.
See you.
4 week = 1 month
so use
week%4
its return you no of month
Here a solution using the Time Period Library for .NET:
// ----------------------------------------------------------------------
public int GetMonthOfWeek( int weekOfYear )
{
return new Week( weekOfYear ).FirstDayStart.Month;
} // GetMonthOfWeek

Resources