Get date of first and last day of week knowing week number

The method above calculates first date wrong for 1st week of 2016.

Fixed code based on previous answers

 public DateTime FirstDateOfWeek(
        int year,
        int weekOfYear)
    {
        var newYear = new DateTime(year, 1, 1);
        var weekNumber = newYear.GetIso8601WeekOfYear(); 

        DateTime firstWeekDate;

        if (weekNumber != 1)
        {
            var dayNumber = (int) newYear.DayOfWeek;
            firstWeekDate = newYear.AddDays(7 - dayNumber + 1);
        }
        else
        {
            var dayNumber = (int)newYear.DayOfWeek;
            firstWeekDate = newYear.AddDays(-dayNumber + 1);
        }

        if (weekOfYear == 1)
        {
            return firstWeekDate;
        }

        return firstWeekDate.AddDays(7 * (weekOfYear - 1));
    }

Plus test

    [TestCase(2016, 1, 2016, 1, 4)]
    [TestCase(2016, 2, 2016, 1, 11)]
    [TestCase(2016, 52, 2016, 12, 26)]
    [TestCase(2014, 1, 2013, 12, 30)]
    public void FirstDateOfWeek_ShouldReturnCorrectDay(int year, int weekNumber, int correctYear, int correctMonth, int correctDay)
    {
        var helper = new DateHelper();
        var result = helper.FirstDateOfWeek(year, weekNumber);

        Assert.That(result.Year, Is.EqualTo(correctYear));
        Assert.That(result.Month, Is.EqualTo(correctMonth));
        Assert.That(result.Day, Is.EqualTo(correctDay));
    }

This is my solution:

public static DateTime FirstDayOfWeek(DateTime date)
{
    DayOfWeek fdow = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
    int offset = fdow - date.DayOfWeek;
    DateTime fdowDate = date.AddDays(offset);
    return fdowDate;
}

public static DateTime LastDayOfWeek(DateTime date)
{
    DateTime ldowDate = FirstDayOfWeek(date).AddDays(6);
    return ldowDate;
}

You can use following two methods to calculate the week-number and the start-date of a given weeknumber according to a given year:

// this method is borrowed from http://stackoverflow.com/a/11155102/284240
public static int GetIso8601WeekOfYear(DateTime time)
{
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
} 

public static DateTime FirstDateOfWeek(int year, int weekOfYear, System.Globalization.CultureInfo ci)
{
    DateTime jan1 = new DateTime(year, 1, 1);
    int daysOffset = (int)ci.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
    DateTime firstWeekDay = jan1.AddDays(daysOffset);
    int firstWeek = ci.Calendar.GetWeekOfYear(jan1, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);
    if ((firstWeek <= 1 || firstWeek >= 52) && daysOffset >= -3)
    {
        weekOfYear -= 1;
    }
    return firstWeekDay.AddDays(weekOfYear * 7);
}

Then you can get both dates in the following way:

// 46
int thisWeekNumber = GetIso8601WeekOfYear(DateTime.Today); 
// 11/11/2013  
DateTime firstDayOfWeek= FirstDateOfWeek(2013, thisWeekNumber, CultureInfo.CurrentCulture); 
// 11/12/2012  
DateTime firstDayOfLastYearWeek = FirstDateOfWeek(2012, thisWeekNumber, CultureInfo.CurrentCulture);   

Add 6 days to get the end of the week.


    private static DateTime FirstDateOfWeek(int year, int weekOfYear)
    {
        var firstDate = new DateTime(year, 1, 4);
        //first thursday of the week defines the first week (https://en.wikipedia.org/wiki/ISO_8601)
        //Wiki: the 4th of january is always in the first week
        while (firstDate.DayOfWeek != DayOfWeek.Monday)
            firstDate = firstDate.AddDays(-1);

        return firstDate.AddDays((weekOfYear - 1)*7);
    }

Easyer and more efficient solution!

Tags:

C#

Date