Мне нужно показать календарную неделю даты, используя ту же нумерацию, что и в Outlook.
Нумерация должна соответствовать итальянской (it-IT) культуре.
Календарь Outlook настроен с использованием понедельника в качестве первого дня неделю и «1 января всегда в неделю 1».
Пример другого календаря, использующего те же логики нумерации c , приведен здесь (возможно, вам нужно включить номера недели).
Я пробовал разные методы, но я не получаю правильный номер недели с некоторыми датами.
В частности, я пытался использовать:
Calendar
возвращено с CultureInfo.GetCulture("it-IT")
GregorianCalendar
ISOWeek
Некоторые даты, которые я пробовал:
- 31 декабря 200
- 29 марта 2021
- 31 декабря 2012
- 21 декабря 1992
- 30 декабря 2019
Единственный надежный способ Я нашел правильный номер недели, чтобы вычислить его сам, но мне не очень нравится идея зависеть от моего кода вычисления даты (я не могу быть на 100% уверен, что нашел правильный лог c Я не могу проверить каждую возможную дату).
Ниже приведена программа, показывающая различные результаты для каждого метода, который я пробовал, и способ вычисления номеров недель вручную.
Вы также можете попробовать его здесь.
Вывод примера (в виде изображения для отображения различных цветов):
Так что вопрос: есть ли встроенный способ получить номера недели из даты, используя те же номера нумерации c, используемые Outlook?
РЕДАКТИРОВАТЬ:
Я уже пытался использовать CalendarWeekRule.FirstFourDayWeek
и CalendarWeekRule.FirstFullWeek
Пример программы, о которой я говорил:
public sealed class Program
{
private static Calendar italianCalendar = CultureInfo.GetCultureInfo("it-IT").Calendar;
private static Calendar plainGregorianCalendar = new GregorianCalendar();
public static void Main()
{
var _31stOfDecember2000 = new DateTime(2000, 12, 31);
var _29thOfMarch2021 = new DateTime(2021, 3, 29);
var _31stOfDecember2012 = new DateTime(2012, 12, 31);
var _21stDecember1992 = new DateTime(1992, 12, 21);
var _30thDecember2019 = new DateTime(2019, 12, 30);
var _1stOfJanuary2013 = new DateTime(2013, 1, 1);
PrintWeek(_31stOfDecember2000, 53);
PrintWeek(_29thOfMarch2021, 14);
PrintWeek(_31stOfDecember2012, 1);
PrintWeek(_21stDecember1992, 52);
PrintWeek(_30thDecember2019, 1);
PrintWeek(_1stOfJanuary2013, 1);
Console.ReadKey();
}
private static void PrintWeek(DateTime date, int expectedWeek)
{
var isoWeek = ISOWeek.GetWeekOfYear(date);
var italianCalendarWeek = italianCalendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
var gregorianCalendarWeek = plainGregorianCalendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
var manuallyCalculatedWeek = CalculateWeek(date);
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Date: {0:yyyy MMMM dd} - Expected week {1}", date, expectedWeek);
Console.ForegroundColor = isoWeek == expectedWeek ? ConsoleColor.Green : ConsoleColor.Red;
Console.WriteLine("ISO Week: {0}", isoWeek);
Console.ForegroundColor = italianCalendarWeek == expectedWeek ? ConsoleColor.Green : ConsoleColor.Red;
Console.WriteLine("Italian calendar Week: {0}", italianCalendarWeek);
Console.ForegroundColor = gregorianCalendarWeek == expectedWeek ? ConsoleColor.Green : ConsoleColor.Red;
Console.WriteLine("Gregorian calendar Week: {0}", gregorianCalendarWeek);
Console.ForegroundColor = manuallyCalculatedWeek == expectedWeek ? ConsoleColor.Green : ConsoleColor.Red;
Console.WriteLine("Manually calculated Week: {0}", manuallyCalculatedWeek);
Console.WriteLine();
}
public static int CalculateWeek(DateTime date)
{
var firstDayOfFirstWeekOfDateYear = StartOfWeekOfYear(date.Year, 1);
var firstDayOfFirstWeekOfNextYear = StartOfWeekOfYear(date.Year + 1, 1);
var lastDayOfLastWeekOfDateYear = firstDayOfFirstWeekOfNextYear.AddDays(-1);
var timePassedSinceFirstWeek = date - firstDayOfFirstWeekOfDateYear;
var daysPassedSinceFirstWeek = timePassedSinceFirstWeek.Days;
var timePassedBetweenFirstAndEndOfYear = lastDayOfLastWeekOfDateYear - firstDayOfFirstWeekOfDateYear;
var daysPassedBetweenFirstAndEndOfYear = timePassedBetweenFirstAndEndOfYear.Days;
var weeksOfDateYear = (daysPassedBetweenFirstAndEndOfYear / 7) + 1;
//If the week number surpasses the effective number of weeks of the year it is wrapped around the next year using modulo operator
//Modulo will wrap the week number around the Year weeks leaving the reminder of the calculation as the Week number of the next year.
var week = (daysPassedSinceFirstWeek / 7 % weeksOfDateYear) + 1;
return week;
}
private static DateTime StartOfWeekOfYear(int year, int week)
{
var firstOfJanuary = new DateTime(year, 1, 1);
var dayOfWeekFirstOfJanuary = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(firstOfJanuary);
//Sunday is 0 instead of 7, screwing calculations over
var dayOfWeekOffset = dayOfWeekFirstOfJanuary == DayOfWeek.Sunday ? -6 : DayOfWeek.Monday - dayOfWeekFirstOfJanuary;
var daysOffset = (7 * (week - 1)) + dayOfWeekOffset;
return firstOfJanuary.AddDays(daysOffset);
}