Получить список недель для определенного года с датами начала и окончания

Я хочу получить список недель в определенном году вместе с датами начала и окончания.

Я попробовал решение, приведенное в это

который:

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

он правильно возвращает недели для 2023 года. Но когда я выбираю 2020 год, он занимает первый день с 2019 года и последний день с 2021 года:

Ни одна неделя не должна включать даты из другого года в начале/конце. Например, если год начинается в четверг, предыдущая неделя закончится в среду, а новая неделя начнется с четверга.

Любые предложения, чтобы решить эту проблему? Я хочу недели в том же формате, просто чтобы решить эту проблему с началом и концом

Заранее спасибо!

ОБНОВЛЯТЬ:

Я пробовал следующий код, который получает правильную дату начала и окончания для первой недели, но вторая неделя начинается с даты окончания первой недели:

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();

«Но когда я выбираю 2020 год, он берет первый день из 2019 года и последний день из 2021 года:» - Почему вы думаете, что это неправильно? Первая неделя 2020 г. началась в понедельник, 30 декабря. 2019 г. и последняя неделя 2020 г. закончилась в пятницу, 1 января 2021 г.

Fildor 30.05.2023 10:08

Согласно моему требованию, я не хочу этого. это система расчета стоимости за год. мы не можем брать дополнительные дни начала/окончания.

Alina Anjum 30.05.2023 10:09

Если вы делаете это по неделям, то «дополнительных» дней не будет. 30 и 31 декабря 2019 года считаются первой неделей 2020 года, кстати...

Fildor 30.05.2023 10:11

Если ваше требование состоит в том, чтобы исключить все дни не из текущего года (что приведет к ошибкам в расчетах), вам нужно будет перепроверить, действительно ли это требуется. Он упадет через несколько дней.

Fildor 30.05.2023 10:15

Вы должны проверить свое требование того, какому стандарту вы хотите следовать здесь. Какая первая неделя (и, следовательно, первый день этой недели) года, зависит от культуры и стандарта, которому вы хотите следовать (например, ISO8601). Вы действительно хотите полные недели здесь? Значит, первую и последнюю неделю можно просто вырезать в последний/первый день года?

Ralf 30.05.2023 10:29

Привет, @Ralf, да, последний/первый день будет сокращен, если приближается начало конца года. например, год заканчивается в среду, тогда первая неделя следующего года должна начинаться с четверга. Я следую стандарту, где понедельник — первый день недели.

Alina Anjum 30.05.2023 11:09

Вы сказали: «Я следую стандарту, где понедельник — первый день недели», но затем вы также сказали: «Он правильно возвращает недели для 2023 года». Но так как 2023 год начался в воскресенье, это не имеет смысла, если я что-то не упустил. Пожалуйста, обновите свой исходный вопрос дополнительными требованиями (которые, по-видимому, заключаются в том, что недели не должны быть включены, если они содержат дни из другого года?).

Rufus L 30.05.2023 11:29

@RufusL Все недели должны быть включены, но их следует вырезать с начала и конца, если наступит еще один год.

Alina Anjum 30.05.2023 11:31

@RufusL Я добавил это в свой вопрос.

Alina Anjum 30.05.2023 11:34

Обратите внимание, что также возможно, что несколько дней с конца года X можно считать относящимися к первой неделе года X+1. Что вы хотите, чтобы случилось с ними? (Что отличается от «последняя неделя года X содержит несколько дней года X + 1»)

Fildor 30.05.2023 11:41

@Fildor Например, если в 2020 году конец года приходится на вторник, на последней неделе 2020 года будет только два дня, то есть понедельник и вторник. а затем 2021 год начнется со среды и будет иметь 5 дней со среды по воскресенье. и затем 2-я неделя 2021 года начнется с понедельника и так далее

Alina Anjum 30.05.2023 11:44

Я могу только порекомендовать перепроверить, действительно ли это требуется. «Последняя / первая неделя года» действительно может иметь совершенно разные определения в разных стандартах / личных мнениях. Также убедитесь, что люди находятся на одной странице, что конкретно представляет собой желаемый стандарт и как он это определяет.

Fildor 30.05.2023 11:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы должны изменить свой код, чтобы сделать исключения для первой и последней недель. Для первого вы устанавливаете начало на 1 января, а для последнего вы удаляете все дни следующего года.

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
        });
Ответ принят как подходящий

Спасибо за разъяснение вашего вопроса, я думаю, что понимаю, что вы хотите. Первая неделя года должна начинаться 1 января, а последняя неделя должна заканчиваться 31 декабря.

Я бы решил это, прежде всего, используя реальный класс вместо анонимного типа для представления недели (у которого есть Number, StartDate и EndDate):

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

Затем мы можем создать метод для заполнения списка недель для указанного года.

В методе, когда мы перечисляем каждую неделю, мы устанавливаем дату начала либо на 1 января (если это первая неделя), либо рассчитываем дату начала на основе фактического первого дня первой недели (который может быть в предыдущем году). ), как мы делали раньше.

Мы также гарантируем, что последний день последней недели установлен на 31 декабря, проверяя, имеет ли фактический последний день недели год больше, чем тот, который передан в наш метод. В противном случае мы просто используем результат добавления 6 к StartDate.

Кроме того, я не уверен, почему в вашем коде так много операторов Select — вы можете просто выбрать каждую неделю один раз, заполнив StartDate, EndDate и Number все за один раз.


ОБНОВЛЯТЬ

Вы упомянули, что хотите, чтобы недели начинались Monday и заканчивались Sunday. Чтобы добиться этого, я изменил приведенный ниже метод, чтобы использовать необязательный параметр firstDayOfWeek, который указывает, какой день следует считать первым днем ​​недели.

Затем мы можем взять значение firstDayOfWeek и вычесть из него jan1.DayOfWeek, чтобы определить количество дней, которое нам нужно добавить к jan1, чтобы добраться до целевого дня начала недели.


Например:

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

Спасибо за решение Руфус. Неделя начинается с воскресенья и заканчивается в субботу. в то время как мне нужен понедельник как начало и воскресенье как конец.

Alina Anjum 30.05.2023 13:19

Если я добавлю 7 вместо 6, чтобы считать, что это 7-дневная неделя, та же дата окончания первой недели будет датой начала следующей недели.

Alina Anjum 30.05.2023 13:30

Я добавил обновление, в котором есть снимок экрана с проблемами, можете ли вы что-нибудь предложить?

Alina Anjum 30.05.2023 14:19

Я обновил ответ и добавил в метод необязательный параметр, который позволяет изменить первый день недели. Значение по умолчанию — понедельник, но теперь его можно легко изменить для других сценариев.

Rufus L 31.05.2023 16:46

Другие вопросы по теме