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

Leave a Reply

Your email address will not be published. Required fields are marked *