【发布时间】:2020-03-14 16:55:45
【问题描述】:
我必须使用与 Outlook 中相同的编号来显示日期的日历周。
编号必须遵循意大利 (it-IT) 文化。
Outlook 日历配置为使用星期一作为一周的第一天,并且“1 月 1 日始终在第 1 周”。
另一个使用相同编号逻辑is here 的日历示例(也许您需要打开周数)。
我尝试了不同的方法,但我没有得到正确的星期数和一些日期。
特别是,我尝试过使用:
-
Calendar从CultureInfo.GetCulture("it-IT")返回 GregorianCalendarISOWeek
我尝试的一些日期是:
- 200 年 12 月 31 日
- 2021 年 3 月 29 日
- 2012 年 12 月 31 日
- 1992 年 12 月 21 日
- 2019 年 12 月 30 日
我发现获得正确周数的唯一可靠方法是自己计算,但我真的不喜欢必须依赖我的日期计算代码的想法(我不能 100% 肯定有发现正确的逻辑我无法测试每个可能的日期)。
下面有一个程序显示了我尝试的每种方法的各种结果以及我如何手动计算周数。
You can also try it online here.
所以问题是:是否有一种内置方法可以使用 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);
}
【问题讨论】:
-
您阅读stackoverflow.com/questions/11154673/… 的答案了吗?我认为该页面上扩展方法的输出符合您的要求。
-
@PranavNegandhi 似乎它使用的是由静态类
ISOWeek实现的ISO8601 周编号,我尝试过但无济于事。此外,ISO 周编号不允许在一年中拆分周,这似乎是我的 Outlook 日历和意大利日历正在做的事情 -
您是否尝试过使用
CalendarWeekRule.FirstFourDayWeek? -
@AimusSage 是的,同样没有多大成功。我已更新问题以添加此详细信息
标签: c# date .net-core calendar