2013-11-11 21 views
5

Мне нужно получить дату первого и последнего дня недели, зная номер недели.Получить дату первого и последнего дня недели, зная номер недели

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

Мне удалось получить номер недели на основе заданной даты начала и окончания. Теперь мне нужно получить дату первого дня и последнего дня той же недели предыдущего года. Как я мог сделать это быстрее всего?

EDIT: Это, как я получил номер недели:

private int GetWeekNumber(DateTime date) 
    { 
     GregorianCalendar calendar = new GregorianCalendar(GregorianCalendarTypes.USEnglish); 
     return calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);    
    } 

ответ

14

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

// this method is borrowed from http://stackoverflow.com/a/11155102/284240 
public static int GetIso8601WeekOfYear(DateTime time) 
{ 
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time); 
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday) 
    { 
     time = time.AddDays(3); 
    } 

    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); 
} 

public static DateTime FirstDateOfWeek(int year, int weekOfYear, System.Globalization.CultureInfo ci) 
{ 
    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; 
    } 
    return firstWeekDay.AddDays(weekOfYear * 7); 
} 

Тогда вы можете получить обе даты в следующем виде:

// 46 
int thisWeekNumber = GetIso8601WeekOfYear(DateTime.Today); 
// 11/11/2013 
DateTime firstDayOfWeek= FirstDateOfWeek(2013, thisWeekNumber, CultureInfo.CurrentCulture); 
// 11/12/2012 
DateTime firstDayOfLastYearWeek = FirstDateOfWeek(2012, thisWeekNumber, CultureInfo.CurrentCulture); 

Добавить 6 дней, чтобы получить окончание недели.

+0

как я могу сделать эту работу для Календаря США, где воскресенье - первый день недели? Это так же просто, как заменить все ссылки на DayOfWeek.Monday с DayOfWeek.Sunday? –

+0

@OctavianEpure: этот метод возвращает номер недели в соответствии с [ISO 8601] (http://en.wikipedia.org/wiki/ISO_8601). Но если у вас уже есть способ получить номер недели, вам нужен только второй метод, который поддерживает параметр «CultureInfo». Просто передайте 'CultureInfo.CurentCulture' или' CultureInfo.CreateSpecificCulture («en-US») '. Я только что показал свой метод, чтобы получить номер недели, так как вы не показали свой. –

+0

Я vave показал мой метод, чтобы получить номер недели в моем отредактированном ответе. Большое спасибо за ваш пост. Я попробую его, как только начну полное тестирование. –

-1

Поскольку Есть 7 дней в неделю, вы будете знать, что неделя 10 такая же, как дни 71 - 77. Вы знаете номер дней в месяц (не забывайте високосный год). Постройте точные даты, а затем вы можете получить информацию о тех днях.

+3

Уверены ли вы в этом? Что произойдет, если первый из января в пятницу? –

+0

Предположительно, ОП знает это, потому что он говорит, что может получить номер недели. Чтобы это сделать, я полагаю, он должен был знать, когда началась первая неделя. С оборотной стороны вы можете узнать день недели на 1 января любого года. Затем вам нужно установить правило: это ваша первая неделя, или вам нужно перейти в следующий понедельник, чтобы начать первую неделю? – user1646737

+0

Кто-нибудь позаботится объяснить нисходящий голос? Если ОП знает, что он на неделе 43, то, очевидно, ему нужно знать, что в пятницу, 1 января, это либо первая неделя года, либо вторая неделя, в зависимости от того, какое правило он хочет установить и следовать. Остальное - просто математика. – user1646737

0

Вычитайте 1 год с момента создания DateTime и снова вызовите метод GetWeekNumber.

TimeSpan oneYear = dateTime.AddYears(1) - dateTime; 
var lastYearWeekNumber = GetWeekNumber(dateTime.Subtract(oneYear)); 
8

Это мое решение:

public static DateTime FirstDayOfWeek(DateTime date) 
{ 
    DayOfWeek fdow = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; 
    int offset = fdow - date.DayOfWeek; 
    DateTime fdowDate = date.AddDays(offset); 
    return fdowDate; 
} 

public static DateTime LastDayOfWeek(DateTime date) 
{ 
    DateTime ldowDate = FirstDayOfWeek(date).AddDays(6); 
    return ldowDate; 
} 
+0

. лучший ответ – sheavens

+0

FirstDayOfWeek дает первый день следующей недели, если «дата» - воскресенье. – MxFragz

1

выше метод вычисляет первую дату неправильно 1-й недели 2016 года

с фиксированным кодом на основе предыдущих ответов

public DateTime FirstDateOfWeek(
     int year, 
     int weekOfYear) 
    { 
     var newYear = new DateTime(year, 1, 1); 
     var weekNumber = newYear.GetIso8601WeekOfYear(); 

     DateTime firstWeekDate; 

     if (weekNumber != 1) 
     { 
      var dayNumber = (int) newYear.DayOfWeek; 
      firstWeekDate = newYear.AddDays(7 - dayNumber + 1); 
     } 
     else 
     { 
      var dayNumber = (int)newYear.DayOfWeek; 
      firstWeekDate = newYear.AddDays(-dayNumber + 1); 
     } 

     if (weekOfYear == 1) 
     { 
      return firstWeekDate; 
     } 

     return firstWeekDate.AddDays(7 * (weekOfYear - 1)); 
    } 

Plus тест

[TestCase(2016, 1, 2016, 1, 4)] 
    [TestCase(2016, 2, 2016, 1, 11)] 
    [TestCase(2016, 52, 2016, 12, 26)] 
    [TestCase(2014, 1, 2013, 12, 30)] 
    public void FirstDateOfWeek_ShouldReturnCorrectDay(int year, int weekNumber, int correctYear, int correctMonth, int correctDay) 
    { 
     var helper = new DateHelper(); 
     var result = helper.FirstDateOfWeek(year, weekNumber); 

     Assert.That(result.Year, Is.EqualTo(correctYear)); 
     Assert.That(result.Month, Is.EqualTo(correctMonth)); 
     Assert.That(result.Day, Is.EqualTo(correctDay)); 
    } 
-1

Метод Тима Шмельтера не работал на шведскую (sv-SE) культуру, где начинаются недели по понедельникам. Это было протестировано с помощью en-US и sv-SE.

public static DateTime GetFirstDateOfWeek(int year, int weekOfYear, CultureInfo cultureInfo) 
    { 
     DateTime jan1 = new DateTime(year, 1, 1); 
     int daysOffset = (int)cultureInfo.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek; 
     DateTime firstWeekDay = jan1.AddDays(daysOffset); 
     int firstWeek = cultureInfo.Calendar.GetWeekOfYear(jan1, cultureInfo.DateTimeFormat.CalendarWeekRule, cultureInfo.DateTimeFormat.FirstDayOfWeek); 
     if (firstWeek == 1) 
     { 
      weekOfYear -= 1; 
     } 
     return firstWeekDay.AddDays(weekOfYear * 7); 
    } 
0
private static DateTime FirstDateOfWeek(int year, int weekOfYear) 
    { 
     var firstDate = new DateTime(year, 1, 4); 
     //first thursday of the week defines the first week (https://en.wikipedia.org/wiki/ISO_8601) 
     //Wiki: the 4th of january is always in the first week 
     while (firstDate.DayOfWeek != DayOfWeek.Monday) 
      firstDate = firstDate.AddDays(-1); 

     return firstDate.AddDays((weekOfYear - 1)*7); 
    } 

Easyer и более эффективное решение!

Смежные вопросы