Рассчитать дату по номеру недели - PullRequest
122 голосов
/ 19 марта 2009

Каждый знает простой способ получить дату первого дня недели (понедельник здесь, в Европе). Я знаю год и номер недели? Я собираюсь сделать это в C #.

Ответы [ 23 ]

2 голосов
/ 13 мая 2011

Бесплатная библиотека периодов времени для .NET включает ISO 8601 класс соответствия Неделя :

// ----------------------------------------------------------------------
public static DateTime GetFirstDayOfWeek( int year, int weekOfYear )
{
  return new Week( year, weekOfYear ).FirstDayStart;
} // GetFirstDayOfWeek
1 голос
/ 06 февраля 2017

Слегка измененный код Микаэля Свенсона. Я нашел неделю первого понедельника и изменил номер недели.

 DateTime GetFirstWeekDay(int year, int weekNum)
    {
        Calendar calendar = CultureInfo.CurrentCulture.Calendar;

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

        int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
        DateTime firstMonday = jan1.AddDays(daysOffset);
        int firstMondayWeekNum = calendar.GetWeekOfYear(firstMonday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

        DateTime firstWeekDay = firstMonday.AddDays((weekNum-firstMondayWeekNum) * 7);

        return firstWeekDay;
    }
1 голос
/ 09 июля 2010

Предполагая, что номер недели начинается с 1

DateTime dt =  new DateTime(YearNumber, 1, 1).AddDays((WeekNumber - 1) * 7 - (WeekNumber == 1 ? 0 : 1));
return dt.AddDays(-(int)dt.DayOfWeek);

Это должно дать вам первый день в любой данной неделе. Я не проводил много испытаний, но похоже, что это работает. Это меньшее решение, чем большинство других, которые я нашел в Интернете, поэтому хотел бы поделиться.

0 голосов
/ 21 сентября 2012

Предлагаемое решение не является полным - оно работает только для CalendarWeekRule.FirstFullWeek. Другие типы правил недели не работают. Это можно увидеть с помощью этого теста:

foreach (CalendarWeekRule rule in Enum.GetValues(typeof(CalendarWeekRule)))
{
    for (int year = 1900; year < 2000; year++)
    {
        DateTime date = FirstDateOfWeek(year, 1, rule);
        Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, rule, DayOfWeek.Monday) == 1);
        Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(-1), rule, DayOfWeek.Monday) != 1);
    }
}
0 голосов
/ 08 ноября 2016

В настоящее время не существует класса C #, который бы правильно обрабатывал номера ISO 8601week. Даже если вы можете создать культуру, найти ближайшую вещь и исправить ее, я думаю, что лучше сделать полный расчет самостоятельно:

    /// <summary>
    /// Converts a date to a week number.
    /// ISO 8601 week 1 is the week that contains the first Thursday that year.
    /// </summary>
    public static int ToIso8601Weeknumber(this DateTime date)
    {
        var thursday = date.AddDays(3 - date.DayOfWeek.DayOffset());
        return (thursday.DayOfYear - 1) / 7 + 1;
    }

    /// <summary>
    /// Converts a week number to a date.
    /// Note: Week 1 of a year may start in the previous year.
    /// ISO 8601 week 1 is the week that contains the first Thursday that year, so
    /// if December 28 is a Monday, December 31 is a Thursday,
    /// and week 1 starts January 4.
    /// If December 28 is a later day in the week, week 1 starts earlier.
    /// If December 28 is a Sunday, it is in the same week as Thursday January 1.
    /// </summary>
    public static DateTime FromIso8601Weeknumber(int weekNumber, int? year = null, DayOfWeek day = DayOfWeek.Monday)
    {
        var dec28 = new DateTime((year ?? DateTime.Today.Year) - 1, 12, 28);
        var monday = dec28.AddDays(7 * weekNumber - dec28.DayOfWeek.DayOffset());
        return monday.AddDays(day.DayOffset());
    }

    /// <summary>
    /// Iso8601 weeks start on Monday. This returns 0 for Monday.
    /// </summary>
    private static int DayOffset(this DayOfWeek weekDay)
    {
        return ((int)weekDay + 6) % 7;
    }
0 голосов
/ 04 ноября 2015

Я написал и протестировал следующий код, и он отлично работает для меня. Пожалуйста, дайте мне знать, если у кого-то возникнут проблемы с этим, я также разместил вопрос, чтобы получить наилучший ответ. Кто-то может найти это полезным.

public static DateTime GetFirstDateOfWeekByWeekNumber(int year, int weekNumber)
        {
            var date = new DateTime(year, 01, 01);
            var firstDayOfYear = date.DayOfWeek;
            var result = date.AddDays(weekNumber * 7);

            if (firstDayOfYear == DayOfWeek.Monday)
                return result.Date;
            if (firstDayOfYear == DayOfWeek.Tuesday)
                return result.AddDays(-1).Date;
            if (firstDayOfYear == DayOfWeek.Wednesday)
                return result.AddDays(-2).Date;
            if (firstDayOfYear == DayOfWeek.Thursday)
                return result.AddDays(-3).Date;
            if (firstDayOfYear == DayOfWeek.Friday)
                return result.AddDays(-4).Date;
            if (firstDayOfYear == DayOfWeek.Saturday)
                return result.AddDays(-5).Date;
            return result.AddDays(-6).Date;
        }
0 голосов
/ 10 июля 2015

Я упростил код, предоставленный Микаэлем Свенссоном, который подходит для многих стран Европы.

public static DateTime FirstDateOfWeekIso8601(int year, int week)
{
        var firstThursdayOfYear = new DateTime(year, 1, 1);
        while (firstThursdayOfYear.DayOfWeek != DayOfWeek.Thursday)
        {
            firstThursdayOfYear = firstThursdayOfYear.AddDays(1);
        }

        var startDateOfWeekOne = firstThursdayOfYear.AddDays(-(DayOfWeek.Thursday - DayOfWeek.Monday));

        return startDateOfWeekOne.AddDays(7 * (week - 1));        
}
0 голосов
/ 27 ноября 2014

Это моё решение, когда мы хотим вычислить дату, указанную в году, номере недели и дне недели.

int Year = 2014;
int Week = 48;
int DayOfWeek = 4;

DateTime FecIni = new DateTime(Year, 1, 1);
FecIni = FecIni.AddDays(7 * (Week - 1));
if ((int)FecIni.DayOfWeek > DayOfWeek)
{
    while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(-1);
}
else
{
    while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(1);
}
0 голосов
/ 21 сентября 2012

Я сделал улучшенную версию предложенного решения, которая является более простой и параметризует firstDayOfWeek:

public static DateTime GetFirstDayOfWeek(int year, int week, DayOfWeek firstDayOfWeek)
{
    return GetWeek1Day1(year, firstDayOfWeek).AddDays(7 * (week - 1));
}

public static DateTime GetWeek1Day1(int year, DayOfWeek firstDayOfWeek)
{
    DateTime date = new DateTime(year, 1, 1);

    // Move towards firstDayOfWeek
    date = date.AddDays(firstDayOfWeek - date.DayOfWeek);

    // Either 1 or 52 or 53
    int weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFullWeek, firstDayOfWeek);

    // Move forwards 1 week if week is 52 or 53
    date = date.AddDays(7 * System.Math.Sign(weekOfYear - 1));

    return date;
}
0 голосов
/ 05 сентября 2009

Чтобы конвертировать в обоих направлениях, смотрите здесь: Статья в Википедии о датах недели ISO

...