web-dev-qa-db-ja.com

特定の日付の週番号を計算/検索するにはどうすればよいですか?

特定の日付の週番号を計算/検索するにはどうすればよいですか?

26
cllpse
var currentCulture = CultureInfo.CurrentCulture;
var weekNo = currentCulture.Calendar.GetWeekOfYear(
                new DateTime(2013, 12, 31),
                currentCulture.DateTimeFormat.CalendarWeekRule,
                currentCulture.DateTimeFormat.FirstDayOfWeek);

これはnotISO 8601 と互換性があることに注意してください。スウェーデンではISO 8601 week 数値を使用しますが、カルチャが「sv-SE」に設定されている場合でも、CalendarWeekRuleFirstFourDayWeekであり、FirstDayOfWeekweekNo変数は、上記のコードで正しい1ではなく5に設定されます。

私はこれをスウェーデンの設定で試しただけですが、ISO 8601の週数を使用しているすべての国(オーストリア、ドイツ、スイスなど)がこの問題の影響を受けると確信しています。

Peter van Ooijen および Shawn Steele は、この問題に対して異なる解決策を持っています。

これがコンパクトなソリューションです

private static int WeekOfYearISO8601(DateTime date)
{
    var day = (int)CultureInfo.CurrentCulture.Calendar.GetDayOfWeek(date);
    return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(4 - (day == 0 ? 7 : day)), CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}

次の日付でテストされています

var datesAndISO8601Weeks = new Dictionary<DateTime, int>
                        {
                            {new DateTime(2000, 12, 31), 52},
                            {new DateTime(2001, 1, 1), 1},
                            {new DateTime(2005, 1, 1), 53},
                            {new DateTime(2007, 12, 31), 1},
                            {new DateTime(2008, 12, 29), 1},
                            {new DateTime(2010, 1, 3), 53},
                            {new DateTime(2011, 12, 31), 52},
                            {new DateTime(2012, 1, 1), 52},
                            {new DateTime(2013, 1, 2), 1},
                            {new DateTime(2013, 12, 31), 1},
                        };

foreach (var dateWeek in datesAndISO8601Weeks)
{
    Debug.Assert(WeekOfYearISO8601(dateWeek.Key) == dateWeek.Value, dateWeek.Key.ToShortDateString() + " should be week number " + dateWeek.Value + " but was " + WeekOfYearISO8601(dateWeek.Key));
}
72
Jonas Elfström
  public static int GetWeekNumber(DateTime dtPassed)
  {
          CultureInfo ciCurr = CultureInfo.CurrentCulture;
          int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
          return weekNum;
  }
4
Andriy Tkach

チェックアウト GetWeekOfYear MSDNには次の例があります。

using System;
using System.Globalization;


public class SamplesCalendar  {

   public static void Main()  {

      // Gets the Calendar instance associated with a CultureInfo.
      CultureInfo myCI = new CultureInfo("en-US");
      Calendar myCal = myCI.Calendar;

      // Gets the DTFI properties required by GetWeekOfYear.
      CalendarWeekRule myCWR = myCI.DateTimeFormat.CalendarWeekRule;
      DayOfWeek myFirstDOW = myCI.DateTimeFormat.FirstDayOfWeek;

      // Displays the number of the current week relative to the beginning of the year.
      Console.WriteLine( "The CalendarWeekRule used for the en-US culture is {0}.", myCWR );
      Console.WriteLine( "The FirstDayOfWeek used for the en-US culture is {0}.", myFirstDOW );
      Console.WriteLine( "Therefore, the current week is Week {0} of the current year.", myCal.GetWeekOfYear( DateTime.Now, myCWR, myFirstDOW ));

      // Displays the total number of weeks in the current year.
      DateTime LastDay = new System.DateTime( DateTime.Now.Year, 12, 31 );
      Console.WriteLine( "There are {0} weeks in the current year ({1}).", myCal.GetWeekOfYear( LastDay, myCWR, myFirstDOW ), LastDay.Year );

   }

}
4
SwDevMan81
My.Computer.Info.InstalledUICulture.DateTimeFormat.Calendar.GetWeekOfYear(yourDateHere, CalendarWeekRule.FirstDay, My.Computer.Info.InstalledUICulture.DateTimeFormat.FirstDayOfWeek)

このようなもの...

1
Bobby

ISO 8601週番号が必要な場合、週は月曜日で始まり、すべての週は7日であり、第1週はその年の最初の木曜日を含む週です。これが解決策になる場合があります。

正しいISO-8601週数を生成する.Netカルチャーがないように思われるため、評価者は組み込みの週の決定をすべてバイパスし、部分的に正しい結果を修正するのではなく、手動で計算を行います。

私が最終的に得たのは、次の拡張メソッドです。

public static int GetIso8601WeekNumber(this DateTime date)
{    var thursday = date.AddDays(3 - ((int)date.DayOfWeek + 6) % 7);
     return 1 + (thursday.DayOfYear - 1) / 7;
}

まず、((int)date.DayOfWeek + 6)%7)は、曜日番号を決定します。0=月曜日、6 =日曜日です。

date.AddDays(-((int)date.DayOfWeek + 6)%7)は、要求された週番号に先行する月曜日の日付を決定します。

3日後は、目標とする木曜日で、週が何年かを決定します。

年内の(ゼロベースの)日数を7で割ると(切り捨て)、その年の(ゼロベースの)週数が得られます。

C#では、整数の計算結果は暗黙的に切り捨てられます。

1
realbart

私はこれが遅いことを知っていますが、それが私の検索で出てきたので、私は別のソリューションを投入すると思いました。これはc#ソリューションでした。

(int)(Math.Ceiling((decimal)startDate.Day / 7)) + (((new DateTime(startDate.Year, startDate.Month, 1).DayOfWeek) > startDate.DayOfWeek) ? 1 : 0);  
1
GAdams

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);

         //Check if this is the last week in the year and it doesn`t occupy the whole week
        var weekNumber = calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek);
        return weekNumber == 53 && lastDayOfYear.DayOfWeek != lastDayOfWeek 
               ? 1 
               : weekNumber;

これは、米国とロシアの両方の文化でうまく機能します。 ISO 8601も正しくなります。これは、ロシアの週が月曜日から始まるためです。

0
Donskikh Andrei