문제

에 따르면 공식 (Gregorian) 달력, 2008 년 29/12/2008의 주 번호는 1입니다. 52 주 마지막 날 (예 : 28/12) 이후에는 연중 3 일 이하가 남아 있기 때문입니다. 이상하지만, 규칙은 규칙입니다.

이 달력에 따르면 2008/2009의 경계 값이 있습니다.

  • 28/12는 52 주차입니다
  • 29/12는 1 주차입니다
  • 1/1은 1 주차입니다
  • 8/1은 2 주차입니다

C#은 기능이있는 GregorianCalendar 클래스를 제공합니다. GetWeekOfYear(date, rule, firstDayOfWeek).

매개 변수 rule 3 가지 가능한 값을 가진 열거입니다. FirstDay, FirstFourWeekDay, FirstFullWeek. 내가 이해 한 것에서 나는 가야한다 FirstFourWeekDay 규칙이지만 만일을 대비하여 모두 시도했습니다.

마지막 매개 변수는 월요일에 달력에 따르면 월요일에 어떤 주일을 고려해야하는지 알려줍니다.

그래서 나는 이것을 테스트하기 위해 빠르고 더러운 콘솔 앱을 발사했습니다.

using System;
using System.Globalization;

namespace CalendarTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var cal = new GregorianCalendar();
            var firstWeekDay = DayOfWeek.Monday;
            var twentyEighth = new DateTime(2008, 12, 28);
            var twentyNinth = new DateTime(2008, 12, 29);
            var firstJan = new DateTime(2009, 1, 1);
            var eightJan = new DateTime(2009, 1, 8);
            PrintWeekDays(cal, twentyEighth, firstWeekDay);
            PrintWeekDays(cal, twentyNinth, firstWeekDay);
            PrintWeekDays(cal, firstJan, firstWeekDay);
            PrintWeekDays(cal, eightJan, firstWeekDay);
            Console.ReadKey();
        }

        private static void PrintWeekDays(Calendar cal, DateTime dt, DayOfWeek firstWeekDay)
        {
            Console.WriteLine("Testing for " + dt.ToShortDateString());
            Console.WriteLine("--------------------------------------------");
            Console.Write(CalendarWeekRule.FirstDay.ToString() + "\t\t");
            Console.WriteLine(cal.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, firstWeekDay));
            Console.Write(CalendarWeekRule.FirstFourDayWeek.ToString() + "\t");
            Console.WriteLine(cal.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, firstWeekDay));
            Console.Write(CalendarWeekRule.FirstFullWeek.ToString() + "\t\t");
            Console.WriteLine(cal.GetWeekOfYear(dt, CalendarWeekRule.FirstFullWeek, firstWeekDay));
            Console.WriteLine("--------------------------------------------");
        }
    }
}

... 그리고 내가 얻는 것

Testing for 28.12.2008
--------------------------------------------
FirstDay                52
FirstFourDayWeek        52
FirstFullWeek           51
--------------------------------------------
Testing for 29.12.2008
--------------------------------------------
FirstDay                53
FirstFourDayWeek        53
FirstFullWeek           52
--------------------------------------------
Testing for 01.01.2009
--------------------------------------------
FirstDay                1
FirstFourDayWeek        1
FirstFullWeek           52
--------------------------------------------
Testing for 08.01.2009
--------------------------------------------
FirstDay                2
FirstFourDayWeek        2
FirstFullWeek           1
--------------------------------------------

우리가 보시다시피, 위의 조합 중 어느 것도 공식 일정과 일치하지 않습니다 (서두르면 29/12가 1 주일을 보내지 않는다는 것을 알 수 있습니다).

여기서 내가 무엇을 잘못하고 있습니까? 내가 놓친 것이 눈에 띄는 것이 있습니까? (벨기에에서 금요일과 늦은 근무 시간입니다.

편집 : 어쩌면 설명해야 할 것입니다 : 필요한 것은 모든 해에 효과가있는 기능이며, 내가 링크 한 그레고리 캘린더와 동일한 결과를 반환합니다. 따라서 2008 년의 특별한 해결 방법이 없습니다.

도움이 되었습니까?

해결책

이것 기사 문제와 가능한 해결 방법에 대해 더 깊이 보입니다. 이 문제의 허브는 .NET 캘린더 구현이 ISO 표준을 충실하게 구현하지 않는 것 같습니다.

다른 팁

@conrad가 맞습니다. DateTime과 GregorianCalendar의 .NET 구현은 전체 ISO 8601 사양을 구현/따릅니다. 즉, 사양은 적어도 사물의 구문 분석 측면에서 완전히 구현하는 데 매우 상세하고 사소하지 않습니다.

몇 가지 자세한 정보는 다음 사이트에서 제공됩니다.

간단히 말해서:

일주일은 주어진 해의 수로 식별되고 월요일부터 시작됩니다. 1 년의 첫 주에는 첫 번째 목요일이 포함 된 첫 주 또는 1 월 4 일을 포함하는 것입니다.

다음은 ISO 8601 날짜를 올바르게 처리하는 데 사용하는 코드의 일부입니다.

    #region FirstWeekOfYear
    /// <summary>
    /// Gets the first week of the year.
    /// </summary>
    /// <param name="year">The year to retrieve the first week of.</param>
    /// <returns>A <see cref="DateTime"/>representing the start of the first
    /// week of the year.</returns>
    /// <remarks>
    /// Week 01 of a year is per definition the first week that has the Thursday 
    /// in this year, which is equivalent to the week that contains the fourth
    /// day of January. In other words, the first week of a new year is the week
    /// that has the majority of its days in the new year. Week 01 might also 
    /// contain days from the previous year and the week before week 01 of a year
    /// is the last week (52 or 53) of the previous year even if it contains days 
    /// from the new year.
    /// A week starts with Monday (day 1) and ends with Sunday (day 7). 
    /// </remarks>
    private static DateTime FirstWeekOfYear(int year)
    {
        int dayNumber;

        // Get the date that represents the fourth day of January for the given year.
        DateTime date = new DateTime(year, 1, 4, 0, 0, 0, DateTimeKind.Utc);

        // A week starts with Monday (day 1) and ends with Sunday (day 7).
        // Since DayOfWeek.Sunday = 0, translate it to 7. All of the other values
        // are correct since DayOfWeek.Monday = 1.
        if (date.DayOfWeek == DayOfWeek.Sunday)
        {
            dayNumber = 7;
        }
        else
        {
            dayNumber = (int)date.DayOfWeek;
        }

        // Since the week starts with Monday, figure out what day that 
        // Monday falls on.
        return date.AddDays(1 - dayNumber);
    }

    #endregion

    #region GetIsoDate
    /// <summary>
    /// Gets the ISO date for the specified <see cref="DateTime"/>.
    /// </summary>
    /// <param name="date">The <see cref="DateTime"/> for which the ISO date
    /// should be calculated.</param>
    /// <returns>An <see cref="Int32"/> representing the ISO date.</returns>
    private static int GetIsoDate(DateTime date)
    {
        DateTime firstWeek;
        int year = date.Year;

        // If we are near the end of the year, then we need to calculate
        // what next year's first week should be.
        if (date >= new DateTime(year, 12, 29))
        {
            if (date == DateTime.MaxValue)
            {
                firstWeek = FirstWeekOfYear(year);
            }
            else
            {
                firstWeek = FirstWeekOfYear(year + 1);
            }

            // If the current date is less than next years first week, then
            // we are still in the last month of the current year; otherwise
            // change to next year.
            if (date < firstWeek)
            {
                firstWeek = FirstWeekOfYear(year);
            }
            else
            {
                year++;
            }
        }
        else
        {
            // We aren't near the end of the year, so make sure
            // we're not near the beginning.
            firstWeek = FirstWeekOfYear(year);

            // If the current date is less than the current years
            // first week, then we are in the last month of the
            // previous year.
            if (date < firstWeek)
            {
                if (date == DateTime.MinValue)
                {
                    firstWeek = FirstWeekOfYear(year);
                }
                else
                {
                    firstWeek = FirstWeekOfYear(--year);
                }
            }
        }

        // return the ISO date as a numeric value, so it makes it
        // easier to get the year and the week.
        return (year * 100) + ((date - firstWeek).Days / 7 + 1);
    }

    #endregion

    #region Week
    /// <summary>
    /// Gets the week component of the date represented by this instance.
    /// </summary>
    /// <value>The week, between 1 and 53.</value>
    public int Week
    {
        get
        {
            return this.isoDate % 100;
        }
    }
    #endregion

    #region Year
    /// <summary>
    /// Gets the year component of the date represented by this instance.
    /// </summary>
    /// <value>The year, between 1 and 9999.</value>
    public int Year
    {
        get
        {
            return this.isoDate / 100;
        }
    }
    #endregion

주 숫자는 국가마다 다르며 내가 완전히 틀리지 않은 경우 로케일/지역 환경에 따라 달라야합니다.

편집 : Wikipedia는이 숫자가 국가에 따라 다르다는 모호한 기억을 뒷받침합니다. http://en.wikipedia.org/wiki/week_number#week_number

나는 당신의 지역 런타임에서 선정 된 국가에 순종 할 존경하는 프레임 워크가 기대합니다.

내 경험에 따르면, 입증 된 행동은 전형적인 행동이며, 부분 마지막 주를 5 주차로 언급합니다. 이것은 내가 주에 필요한 모든 노출이보고 목적으로 달력 연말의 회계와 관련이 있었기 때문일 수 있습니다. 및 IRS (또는 선택한 세금 기관)는 연도의 마지막 주가 아니라 12 월 31 일에 끝날 달력을 고려합니다.

나는 이것이 오래된 게시물이라는 것을 알고 있지만, 어떤 식 으로든 Noda Time은 올바른 결과를 얻는 것 같습니다 ..

주변의 작업으로, 주 숫자는 Weeknumber Mod 52라고 말할 수 있습니다. 나는 이것이 당신이 설명하는 경우에 효과가 있다고 생각합니다.

해결 방법으로 사용하지 않는 이유는 무엇입니까? FirstFourDayWeek 그러나 추가 :

  if ( weekNumber > 52 )
    weekNumber = 1;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top