0

問題は、以前に計算された「週番号」から DateTime を取得する組み込みの方法がないように見えることです。

私がやりたいことは、基本的に、これをすべての時間とすべての文化的カレンダーで機能させることです.

  DateTime dt1 = new DateTime.Now;
  int week = cal.GetWeekOfYear(dt);
  DateTime dt2 = GetDateTimeFromYearAndWeek(dt.Year, week);

  if (dt1 < dt2 || dt2 > dt2.AddDays(7.0))
  {
    throw new Exception("new datetime limits do not span existing datetime;
  }

問題の 1 つは、一部の文化では、呼び出しがdt.Yearとは異なるcal.GetWeekOfYear(dt)年の正しい週番号を返すことだと思います。つまり、私の架空の通話への通話では使用できません。GetDateTimeFromYearAndWeek

4

1 に答える 1

0

私自身の答えは 3 倍です。Calendar.GetWeekOfYear 最初に、今年はDateTimeオブジェクトの年と同じではない可能性があるため、週の「年」を返すラッパーを思い付きました。

    public static void GetWeek(DateTime dt, CultureInfo ci, out int week, out int year)
    {
        year = dt.Year;
        week = ci.Calendar.GetWeekOfYear(dt, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);

        int prevweek = ci.Calendar.GetWeekOfYear(dt.AddDays(-7.0), ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);

        if (prevweek + 1 == week) {
            // year of prevweek should be correct
            year = dt.AddDays(-7.0).Year;
        } else {
            // stay here
            year = dt.Year;
        }
    }

次に、ここに答えの要点があります。これにより、yearandweekOfYearが逆になり、DateTimeオブジェクトに戻ります。これは、新年の特異点 (52 または 53 が 1 にラップする場合とラップしない場合) の問題を回避するように思われるためです。また、2 つの DayOfWeek 値を比較する負のオフセットの問題を回避して、実際に週の最初の日である日付を見つけることによって日付を同期します。

    public static DateTime FirstDateOfWeek(int year, int weekOfYear, CultureInfo ci)
    {
        DateTime jul1 = new DateTime(year, 7, 1);
        while (jul1.DayOfWeek != ci.DateTimeFormat.FirstDayOfWeek)
        {
            jul1 = jul1.AddDays(1.0);
        }
        int refWeek = ci.Calendar.GetWeekOfYear(jul1, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);

        int weekOffset = weekOfYear - refWeek;

        return jul1.AddDays(7 * weekOffset );
    }

そして最後に、それを疑うすべての人に、これが私の単体テストです。これは、多くの日付と文化を循環させて、それらすべてで機能することを確認します.

    public static void TestDates()
    {
        foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures).Where((x)=>!x.IsNeutralCulture && x.Calendar.AlgorithmType == CalendarAlgorithmType.SolarCalendar))
        {

            for (int year = 2010; year < 2040; year++)
            {
                // first try a bunch of hours in this year
                // convert from date -> week -> date

                for (int hour = 0; hour < 356 * 24; hour+= 6)
                {
                    DateTime dt = new DateTime(year, 1, 1).AddHours(hour);
                    int ww;
                    int wyear;
                    Gener8.SerialNumber.GetWeek(dt, ci, out ww, out wyear);
                    if (wyear != year)
                    {
                        //Console.WriteLine("{0} warning: {1} {2} {3}", ci.Name, dt, year, wyear);
                    }
                    DateTime dt1 = Gener8.SerialNumber.FirstDateOfWeek(wyear, ww, ci);
                    DateTime dt2 = Gener8.SerialNumber.FirstDateOfWeek(wyear, ww, ci).AddDays(7.0);
                    if (dt < dt1 || dt > dt2)
                    {
                        Console.WriteLine("{3} Bad date {0} not between {1} and {2}", dt, dt1, dt2, ci.Name);
                    }
                }

                // next try a bunch of weeks in this year
                // convert from week -> date -> week

                for (int week = 1; week < 54; week++)
                {
                    DateTime dt0 = FirstDateOfWeek(year, week, ci);
                    int ww0;
                    int wyear0;
                    GetWeek(dt0, ci, out ww0, out wyear0);
                    DateTime dt1 = dt0.AddDays(6.9);
                    int ww1;
                    int wyear1;
                    GetWeek(dt1, ci, out ww1, out wyear1);
                    if ((dt0.Year == year && ww0 != week) ||
                        (dt1.Year == year && ww1 != week))
                    {
                        Console.WriteLine("{4} Bad date {0} ww0={1} ww1={2}, week={3}", dt0, ww0, ww1, week, ci.Name);
                    }
                }
            }
        }
    }
于 2013-05-14T22:27:44.927 に答える