0

I want to get the List of Weeks in a specific year along with Start & End Dates.

I have tried the Solution given in this

which is:

var jan1 = new DateTime(DateTime.Today.Year , 1, 1);
//beware different cultures, see other answers
var startOfFirstWeek = jan1.AddDays(1 - (int)(jan1.DayOfWeek));
var weeks=
    Enumerable
        .Range(0,54)
        .Select(i => new {
            weekStart = startOfFirstWeek.AddDays(i * 7)
        })
        .TakeWhile(x => x.weekStart.Year <= jan1.Year)
        .Select(x => new {
            x.weekStart,
            weekFinish=x.weekStart.AddDays(4)
        })
        .SkipWhile(x => x.weekFinish < jan1.AddDays(1) )
        .Select((x,i) => new {
            x.weekStart,
            x.weekFinish,
            weekNum=i+1
        });

it is returning Weeks correctly for 2023. But when I select 2020, it takes first day from 2019 & Last day from 2021:

enter image description here

enter image description here

No any week should include the dates from another year in the start/end. For Example if the year starts at Thursday, The previous week will end at Wednesday & new Week will be started from Thursday.

Any suggestions to Resolve this? I want weeks in the same format, just to resolve this start & end issue

Thanks in Advance!

UPDATE:

I have tried the following Code which is getting the correct Start & End Date for the First Week but the Second Week is starting from the End Date of First Week:

var jan1 = new DateTime(year, 1, 1);
            var dec31 = new DateTime(year, 12, 31);
            CultureInfo cultInfo = CultureInfo.CurrentCulture;



            var startOfFirstWeek = jan1.AddDays(0 - (int)(jan1.DayOfWeek));

            return Enumerable.Range(0, 54)
                .Select(i => new Week
                {
                    StartDate = i == 0
                        ? jan1
                        : startOfFirstWeek.AddDays(i * 7),
                    EndDate = startOfFirstWeek.AddDays(i * 7 + 7).Year == year
                        ? startOfFirstWeek.AddDays(i * 7 + 7)
                        : dec31,
                    Number = i + 1
                })
                .TakeWhile(week => week.StartDate.Year == year)
                .ToList();

enter image description here

Alina Anjum
  • 1,178
  • 6
  • 30
  • 53
  • 1
    _"But when I select 2020, it takes first day from 2019 & Last day from 2021:"_ - Why would you think that is wrong? 1st Week of 2020 started on Monday, Dec 30. 2019 and the last week of 2020 ended in Friday, Jan 1st 2021. – Fildor May 30 '23 at 08:08
  • As per my Requirement, I don't want this. this is cost calculation system for an year. we can't take any additional start/end days. – Alina Anjum May 30 '23 at 08:09
  • If you do it week-based then there are no "additional" days. 30th and 31st Dec 2019 are considered Week 1 of 2020, btw ... – Fildor May 30 '23 at 08:11
  • If your requirement is to exclude all days not from the current year (which _will_ result in calculation errors), then you'll need to recheck if this is what is _actually_ wanted. It will drop some days. – Fildor May 30 '23 at 08:15
  • 2
    You should check your requirement of what standard yo want to follow here. What the first week(and therefore the first day of that week) of a year is depends on culture and what standard you want to follow (ISO8601 for example). Do you actually want complete weeks here? So the first and last week could just be cut of at the last/first day of year? – Ralf May 30 '23 at 08:29
  • Hi @Ralf, yes the last/first day will be cut of if there's start of end of year is coming. for example year ends on Wednesday then first week of next year should start from Thursday. I am following the Standard where Monday is the first Day of Week – Alina Anjum May 30 '23 at 09:09
  • 2
    You said, *"I am following the Standard where Monday is the first Day of Week"*, but then you also said, *"it is returning Weeks correctly for 2023"*. But since 2023 started on a Sunday, that doesn't make sense unless I'm missing something. Please update your original question with the additional requirements (which are, apparently, that no weeks should be included if they contain days from another year?). – Rufus L May 30 '23 at 09:29
  • @RufusL All the weeks should be included but they should be cut of from start/end if there's another year coming in – Alina Anjum May 30 '23 at 09:31
  • @RufusL I have added this in my Question. – Alina Anjum May 30 '23 at 09:34
  • **Note** that it is also possible that a few days from the end of the year X may be considered belonging to the first week of year X+1. What do you want to happen to those? (Which is different from "last Week of year X contains some days of year X+1") – Fildor May 30 '23 at 09:41
  • @Fildor For Example if There's a year end at Tuesday in 2020, The Last week of 2020 will only have two Days i.e. Monday & Tuesday. & then 2021 will start from Wednesday & will have 5 days from Wednesday Till Sunday. & then 2nd week of 2021 will start from Monday & so On – Alina Anjum May 30 '23 at 09:44
  • I can only recommend to recheck if that is actually the required behavior. "Last/First week of year" can really have wildly different definitions in different standards / personal opinions. Also make sure, people are on the same page, what the specific desired standard _actually is and how it defines that_. – Fildor May 30 '23 at 09:51

2 Answers2

1

Thank you for clarifying your question, I think I understand what you want. The first week of the year should start on January 1st, and the last week should end on December 31st.

The way I would solve this is to first of all use an actual class instead of an anonymous type to represent a week (which has a Number, a StartDate, and an EndDate):

public class Week
{
    public int Number { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

Then we can create a method to populate a list of weeks for a specified year.

In the method, as we enumerate each week, we set the start date to either January 1st (if it's the first week) or we calculate the start date based on the actual first day of the first week (which may be in the previous year) as we were doing before.

We also ensure that we set the last day of the last week to December 31st, by checking if the actual last day of the week has a year greater than the one passed into our method. Otherwise we just use the result of adding 6 to the StartDate.

Also, I'm not sure why your code has so many Select statements - you can just select each week once, populating the StartDate, EndDate, and Number all in one go.


UPDATE

You mentioned you want the weeks to start on Monday and end on Sunday. In order to accomplish this, I've modified the method below to take an optional firstDayOfWeek parameter that specifies which day should be considered the first day of the week.

We can then take the value of firstDayOfWeek and subtract jan1.DayOfWeek from it to determine the number of days we need to add to jan1 to get to the target start day for the week.


For example:

static List<Week> GetWeeks(int year, DayOfWeek firstDayOfWeek = DayOfWeek.Monday)
{
    var jan1 = new DateTime(year, 1, 1);
    var dec31 = new DateTime(year, 12, 31);
    var startOfFirstWeek = jan1.AddDays(firstDayOfWeek - jan1.DayOfWeek);

    return Enumerable.Range(0, 54)
        .Select(i => new Week
        {
            StartDate = i == 0 
                ? jan1 
                : startOfFirstWeek.AddDays(i * 7),
            EndDate = startOfFirstWeek.AddDays(i * 7 + 6).Year == year
                ? startOfFirstWeek.AddDays(i * 7 + 6)
                : dec31,
            Number = i + 1
        })
        .TakeWhile(week => week.StartDate.Year == year)
        .ToList();
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • Thanks for the Solution Rufus. it is Starting the Week from Sunday & ending at Saturday. while I need Monday as Start & Sunday as End. – Alina Anjum May 30 '23 at 11:19
  • If I am adding 7 in Place of 6 to consider it 7 days Week, the Same EndDate of first week is coming as Start Date of next week – Alina Anjum May 30 '23 at 11:30
  • I have added an update which has screen shot of the issues, can you suggest something? – Alina Anjum May 30 '23 at 12:19
  • I updated the answer and added an optional parameter to the method which allows you to change the first day of the week. It has a default value of Monday, but now it can be easily changed for other scenarios. – Rufus L May 31 '23 at 14:46
0

You have to change your code to make exceptions for the first and last weeks. For the first, you set the start at jan1 and for the last you remove all days going on next year.

var jan1 = new DateTime(DateTime.Today.Year , 1, 1);
var nextJan1 = new DateTime(DateTime.Today.Year + 1 , 1, 1);
//beware different cultures, see other answers
var startOfFirstWeek = jan1.AddDays(1 - (int)(jan1.DayOfWeek));
var weeks=
    Enumerable
        .Range(0,54)
        .Select(i => new {
            weekStart = i == 0 ? jan1 : startOfFirstWeek.AddDays(i * 7)
            })
        .TakeWhile(x => x.weekStart.Year <= jan1.Year)
        .Select(x => new {
            x.weekStart,
            weekFinish= x.weekStart.AddDays(4) < nextJan1 ? x.weekStart.AddDays(4) : x.weekStart.AddDays((nextJan1  , 1, 1) - x.weekStart).TotalDays)
        })
        .SkipWhile(x => x.weekFinish < jan1.AddDays(1) )
        .Select((x,i) => new {
            x.weekStart,
            x.weekFinish,
            weekNum=i+1
        });
Bibimission
  • 317
  • 5
  • 17