我在谷歌上搜索了很多,找到了很多解决方案,但没有一个能告诉我2012-12-31的正确周数。即使是MSDN上的例子(链接)也失败了。

2012-12-31是星期一,所以应该是第一周,但是我尝试的每一种方法都给了我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;

更新

当date为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);
}

当前回答

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也是正确的,因为俄罗斯周从周一开始。

其他回答

问题是:你如何定义一个星期是在2012年还是2013年? 我猜,你的假设是,因为一周中有6天是在2013年,所以这周应该被标记为2013年的第一周。

我不确定这样做对不对。 那一周开始于2012年(12月31日星期一),所以它应该被标记为2012年的最后一周,因此它应该是2012年的53日。2013年的第一周应该从7号星期一开始。

现在,您可以使用星期几信息处理边缘周(一年中的第一个和最后一个星期)的特定情况。这完全取决于你的逻辑。

在。net 3.0及以后版本中,你可以使用isoweek . getweekofdate方法。

请注意,年+周数格式中的年份可能与DateTime中的年份不同,因为有些星期跨越了年份边界。

从上面il_guru的代码到Powershell端口:

function GetWeekOfYear([datetime] $inputDate)
{
   $day = [System.Globalization.CultureInfo]::InvariantCulture.Calendar.GetDayOfWeek($inputDate)
   if (($day -ge [System.DayOfWeek]::Monday) -and ($day -le [System.DayOfWeek]::Wednesday))
   {
      $inputDate = $inputDate.AddDays(3)
   }

   # Return the week of our adjusted day
   $weekofYear = [System.Globalization.CultureInfo]::InvariantCulture.Calendar.GetWeekOfYear($inputDate, [System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [System.DayOfWeek]::Monday)
   return $weekofYear
}

由于似乎没有. 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)日期。DayOfWeek + 6) % 7)确定所请求的周数之前的星期一。

三天后是目标星期四,这决定了一周是哪一年。

如果将一年中(以零为基数)的天数除以7(四舍五入),就会得到一年中(以零为基数)的周数。

在c#中,整数计算结果隐式向下舍入。

在PowerShell 7.x.y中: 如果您需要匹配的WeekYear,您将需要以下两个代码行。

[System.Globalization.ISOWeek]::GetWeekOfYear((get-date))
[System.Globalization.ISOWeek]::GetYear((get-date))