147

週の最初の日 (ここヨーロッパでは月曜日) の日付を取得する簡単な方法を誰でも知っています。年と週番号はわかりますか?これを C# で実行します。

4

25 に答える 25

283

@RobinAnderssonによる修正があっても、@HenkHoltermanによる解決策に問題がありました。

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);
}       
于 2012-01-30T13:55:53.197 に答える
51

ノート

以下の回答では、.NET Calendar ルールを使用しています。ISO8601への適合を約束するものではありません。必要な場合は、ここで他の回答のいくつかを参照してください。週の番号付けはごちゃごちゃしています。最初に従う必要があるルールを常に見つけてください。


以下のコードは、2009 年第 1 週の始まりを 2008 年 12 月 29 日に正しく設定します。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;
}
于 2009-03-19T15:06:38.130 に答える
37

HenkHoltermanが提供するソリューションが好きです。しかし、もう少し文化に依存しないようにするには、現在の文化の週の最初の日を取得する必要があります(必ずしも月曜日とは限りません)。

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);
}
于 2009-05-27T10:07:44.163 に答える
10

最も簡単な方法は、おそらくその年の最初の月曜日を見つけて、関連する週数を追加することです。ここにいくつかのサンプルコードがあります。ちなみに、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);
    }
}
于 2009-03-19T14:18:53.720 に答える
4

Fluent DateTime を使用http://fluentdatetime.codeplex.com/

        var year = 2009;
        var firstDayOfYear = new DateTime(year, 1, 1);
        var firstMonday = firstDayOfYear.Next(DayOfWeek.Monday);
        var weeksDateTime = 12.Weeks().Since(firstMonday);
于 2009-09-04T12:50:15.900 に答える
4

個人的には、カルチャ情報を利用して曜日を取得し、カルチャの最初の曜日にループします。うまく説明できているかどうかわかりませんが、例を次に示します。

    public DateTime GetFirstDayOfWeek(int year, int weekNumber)
    {
        return GetFirstDayOfWeek(year, weekNumber, Application.CurrentCulture);
    }

    public DateTime GetFirstDayOfWeek(int year, int weekNumber,
        System.Globalization.CultureInfo culture)
    {
        System.Globalization.Calendar calendar = culture.Calendar;
        DateTime firstOfYear = new DateTime(year, 1, 1, calendar);
        DateTime targetDay = calendar.AddWeeks(firstOfYear, weekNumber);
        DayOfWeek firstDayOfWeek = culture.DateTimeFormat.FirstDayOfWeek;

        while (targetDay.DayOfWeek != firstDayOfWeek)
        {
            targetDay = targetDay.AddDays(-1);
        }

        return targetDay;
    }
于 2009-03-19T15:32:11.337 に答える
4

これは、Google アナリティクスの週番号と互換性のある方法であり、Intel で内部的に使用したのと同じ番号付けスキームでもあり、他の多くのコンテキストでも使用されていると確信しています.

// Google Analytics does not follow ISO standards for date.
// It numbers week 1 starting on Jan. 1, regardless what day of week it starts on.
// It treats Sunday as the first day of the week.
// The first and last weeks of a year are usually not complete weeks.
public static DateTime GetStartDateTimeFromWeekNumberInYear(int year, uint weekOfYear)
{
  if (weekOfYear == 0 || weekOfYear > 54) throw new ArgumentException("Week number must be between 1 and 54! (Yes, 54... Year 2000 had Jan. 1 on a Saturday plus 53 Sundays.)");

  // January 1 -- first week.
  DateTime firstDayInWeek = new DateTime(year, 1, 1);
  if (weekOfYear == 1) return firstDayInWeek;

  // Get second week, starting on the following Sunday.      
  do
  {
    firstDayInWeek = firstDayInWeek.AddDays(1);
  } while (firstDayInWeek.DayOfWeek != DayOfWeek.Sunday);

  if (weekOfYear == 2) return firstDayInWeek;

  // Now get the Sunday of whichever week we're looking for.
  return firstDayInWeek.AddDays((weekOfYear - 2)*7);
}
于 2014-02-26T19:35:24.757 に答える
2

週番号が 1 から始まると仮定します。

DateTime dt =  new DateTime(YearNumber, 1, 1).AddDays((WeekNumber - 1) * 7 - (WeekNumber == 1 ? 0 : 1));
return dt.AddDays(-(int)dt.DayOfWeek);

これにより、任意の週の最初の日が得られます。私はそれについて多くのテストを行っていませんが、うまくいくようです。これは、私が Web で見つけた他のほとんどのソリューションよりも小さいので、共有したいと思いました。

于 2010-07-09T03:43:27.133 に答える
2

スウェーデンで使用されているISO 8601:1988 によると、年の最初の週は、新年に少なくとも 4 日が含まれる最初の週です。

したがって、週が月曜日に始まる場合、どの年の最初の木曜日も最初の週に含まれます。そこから DateAdd または DateDiff を実行できます。

于 2009-03-19T16:10:46.907 に答える
2

上記のいくつかのコードを試してみましたが、一部には小さな間違いがあります。異なる年を別の開始曜日で試すと、それらが表示されます。Jon Skeet のコードを使用して修正すると、非常に単純なコードで動作します。

Public Function YearWeekDayToDateTime(ByVal year As Integer, ByVal weekDay As Integer, ByVal week As Integer) As DateTime
   ' weekDay, day you want
    Dim startOfYear As New DateTime(year, 1, 1)
    Dim startOfYearFixDay As Integer

    If startOfYear.DayOfWeek <> DayOfWeek.Sunday Then
        startOfYearFixDay = startOfYear.DayOfWeek
    Else
        startOfYearFixDay = 7
    End If

    Return startOfYear.AddDays((7 * (week)) - startOfYearFixDay + weekDay)
End Function
于 2011-08-26T10:13:35.390 に答える
2

.NET 用の無料のTime Period Library には、ISO 8601準拠クラスWeekが含まれています。

// ----------------------------------------------------------------------
public static DateTime GetFirstDayOfWeek( int year, int weekOfYear )
{
  return new Week( year, weekOfYear ).FirstDayStart;
} // GetFirstDayOfWeek
于 2011-05-13T17:07:13.113 に答える
2

これは私にとってはうまくいきました。異なるカルチャで式をテストするためのパラメーターとして cultureinfo を期待するという利点もあります。空の場合、現在のカルチャ情報を取得します... 有効な値は次のとおりです: "it"、"en-us"、"fr"、... ando など。秘訣は、年の最初の日の週番号を減算することです。これは、最初の日が最初の週内にあることを示すために 1 になる場合があります。お役に立てれば。

Public Shared Function FirstDayOfWeek(ByVal year As Integer, ByVal weekNumber As Integer, ByVal culture As String) As Date
    Dim cInfo As System.Globalization.CultureInfo
    If culture = "" Then
        cInfo = System.Globalization.CultureInfo.CurrentCulture
    Else
        cInfo = System.Globalization.CultureInfo.CreateSpecificCulture(culture)
    End If
    Dim calendar As System.Globalization.Calendar = cInfo.Calendar
    Dim firstOfYear As DateTime = New DateTime(year, 1, 1, calendar)
    Dim firstDayWeek As Integer = calendar.GetWeekOfYear(firstOfYear, cInfo.DateTimeFormat.CalendarWeekRule, cInfo.DateTimeFormat.FirstDayOfWeek)
    weekNumber -= firstDayWeek
    Dim targetDay As DateTime = calendar.AddWeeks(firstOfYear, weekNumber)
    Dim fDayOfWeek As DayOfWeek = cInfo.DateTimeFormat.FirstDayOfWeek

    While (targetDay.DayOfWeek <> fDayOfWeek)
        targetDay = targetDay.AddDays(-1)
    End While
    Return targetDay
End Function
于 2013-03-29T17:58:28.140 に答える
1

Mikael Svensson が提供したコードを単純化しました。これは、ヨーロッパの多くの国で正しいものです。

public static DateTime FirstDateOfWeekIso8601(int year, int week)
{
        var firstThursdayOfYear = new DateTime(year, 1, 1);
        while (firstThursdayOfYear.DayOfWeek != DayOfWeek.Thursday)
        {
            firstThursdayOfYear = firstThursdayOfYear.AddDays(1);
        }

        var startDateOfWeekOne = firstThursdayOfYear.AddDays(-(DayOfWeek.Thursday - DayOfWeek.Monday));

        return startDateOfWeekOne.AddDays(7 * (week - 1));        
}
于 2015-07-10T10:39:01.040 に答える
0

I used one of the solutions but it gave me wrong results, simply because it counts Sunday as a first day of the week.

I changed:

var firstDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber - 1) * 7);
var lastDay = firstDay.AddDays(6);

to:

var lastDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber) * 7);
var firstDay = lastDay.AddDays(-6);

and now it is working as a charm.

于 2012-08-09T16:10:55.210 に答える
0

現在、ISO 8601week 番号を正しく処理する C# クラスはありません。文化をインスタンス化し、最も近いものを探して修正することはできますが、完全な計算を自分で行う方がよいと思います。

    /// <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;
    }
于 2016-11-08T15:48:01.337 に答える
0

オーバーライドを使用して、トーマスのソリューションを少し改善しました。

   public static DateTime FirstDateOfWeek(int year, int weekOfYear)
    {
      return Timer.FirstDateOfWeekOfMonth(year, 1, weekOfYear);
    }

    public static DateTime FirstDateOfWeekOfMonth(int year, int month, 
    int weekOfYear)
    {
      DateTime dtFirstDayOfMonth = new DateTime(year, month, 1);

       //I also commented out this part:
      /*
      if (firstWeek <= 1)
      {
        weekOfYear -= 1;
      }
      */

そうでなければ、日付は1週間前でした..

トーマス、ありがとう。

于 2011-03-30T05:29:18.310 に答える
0

提案されたソリューションは完全ではありません。CalendarWeekRule.FirstFullWeek でのみ機能します。他のタイプの週ルールは機能しません。これは、次のテスト ケースを使用して確認できます。

foreach (CalendarWeekRule rule in Enum.GetValues(typeof(CalendarWeekRule)))
{
    for (int year = 1900; year < 2000; year++)
    {
        DateTime date = FirstDateOfWeek(year, 1, rule);
        Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, rule, DayOfWeek.Monday) == 1);
        Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(-1), rule, DayOfWeek.Monday) != 1);
    }
}
于 2012-09-21T17:57:28.283 に答える
0

両方向に変換するには、こちらを参照してください: ISO の週の日付に関するウィキペディアの記事

于 2009-09-05T05:35:05.380 に答える
0

私は提案された解決策の洗練されたバージョンを作成しました。これはよりシンプルで、firstDayOfWeek をパラメータ化します。

public static DateTime GetFirstDayOfWeek(int year, int week, DayOfWeek firstDayOfWeek)
{
    return GetWeek1Day1(year, firstDayOfWeek).AddDays(7 * (week - 1));
}

public static DateTime GetWeek1Day1(int year, DayOfWeek firstDayOfWeek)
{
    DateTime date = new DateTime(year, 1, 1);

    // Move towards firstDayOfWeek
    date = date.AddDays(firstDayOfWeek - date.DayOfWeek);

    // Either 1 or 52 or 53
    int weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFullWeek, firstDayOfWeek);

    // Move forwards 1 week if week is 52 or 53
    date = date.AddDays(7 * System.Math.Sign(weekOfYear - 1));

    return date;
}
于 2012-09-21T18:08:09.110 に答える
0

第 1 週は、月曜日から始まり、その年の最初の木曜日を含む週として定義されます。

于 2009-03-19T15:03:18.480 に答える