Как я могу вычислить/найти номер недели для данной даты?
Как я могу вычислить/найти номер недели определенной даты?
Ответ 1
var currentCulture = CultureInfo.CurrentCulture;
var weekNo = currentCulture.Calendar.GetWeekOfYear(
new DateTime(2013, 12, 31),
currentCulture.DateTimeFormat.CalendarWeekRule,
currentCulture.DateTimeFormat.FirstDayOfWeek);
Помните, что это не ISO 8601. В Швеции мы используем ISO 8601 week, но даже если для культуры установлено значение "sv-SE", CalendarWeekRule
- FirstFourDayWeek
, а FirstDayOfWeek
- в понедельнике переменная weekNo будет установлена на 53 вместо правильного 1 в приведенном выше коде.
Я только пробовал это со шведскими настройками, но я уверен, что эта проблема будет затронута всеми странами (Австрия, Германия, Швейцария и др.) с использованием номеров в течение недели ISO 8601.
Peter van Ooijen и Шон Стил имеет разные решения к этой проблеме.
Здесь компактное решение
private static int WeekOfYearISO8601(DateTime date)
{
var day = (int)CultureInfo.CurrentCulture.Calendar.GetDayOfWeek(date);
return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(4 - (day == 0 ? 7 : day)), CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
Он был протестирован на следующие даты
var datesAndISO8601Weeks = new Dictionary<DateTime, int>
{
{new DateTime(2000, 12, 31), 52},
{new DateTime(2001, 1, 1), 1},
{new DateTime(2005, 1, 1), 53},
{new DateTime(2007, 12, 31), 1},
{new DateTime(2008, 12, 29), 1},
{new DateTime(2010, 1, 3), 53},
{new DateTime(2011, 12, 31), 52},
{new DateTime(2012, 1, 1), 52},
{new DateTime(2013, 1, 2), 1},
{new DateTime(2013, 12, 31), 1},
};
foreach (var dateWeek in datesAndISO8601Weeks)
{
Debug.Assert(WeekOfYearISO8601(dateWeek.Key) == dateWeek.Value, dateWeek.Key.ToShortDateString() + " should be week number " + dateWeek.Value + " but was " + WeekOfYearISO8601(dateWeek.Key));
}
Ответ 2
public static int GetWeekNumber(DateTime dtPassed)
{
CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;
}
Ответ 3
Отъезд GetWeekOfYear в MSDN имеет следующий пример:
using System;
using System.Globalization;
public class SamplesCalendar {
public static void Main() {
// Gets the Calendar instance associated with a CultureInfo.
CultureInfo myCI = new CultureInfo("en-US");
Calendar myCal = myCI.Calendar;
// Gets the DTFI properties required by GetWeekOfYear.
CalendarWeekRule myCWR = myCI.DateTimeFormat.CalendarWeekRule;
DayOfWeek myFirstDOW = myCI.DateTimeFormat.FirstDayOfWeek;
// Displays the number of the current week relative to the beginning of the year.
Console.WriteLine( "The CalendarWeekRule used for the en-US culture is {0}.", myCWR );
Console.WriteLine( "The FirstDayOfWeek used for the en-US culture is {0}.", myFirstDOW );
Console.WriteLine( "Therefore, the current week is Week {0} of the current year.", myCal.GetWeekOfYear( DateTime.Now, myCWR, myFirstDOW ));
// Displays the total number of weeks in the current year.
DateTime LastDay = new System.DateTime( DateTime.Now.Year, 12, 31 );
Console.WriteLine( "There are {0} weeks in the current year ({1}).", myCal.GetWeekOfYear( LastDay, myCWR, myFirstDOW ), LastDay.Year );
}
}
Ответ 4
My.Computer.Info.InstalledUICulture.DateTimeFormat.Calendar.GetWeekOfYear(yourDateHere, CalendarWeekRule.FirstDay, My.Computer.Info.InstalledUICulture.DateTimeFormat.FirstDayOfWeek)
Что-то вроде этого...
Ответ 5
Я знаю, что это уже поздно, но так как он появился в моем поиске, я подумал, что я бы выбрал другое решение. Это было решение С#.
(int)(Math.Ceiling((decimal)startDate.Day / 7)) + (((new DateTime(startDate.Year, startDate.Month, 1).DayOfWeek) > startDate.DayOfWeek) ? 1 : 0);
Ответ 6
Если вам нужен номер недели ISO 8601, в котором недели начинаются с понедельника, все недели - семь дней, а неделя 1 - неделя, содержащая первый четверг года, это может быть решение.
Так как, кажется, не существует .Net-культуры, которая дает правильный номер недели ISO-8601, я бы стал обходить встроенное определение недели alltogether и выполнять вычисления вручную, а не пытаться исправить частично правильный результат.
В результате я получил следующий метод расширения:
public static int GetIso8601WeekNumber(this DateTime date)
{ var thursday = date.AddDays(3 - ((int)date.DayOfWeek + 6) % 7);
return 1 + (thursday.DayOfYear - 1) / 7;
}
Прежде всего, ((int) date.DayOfWeek + 6)% 7) определяет день недели, 0 = понедельник, 6 = воскресенье.
date.AddDays(- ((int) date.DayOfWeek + 6)% 7) определяет дату понедельника, преследующую запрошенный номер недели.
Спустя три дня - целевой день, который определяет, в каком году проходит неделя.
Если вы делите (нулевой) день-число в течение года на семь (округлить вниз), вы получите номер недели на нулевой основе в году.
В С# результаты целочисленного вычисления округлены вниз неявно.
Ответ 7
var cultureInfo = CultureInfo.CurrentCulture; var calendar = cultureInfo.Calendar;
var calendarWeekRule = cultureInfo.DateTimeFormat.CalendarWeekRule;
var firstDayOfWeek = cultureInfo.DateTimeFormat.FirstDayOfWeek;
var lastDayOfWeek = cultureInfo.LCID == 1033 //En-us
? DayOfWeek.Saturday
: DayOfWeek.Sunday;
var lastDayOfYear = new DateTime(date.Year, 12, 31);
//Check if this is the last week in the year and it doesn`t occupy the whole week
var weekNumber = calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek);
return weekNumber == 53 && lastDayOfYear.DayOfWeek != lastDayOfWeek
? 1
: weekNumber;
Это хорошо работает как для американской, так и для русской культур. ИСО 8601 также будет правильным, потому что в понедельник начинается русская неделя.