One of the options in bootstrap-datepicker is to show the week number on the same row as the days of the week. This numbers the weeks using the ISO-8061 standard which is fine (though it would be nice to have the option to change locale), for my purposes I wanted to be able to take a week in the format “W52-2018” and then be able to get the start date of that week.
I was previously using the below code which worked but wasn’t ISO-8061 compliant and was giving me a startdate of 07/01/2019 for W01-2019 when (perhaps confusingly) this should be 31/12/2018.
public static DateTime FirstDateOfWeek(string week, CalendarWeekRule rule)
{
int year = int.Parse(week.Split("-W")[0]);
int weekNumber = int.Parse(week.Split("-W")[1]);
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstMonday, rule, DayOfWeek.Monday);
if (firstWeek <= 1)
{
weekNumber -= 1;
}
DateTime result = firstMonday.AddDays(weekNumber * 7);
return result;
}
After a bit of searching I found this StackOverflow answer which provided the below code which worked for my purposes.
public static DateTime FirstDateOfWeekISO8601(string week)
{
int year = int.Parse(week.Split("-W")[0]);
int weekNumber = int.Parse(week.Split("-W")[1]);
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 = 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
return result.AddDays(-3);
}
I also found this handy DateTime extension method which could come in useful.
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(-1 * diff).Date;
}
}
0 Comments