В .net, зная номер недели, как я могу получить дату рабочих дней?

Я хочу создать функцию на С#, которая для номера недели вернет мне дни на этой неделе.

Например, для недели номер 40, как я могу получить дни: 4/10, 5/10, 6/10, 7/10, 8/10, 9/10, 10/10.

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


person Community    schedule 04.10.2010    source источник
comment
возможный дубликат Рассчитать дату по номеру недели   -  person    schedule 06.06.2013


Ответы (3)


Я думаю, что это должно делать то, что вы хотите:

    public static DateTime[] WeekDays(int Year, int WeekNumber)
    {
        DateTime start = new DateTime(Year, 1, 1).AddDays(7 * WeekNumber);
        start = start.AddDays(-((int)start.DayOfWeek));
        return Enumerable.Range(0, 7).Select(num => start.AddDays(num)).ToArray();
    }

Хотя я рассматриваю воскресенье как первый день недели, если вы хотите, чтобы понедельник был первым днем, измените диапазон от (0,7) до (1,7).

Если вы хотите соответствовать стандарту ISO, я думаю, это должно работать:

    public static DateTime[] WeekDays(int Year, int WeekNumber)
    {
        DateTime start = new DateTime(Year, 1, 4);
        start = start.AddDays(-((int)start.DayOfWeek));
        start = start.AddDays(7 * (WeekNumber - 1));
        return Enumerable.Range(0, 7).Select(num => start.AddDays(num)).ToArray();
    }
person JDunkerley    schedule 04.10.2010
comment
В основном это зависит от того, в какой части мира вы находитесь, потому что в Европе неделя 1 — это первая неделя с 4 днями, тогда как в США это неделя с 1/1 (en.wikipedia.org/wiki/Seven-day_week#Week_numbering), поэтому код правильный, за исключением того, что может потребоваться корректировка базы. - person veggerby; 04.10.2010
comment
Насколько я помню из старшего проекта, приведенный выше код не будет работать при расчете с ISO-неделями (8601, что часто используется в европе), даже если база будет скорректирована (см. мой ответ). Но, возможно, это изменилось с .net4. - person HCL; 04.10.2010
comment
Да, вы правы, это не соответствует стандарту ISO. Может быть довольно легко отрегулирован, чтобы соответствовать стандарту. Поставлю и поправлю. - person JDunkerley; 04.10.2010
comment
Спасибо, я использовал другую функцию, но основная идея та же. - person ; 07.10.2010
comment
Я предоставил правильный способ вычисления дат недели ISO в своем собственном ответе. Я считаю, что большинство людей понимают это неправильно и считают хорошей идеей оставить этот код лежащим поблизости. Он не делает никаких странных вещей, вместо этого он максимально использует .NET API для получения правильных результатов. - person John Leidegren; 21.03.2011

Примечание

Кажется, я пропустил ошибку. Текущий код был обновлен по состоянию на 30 января 2012 г., чтобы учесть этот факт, и теперь мы получаем daysOffset на основе вторника, который согласно Микаэль Свенсон, похоже, решил проблему. Подробности см. в этом ответе.

Большинство людей склонны понимать это неправильно, и под неправильным я подразумеваю несоответствие стандарту даты недели ISO8601 (мы часто используем его в Швеции). Этот расчет довольно странный, но он сводится к этому коду в .NET:

DateTime jan1 = new DateTime(yyyy, 1, 1);

int daysOffset = DayOfWeek.Tuesday - jan1.DayOfWeek;

DateTime firstMonday = jan1.AddDays(daysOffset);

var cal = CultureInfo.CurrentCulture.Calendar;

int firstWeek = cal.GetWeekOfYear(jan1, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

var weekNum = ww;

if (firstWeek <= 1)
{
    weekNum -= 1;
}

var result = firstMonday.AddDays(weekNum * 7 + d - 1);

return result;

Он будет вычислять дату года (yyyy), номер недели (ww) и день недели (d). Для этого сначала устанавливается первое января с помощью встроенного календаря (чтобы этот код можно было настроить). Причина, по которой это немного странно, заключается в том, что 53-я неделя иногда приходится на январь, а иногда 1-я неделя приходится на декабрь.

Если вам нужно пойти другим путем, это не совсем тривиально, но здесь показан правильный способ сделать это в .NET.

var c = CultureInfo.CurrentCulture.Calendar;

// `FromDayOfWeek` fixes problem with the enumeration
// not based on Monday being the first day of the week
d = (byte)FromDayOfWeek(c.GetDayOfWeek(t));
switch (d)
{
    case 1:
    case 2:
    case 3:
        // see this for details
        // http://blogs.msdn.com/shawnste/archive/2006/01/24/iso-8601-week-of-year-format-in-microsoft-net.aspx
        t = t.AddDays(3);
        break;
}

ww = (byte)c.GetWeekOfYear(t, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

// Adjust year when week 53 occurs in January or week 1 occurs in December 
if (ww == 53 && t.Month == 1)
{
    yyyy = (short)(t.Year - 1);
}
else if (ww == 1 && t.Month == 12)
{
    yyyy = (short)(t.Year + 1);
}
else
{
    yyyy = (short)t.Year;
}
person John Leidegren    schedule 21.03.2011

Следующая функция поможет вам получить начальную дату по номеру недели и году.

public DateTime GetFirstDayFromWeekNumber(int weekNumber, int weekYear)
        {
            DateTime beginingYear = new DateTime(weekYear, 1, 1);
            DateTime finalDate = new DateTime();
            int maxDayOfWeek = (int)DayOfWeek.Saturday;
            int yearStartDay = (int)beginingYear.DayOfWeek;
            int dayDeference = maxDayOfWeek - yearStartDay;

            if (weekNumber == 1)
            {
                finalDate = beginingYear.AddDays(-yearStartDay);
            }
            else if (weekNumber == 2)
            {
                finalDate = beginingYear.AddDays((dayDeference + 1));
            }
            else if (weekNumber > 2 && weekNumber <= 53)
            {
                finalDate = beginingYear.AddDays((dayDeference + 1) + ((weekNumber - 2)* 7));
            }
            return finalDate;
        }
person Muhammed Rafi    schedule 05.03.2012