从周数计算日期

Bob*_*bby 128 .net c# week-number

任何人都知道一个简单的方法来获取本周第一天的日期(欧洲的星期一).我知道年份和周数?我打算用C#做这个.

Mik*_*son 235

我对@HenkHolterman的解决方案有疑问,即使是@RobinAndersson的解决方案.

阅读ISO 8601标准很好地解决了这个问题.使用第一个星期四作为目标,而不是星期一.以下代码也适用于2009年第53周.

public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
    DateTime jan1 = new DateTime(year, 1, 1);
    int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;

    // Use first Thursday in January to get first week of the year as
    // it will never be in Week 52/53
    DateTime firstThursday = jan1.AddDays(daysOffset);
    var cal = CultureInfo.CurrentCulture.Calendar;
    int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

    var weekNum = weekOfYear;
    // As we're adding days to a date in Week 1,
    // we need to subtract 1 in order to get the right date for week #1
    if (firstWeek == 1)
    {
        weekNum -= 1;
    }

    // Using the first Thursday as starting week ensures that we are starting in the right year
    // then we add number of weeks multiplied with days
    var result = firstThursday.AddDays(weekNum * 7);

    // Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
    return result.AddDays(-3);
}       
Run Code Online (Sandbox Code Playgroud)

  • 我已经尝试了几乎所有这里给出的解决方案,这个是现在唯一正确适用于我的解决方案.目前,它是2012年2月7日.本周nr是#6.这段代码正确地给了我2月6日作为一周的开始日期.其他解决方案都给了我2月13日,这实际上是第7周的开始日期. (2认同)
  • 建议:制作方法名称的"ISO8601",因为根本没有通用的"正确"答案. (2认同)

Hen*_*man 50

笔记

以下答案使用 .NET 日历规则。它不承诺符合 ISO8601。当您需要时,请在此处查看其他一些答案。周编号是一团糟,总是试着先找出你需要遵循的规则。


下面的代码正确地将 2009 年第 1 周的开始时间设为 29-12-2008。CalendarWeekRule 可能应该是一个参数。

请注意,weekNum 应该 >= 1

static DateTime FirstDateOfWeek(int year, int weekNum, CalendarWeekRule rule)
{
    Debug.Assert(weekNum >= 1);

    DateTime jan1 = new DateTime(year, 1, 1);

    int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
    DateTime firstMonday = jan1.AddDays(daysOffset);
    Debug.Assert(firstMonday.DayOfWeek == DayOfWeek.Monday);

    var cal = CultureInfo.CurrentCulture.Calendar;
    int firstWeek = cal.GetWeekOfYear(firstMonday, rule, DayOfWeek.Monday);

    if (firstWeek <= 1)
    {
        weekNum -= 1;
    }

    DateTime result = firstMonday.AddDays(weekNum * 7);

    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这是完全正确的。使用 `CalendarWeekRule.FirstFourDayWeek` 和 2006 年和第 32 周,要返回的正确日期是 2006 年 8 月 7 日。但它返回 8 月 14 日。我将 GetWeekOfYear 调用更改为使用 firstMonday 而不是 jan1,它似乎有效 (6认同)
  • 不仅是 2012 年出现问题的玛雅人。 2012 年第一周的代码行为不端,更改了 cal.GetWeekOfYear(jan1, rule, DayOfWeek.Monday); 到 cal.GetWeekOfYear(firstMonday, rule, DayOfWeek.Monday); 哪个更正了它。 (3认同)
  • 发布了一个答案,其中包含显然适用于所有边界特殊情况的代码。 (2认同)

小智 36

我喜欢Henk Holterman提供的解决方案.但是为了更加独立于文化,你必须得到当前文化的一周的第一天(它并不总是星期一):

using System.Globalization;

static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
  DateTime jan1 = new DateTime(year, 1, 1);

  int daysOffset = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;

  DateTime firstMonday = jan1.AddDays(daysOffset);

  int firstWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(jan1, CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);

  if (firstWeek <= 1)
  {
    weekOfYear -= 1;
  }

  return firstMonday.AddDays(weekOfYear * 7);
}
Run Code Online (Sandbox Code Playgroud)

  • `firstMonday`是一个糟糕的变量名,可能不是星期一.=) (5认同)

Jon*_*eet 9

最简单的方法可能是查找一年中的第一个星期一,然后添加相关的周数.这是一些示例代码.假设从1开始的周数,顺便说一下:

using System;

class Test
{
    static void Main()
    {
        // Show the third Tuesday in 2009. Should be January 20th
        Console.WriteLine(YearWeekDayToDateTime(2009, DayOfWeek.Tuesday, 3));
    }

    static DateTime YearWeekDayToDateTime(int year, DayOfWeek day, int week)
    {
        DateTime startOfYear = new DateTime (year, 1, 1);

        // The +7 and %7 stuff is to avoid negative numbers etc.
        int daysToFirstCorrectDay = (((int)day - (int)startOfYear.DayOfWeek) + 7) % 7;

        return startOfYear.AddDays(7 * (week-1) + daysToFirstCorrectDay);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是今年的第一个星期一可能属于上一年的第52 | 53周. (4认同)
  • 这取决于你想如何定义事物。不幸的是,我们这里没有太多信息……但我希望这有用。 (2认同)

khe*_*ang 5

更新:.NET Core 3.0和.NET Standard 2.1附带了此类型。

好消息!一个拉请求加入System.Globalization.ISOWeek到.NET的核心刚刚合并,目前内定为3.0版本。希望它将在不远的将来传播到其他.NET平台。

您应该能够使用该ISOWeek.ToDateTime(int year, int week, DayOfWeek dayOfWeek)方法进行计算。

您可以在此处找到源代码。