Masoud Andalibi
Masoud Andalibi

Reputation: 3228

Creating a list of weeks within a year

Greetings i have this Model below:

   public class WeekOfYear
    {
        public int WeekNumber { get; set; }
        public DateTime FirstDayOfWeek { get; set; }
        public DateTime LastDayOfWeek { get; set; }
    }

At the moment i am trying to create a list based on weeks of the year and i have to know which week am i and what is the first day and last day of the week are, I've researched a little bit but nothing came up, I know how to get the WeekNumber but problem starts when i try to get the other properties "first/last days of the week", anyone has any clue? its appreciated.

Update

Let me make it more clear, lets say i know i am within the first week of the year, What i want to know is the first day of the week is for example : Monday 2017-1-1 and the last day is Sunday 2017-1-7.

Upvotes: 0

Views: 301

Answers (2)

Frode
Frode

Reputation: 3455

This code will probably give you some help;

class Program
{
    static void Main(string[] args)
    {
        foreach(var week in 2017.GenerateWeekSequence())
        {
            Console.WriteLine($"Week ({week.WeekNumber}. First day={week.FirstDayOfWeek.ToString()}, Last day={week.LastDayOfWeek.ToString()}");
        }
    }
}

public static class WeekExtensions
{
    private static CultureInfo ThreadCulture => Thread.CurrentThread.CurrentCulture;
    public class Info
    {
        public Info(DateTime firstDayOfWeek) { FirstDayOfWeek = firstDayOfWeek; }

        public int WeekNumber => ThreadCulture.Calendar.GetWeekOfYear(
            FirstDayOfWeek, CalendarWeekRule.FirstDay, ThreadCulture.DateTimeFormat.FirstDayOfWeek);

        public DateTime FirstDayOfWeek { get; }

        public DateTime LastDayOfWeek => FirstDayOfWeek.AddDays(6);
    }

    public static IEnumerable<Info> GenerateWeekSequence(this int year)
    {
        var runner = new DateTime(year, 1, 1);
        // Move back to the first day of week (even if it's in the previous year)
        while (runner.DayOfWeek != ThreadCulture.DateTimeFormat.FirstDayOfWeek)
        {
            runner = runner.AddDays(-1);
        }
        // Now, jump dates one week at a time
        while (runner.Year <= year)
        {
            yield return new Info(runner);
            runner = runner.AddDays(7);  // Jump to first day of next week
        }
    }
}

Upvotes: 0

Tiago &#193;vila
Tiago &#193;vila

Reputation: 2867

I did something like that a some time ago. I've adapted my code to your class, see if it helps:

public static List<WeekOfYear> GetWeeksOfYear(int year)
{
    var weeksQuantity = GetNumberOfWeeksInYear(year);
    var weeksList = new List<WeekOfYear>();

    for (int i = 1; i <= weeksQuantity; i++)
    {
        var weekNumber = i;

        DateTime firstDay;
        DateTime lastDay;
        GetFirstAndLastDateOfWeek(year, weekNumber, out firstDay, out lasDay);

        weeksList.Add(new WeekOfYear
        {
            FirstDayOfWeek = firstDay,
            LastDayOfWeek  = lastDay,
            WeekNumber = weekNumber
        });
    }

    return weeksList;
}

public static int GetNumberOfWeeksInYear(int year)
{
    var dfi = DateTimeFormatInfo.CurrentInfo;
    var date1 = new DateTime(year, 12, 31);
    if (dfi != null)
    {
        Calendar cal = dfi.Calendar;
        return cal.GetWeekOfYear(date1, dfi.CalendarWeekRule,
            dfi.FirstDayOfWeek);
    }

    return 0;
}

public static void GetFirstAndLastDateOfWeek(int year, int weekOfYear, out DateTime firstDay, out DateTime lastDay)
{
    var ci = CultureInfo.CurrentCulture;

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

    firstDay = firstWeekDay.AddDays(weekOfYear * 7);
    lastDay = firstDay.AddDays(6);
}

Upvotes: 2

Related Questions