我搜索了很多并找到了很多解决方案,但没有一个能为我提供2012-12-31的正确周数。甚至MSDN上的示例(link)都失败了。
2012-12-31是星期一,因此它应该是第1周,但我尝试的每种方法都给了我53.以下是我尝试过的一些方法:
来自MDSN图书馆:
DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
Calendar cal = dfi.Calendar;
return cal.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
解决方案2:
return new GregorianCalendar(GregorianCalendarTypes.Localized).GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
解决方案3:
CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;
更新
当日期为2012-12-31时,以下方法实际返回1。换句话说,我的问题是我的方法没有遵循ISO-8601标准。
// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
答案 0 :(得分:261)
正如本MSDN page所述,ISO8601周和.Net周编号之间存在细微差别。
您可以参考MSDN博客中的这篇文章以获得更好的解释:“ISO 8601 Week of Year format in Microsoft .Net”
简单地说,.Net允许数周分开,而ISO标准则没有。 在文章中还有一个简单的功能,可以获得一年中最后一周正确的ISO 8601周数。
更新以下方法实际上为2012-12-31
返回1,这在ISO 8601中是正确的(例如德国)。
// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
答案 1 :(得分:28)
一年可能超过52周。每年有52个完整周+ 1或+2(闰年)额外。他们弥补了第53周。
因此,每年至少有一天额外的一天。两个闰年。这些额外的日子是否被视为自己的独立周?
确实需要几周的时间取决于您一周的开始日期。让我们考虑一下2012年。
检查您当前的文化设置,看看它在一周的第一天使用了什么。
正如你所看到的,结果是53是正常的。
甚至可能有第54周。每隔28年发生1月1日和12月31日作为单独的星期。它也必须是闰年。
例如,2000年有54周。 1月1日(sat)是第一个星期的一天,12月31日(太阳)是第二个星期的一天。
var d = new DateTime(2012, 12, 31);
CultureInfo cul = CultureInfo.CurrentCulture;
var firstDayWeek = cul.Calendar.GetWeekOfYear(
d,
CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
int weekNum = cul.Calendar.GetWeekOfYear(
d,
CalendarWeekRule.FirstDay,
DayOfWeek.Monday);
int year = weekNum == 52 && d.Month == 1 ? d.Year - 1 : d.Year;
Console.WriteLine("Year: {0} Week: {1}", year, weekNum);
打印出:年份:2012周:54
将上面例子中的CalendarWeekRule更改为FirstFullWeek或FirstFourDayWeek,然后你将返回53.让我们在星期一保持开始日,因为我们正在与德国打交道。
所以第53周开始于2012-12-31星期一,持续一天然后停止。
53是正确的答案。如果想尝试,请将文化改为德国。
CultureInfo cul = CultureInfo.GetCultureInfo("de-DE");
答案 2 :(得分:15)
这是方式:
public int GetWeekNumber()
{
CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;
}
最重要的是CalendarWeekRule
参数。
答案 3 :(得分:11)
由于似乎没有.Net文化产生正确的ISO-8601周数,我宁愿完全绕过内置周确定,并手动进行计算,而不是尝试纠正部分正确的结果。
我最终得到的是以下扩展方法:
/// <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;
}
首先,((int)date.DayOfWeek + 6) % 7)
确定工作日编号,0 =星期一,6 =星期日。
date.AddDays(-((int)date.DayOfWeek + 6) % 7)
确定所请求周数之前的星期一的日期。
三天后是星期四的目标,它决定了一周中的哪一年。
如果您将年内的(从零开始)日期数除以7(向下舍入),您将获得该年度的(零基础)周数。
在c#中,整数计算结果是隐式舍入的。
答案 4 :(得分:6)
在.NET 3.0及更高版本中,您可以使用ISOWeek.GetWeekOfDate
-Method。
请注意,年+周数字格式中的年份可能与DateTime
的年份有所不同,因为周跨越了年份边界。
答案 5 :(得分:5)
该类型具有以下签名,该签名应涵盖大多数ISO week需求:
System.Globalization.ISOWeek
您可以找到源代码here。
答案 6 :(得分:3)
来自 il_guru 上面代码的Powershell端口的C#:
About to call a generated method: I am a generated method
答案 7 :(得分:2)
使用c#和DateTime类确定周数ISO 8601样式的最简单方法。
问这个:今年星期四的星期四是星期四。 答案等于想要的周数。
var dayOfWeek = (int)moment.DayOfWeek;
// Make monday the first day of the week
if (--dayOfWeek < 0)
dayOfWeek = 6;
// The whole nr of weeks before this thursday plus one is the week number
var weekNumber = (moment.AddDays(3 - dayOfWeek).DayOfYear - 1) / 7 + 1;
答案 8 :(得分:1)
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);
var weekNumber = calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek);
//Check if this is the last week in the year and it doesn`t occupy the whole week
return weekNumber == 53 && lastDayOfYear.DayOfWeek != lastDayOfWeek
? 1
: weekNumber;
它适用于美国和俄罗斯文化。 ISO 8601也是正确的,因为俄罗斯周从星期一开始。
答案 9 :(得分:0)
在 PowerShell 7.x.y 中: 如果您需要匹配的 WeekYear,您将需要以下两个代码行。
[System.Globalization.ISOWeek]::GetWeekOfYear((get-date))
[System.Globalization.ISOWeek]::GetYear((get-date))
答案 10 :(得分:0)
如果您没有 .NET 5.0,请扩展 DateTime 类以包含周数。
import { createApi } from "unsplash-js"
答案 11 :(得分:0)
假设我们的一周从星期一开始,这两种方法将有所帮助
/// <summary>
/// Returns the weekId
/// </summary>
/// <param name="DateTimeReference"></param>
/// <returns>Returns the current week id</returns>
public static DateTime GetDateFromWeek(int WeekReference)
{
//365 leap
int DaysOffset = 0;
if (WeekReference > 1)
{
DaysOffset = 7;
WeekReference = WeekReference - 1;
}
DateTime DT = new DateTime(DateTime.Now.Year, 1, 1);
int CurrentYear = DT.Year;
DateTime SelectedDateTime = DateTime.MinValue;
while (CurrentYear == DT.Year)
{
int TheWeek = WeekReportData.GetWeekId(DT);
if (TheWeek == WeekReference)
{
SelectedDateTime = DT;
break;
}
DT = DT.AddDays(1.0D);
}
if (SelectedDateTime == DateTime.MinValue)
{
throw new Exception("Please check week");
}
return SelectedDateTime.AddDays(DaysOffset);
}
/// <summary>
/// Returns the weekId
/// </summary>
/// <param name="DateTimeReference"></param>
/// <returns>Returns the current week id</returns>
public static int GetWeekId(DateTime DateTimeReference)
{
CultureInfo ciCurr = CultureInfo.InvariantCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(DateTimeReference,
CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
return weekNum;
}
答案 12 :(得分:0)
根据il_guru的回答,我根据自己的需要创建了该版本,该版本还返回了年份成分。
/// <summary>
/// This presumes that weeks start with Monday.
/// Week 1 is the 1st week of the year with a Thursday in it.
/// </summary>
/// <param name="time">The date to calculate the weeknumber for.</param>
/// <returns>The year and weeknumber</returns>
/// <remarks>
/// Based on Stack Overflow Answer: https://stackoverflow.com/a/11155102
/// </remarks>
public static (short year, byte week) GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
var week = (byte)CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return ((short)(week >= 52 & time.Month == 1 ? time.Year - 1 : time.Year), week);
}
答案 13 :(得分:0)
这里是il_guru的答案的扩展版本和可为空的版本。
public static int GetIso8601WeekOfYear(this DateTime time)
{
var 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 int? GetIso8601WeekOfYear(this DateTime? time)
{
return time?.GetIso8601WeekOfYear();
}
new DateTime(2019, 03, 15).GetIso8601WeekOfYear(); //returns 11
((DateTime?) new DateTime(2019, 03, 15)).GetIso8601WeekOfYear(); //returns 11
((DateTime?) null).GetIso8601WeekOfYear(); //returns null
答案 14 :(得分:0)
DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
DateTime date1 = new DateTime(2011, 1, 1);
Calendar cal = dfi.Calendar;
Console.WriteLine("{0:d}: Week {1} ({2})", date1,
cal.GetWeekOfYear(date1, dfi.CalendarWeekRule,
dfi.FirstDayOfWeek),
cal.ToString().Substring(cal.ToString().LastIndexOf(".") + 1));
答案 15 :(得分:0)
问题是:您如何定义一周是在2012年还是在2013年? 我想,您的假设是,自2013年的6天以来,本周应标记为2013年的第一周。
不确定这是否是正确的方法。 那个星期开始于2012年(12月31日星期一),所以它应该被标记为2012年的最后一周,因此它应该是2012年的第53周。2013年的第一周应该从星期一到7日开始。
现在,您可以使用星期几信息处理边缘周(一年中的第一周和最后一周)的特定情况。这一切都取决于你的逻辑。
答案 16 :(得分:-1)
如果是一年(52 x 7 = 364),则一年有52周和1天或2天。 2012-12-31将是53周,一周只有2天,因为2012年是一年。
答案 17 :(得分:-2)
public int GetWeekNumber()
{
CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(DateTime.Now,
CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;
}