Пример #1
0
        public void AddWeekOfYearsTest()
        {
            const int maxAddWeeks = 40;

            Action <CultureInfo> @AddWeekOfYearsAction =
                (culture) => {
                var currentCulture = culture;

                Enumerable
                .Range(2000, 20)
                .RunEach(year => {
                    const int step         = 10;
                    YearAndWeek prevResult = new YearAndWeek();

                    var maxWeek = WeekTool.GetEndYearAndWeek(year, currentCulture);

                    for (var week = 1; week < maxWeek.Week; week += step)
                    {
                        for (var addWeeks = -maxAddWeeks; addWeeks <= maxAddWeeks; addWeeks += step)
                        {
                            var current = new YearAndWeek(year, week);
                            var result  = WeekTool.AddWeekOfYears(current, addWeeks, currentCulture);

                            if (addWeeks != 0 && prevResult.Week.HasValue)
                            {
                                if (result.Year == prevResult.Year)
                                {
                                    Assert.AreEqual(prevResult.Week + step, result.Week,
                                                    @"Prev=[{0}], Result=[{1}], addWeeks=[{2}]", prevResult, result,
                                                    addWeeks);
                                }
                            }

                            result.Week.Should().Have.Value();
                            result.Week.Value.Should().Be.GreaterThan(0);
                            result.Week.Value.Should().Be.LessThanOrEqualTo(TimeSpec.MaxWeeksPerYear);

                            prevResult = result;

                            if (IsDebugEnabled)
                            {
                                log.Debug("Current=[{0}], Added=[{1}], AddWeeks=[{2}]", current, result, addWeeks);
                            }
                        }
                    }
                });
            };


            Parallel.For(0, CultureTestData.Default.Count(), i => @AddWeekOfYearsAction(CultureTestData.Default[i]));

            var rule = WeekOfYearRuleKind.Iso8601;

            ParallelTool.ForWithStep(2000, 2020, 2,
                                     year => {
                const int step = 10;
                var prevResult = new YearAndWeek();

                var maxWeek = WeekTool.GetEndYearAndWeek(year, null, rule);

                for (var week = 1; week < maxWeek.Week; week += step)
                {
                    for (var addWeeks = -maxAddWeeks; addWeeks <= maxAddWeeks; addWeeks += step)
                    {
                        var current = new YearAndWeek(year, week);
                        var result  = WeekTool.AddWeekOfYears(current, addWeeks, null, rule);

                        if (addWeeks != 0 && prevResult.Week.HasValue)
                        {
                            if (result.Year == prevResult.Year)
                            {
                                Assert.AreEqual(prevResult.Week + step, result.Week,
                                                @"Prev={0}, Result={1}, addWeeks={2}", prevResult, result,
                                                addWeeks);
                            }
                        }

                        result.Week.Should().Have.Value();
                        result.Week.Value.Should().Be.GreaterThan(0);
                        result.Week.Value.Should().Be.LessThanOrEqualTo(TimeSpec.MaxWeeksPerYear);

                        prevResult = result;

                        if (IsDebugEnabled)
                        {
                            log.Debug("Current=[{0}], Added=[{1}], AddWeeks=[{2}]", current, result, addWeeks);
                        }
                    }
                }
            });
        }
Пример #2
0
        /// <summary>
        /// 해당일자의 주차를 구한다. 문화권(Culture) 및 새해 첫주차에 대한 정의에 따라 주차가 달라진다.
        /// ref : http://www.simpleisbest.net/archive/2005/10/27/279.aspx
        /// ref : http://en.wikipedia.org/wiki/ISO_8601#Week_dates
        /// </summary>
        /// <remarks>
        /// <see cref="CalendarWeekRule"/> 값에 따라 WeekOfYear 가 결정된다.
        /// 
        /// FirstDay : 1월1일이 포함된 주를 무조건 첫째 주로 삼는다. (우리나라, 미국 등의 기준) : .NET의 설정대로 하면 이렇게 된다.
        /// FirstFourDayWeek : 1월1일이 포함된 주가 4일 이상인 경우에만 그 해의 첫 번째 주로 삼는다.	(ISO 8601)
        ///					   예) 한 주의 시작 요일이 일요일이고 1월1일이 일/월/화/수 중 하나이면 1월1일이 포함된 주는 해당 해의 첫 번째 주이다.
        ///					   예) 한 주의 시작 요일이 일요일이고 1월1일이 목/금/토 중 하나이면 1월1일이 포함된 주는 해당 해의 첫 번째 주로 간주하지 않는다.
        ///					   예) 2005년 1월 1일은 토요일이므로 1월1일이 포함된 주는 2005년의 첫 번째 주로 간주하지 않는다.
        /// FirstFullWeek : 1월의 첫 번째 주가 7일이 아니면 해당 해의 첫 번째 주로 삼지 않는다.
        ///				    예) 한 주의 시작 요일이 일요일인 경우, 1월1일이 일요일이 아니라면 1월1일이 포함된 주는 해당 해의 첫 번째 주로 간주하지 않는다.
        /// </remarks>
        /// <param name="moment">주차(WeekOfYear)를 산정하기 위한 일자</param>
        /// <param name="timeCalendar">주차 계산을 위한 규칙 정보를 가진 TimeCalendar 인스턴스</param>
        /// <returns>지정된 일자가 속한 Week Of Year를 반환</returns>
        public static YearAndWeek GetYearAndWeek(this DateTime moment, ITimeCalendar timeCalendar) {
            timeCalendar.ShouldNotBeNull("timeCalendar");

            var culture = timeCalendar.Culture.GetOrCurrentCulture();
            var weekRule = timeCalendar.CalendarWeekRule;
            var firstDayOfWeek = timeCalendar.FirstDayOfWeek;

            if(IsDebugEnabled)
                log.Debug("특정일[{0}] 의 주차를 계산합니다. culture=[{1}], weekRule=[{2}], firstDayOfWeek=[{3}]", moment, culture, weekRule,
                          firstDayOfWeek);

            var week = culture.Calendar.GetWeekOfYear(moment, weekRule, firstDayOfWeek);
            var year = moment.Year;

            //!+ NOTE: .NET 라이브러리가 1월1일 기준으로는 정상작동하지만, 12월 31로 계산하면, 무조건 FirstDay 형식으로 작업해버린다.
            //!+ FirstFourDayWeek Rule에 따르면 12월 31일이 다음해의 첫주차에 속할 경우도 있지만, .NET에서는 53주차로 반환해 버린다.
            //!+ 예 12월 31일이 월요일 경우 2001년 53주차가 아니라 2002년 1주차가 되어야 한다.
            //!+ 이를 해결하기 위해 부가적인 작업이 들어간다.
            //
            if(weekRule == CalendarWeekRule.FirstFourDayWeek && firstDayOfWeek == DayOfWeek.Monday) {
                var weekRange = new TimeRange(TimeTool.StartTimeOfWeek(moment, (DayOfWeek?)firstDayOfWeek), DurationUtil.Week);
                if(moment.Month == 12 && weekRange.HasInside(new DateTime(year + 1, 1, 1))) {
                    var startDate = moment.AddYears(1).StartTimeOfYear();
                    if((int)startDate.DayOfWeek > (int)firstDayOfWeek &&
                       (int)startDate.DayOfWeek - (int)firstDayOfWeek < 4) {
                        year++;
                        week = 1;
                    }
                }
            }
            // NOTE : 연도 보정 (1월인데, Week가 충분히 큰 숫자 이상이라면, 전년도의 주차를 따른다는 것이다. 그러므로 Year를 전년도로 설정해준다.
            if(moment.Month == 1 && week > 10)
                year--;

            var result = new YearAndWeek(year, week);

            if(IsDebugEnabled)
                log.Debug("일자[{0}] 의 주차는 [{4}]입니다. culture=[{1}], weekRule=[{2}], firstDayOfWeek=[{3}]", moment, culture, weekRule,
                          firstDayOfWeek, result);

            return result;
        }
Пример #3
0
        /// <summary>
        /// <paramref name="yearAndWeek"/>에 <paramref name="weeks"/>만큼의 주차를 더한 주차를 계산합니다.
        /// </summary>
        /// <param name="yearAndWeek">기준 주차</param>
        /// <param name="weeks">더할 주차 값</param>
        /// <param name="timeCalendar">TimeCalendar</param>
        /// <returns>기준 주차에 주차를 더한 주차 정보</returns>
        public static YearAndWeek AddWeekOfYears(this YearAndWeek yearAndWeek, int weeks, ITimeCalendar timeCalendar) {
            timeCalendar.ShouldNotBeNull("timeCalendar");


            if(IsDebugEnabled)
                log.Debug("주차 연산을 수행합니다... yearAndWeek=[{0}], weeks=[{1}], timeCalendar=[{2}]",
                          yearAndWeek, weeks, timeCalendar);


            var result = new YearAndWeek(yearAndWeek.Year, yearAndWeek.Week);

            if(weeks == 0)
                return result;

            if(weeks > 0) {
                weeks += result.Week.Value;
                if(weeks < GetEndYearAndWeek(yearAndWeek.Year.Value, timeCalendar).Week) {
                    result.Week = weeks;
                    return result;
                }
                while(weeks >= 0) {
                    var endWeek = GetEndYearAndWeek(result.Year.Value, timeCalendar);
                    if(weeks <= endWeek.Week) {
                        result.Week = Math.Max(weeks, 1);
                        return result;
                    }
                    weeks -= endWeek.Week.Value;
                    result.Year++;
                }
                result.Week = Math.Max(weeks, 1);
            }
            else {
                weeks += result.Week.Value;

                if(weeks == 0) {
                    result.Year--;
                    result.Week = GetEndYearAndWeek(result.Year.Value, timeCalendar).Week.Value;
                    return result;
                }
                if(weeks > 0) {
                    result.Week = weeks;
                    return result;
                }
                while(weeks <= 0) {
                    result.Year--;
                    var endWeek = GetEndYearAndWeek(result.Year.Value, timeCalendar);
                    weeks += endWeek.Week.Value;

                    if(weeks > 0) {
                        result.Week = Math.Max(weeks, 1);
                        return result;
                    }
                }
                result.Week = Math.Max(weeks, 1);
            }

            if(IsDebugEnabled)
                log.Debug("주차 연산을 수행했습니다!!! yearAndWeek=[{0}], weeks=[{1}], result=[{2}]", yearAndWeek, weeks, result);

            return result;
        }
Пример #4
0
        public void AddWeekOfYearsTest() {
            const int maxAddWeeks = 40;

            Action<CultureInfo> @AddWeekOfYearsAction =
                (culture) => {
                    var currentCulture = culture;

                    Enumerable
                        .Range(2000, 20)
                        .RunEach(year => {
                                     const int step = 10;
                                     YearAndWeek prevResult = new YearAndWeek();

                                     var maxWeek = WeekTool.GetEndYearAndWeek(year, currentCulture);

                                     for(var week = 1; week < maxWeek.Week; week += step) {
                                         for(var addWeeks = -maxAddWeeks; addWeeks <= maxAddWeeks; addWeeks += step) {
                                             var current = new YearAndWeek(year, week);
                                             var result = WeekTool.AddWeekOfYears(current, addWeeks, currentCulture);

                                             if(addWeeks != 0 && prevResult.Week.HasValue) {
                                                 if(result.Year == prevResult.Year)
                                                     Assert.AreEqual(prevResult.Week + step, result.Week,
                                                                     @"Prev=[{0}], Result=[{1}], addWeeks=[{2}]", prevResult, result,
                                                                     addWeeks);
                                             }

                                             result.Week.Should().Have.Value();
                                             result.Week.Value.Should().Be.GreaterThan(0);
                                             result.Week.Value.Should().Be.LessThanOrEqualTo(TimeSpec.MaxWeeksPerYear);

                                             prevResult = result;

                                             if(IsDebugEnabled)
                                                 log.Debug("Current=[{0}], Added=[{1}], AddWeeks=[{2}]", current, result, addWeeks);
                                         }
                                     }
                                 });
                };


            Parallel.For(0, CultureTestData.Default.Count(), i => @AddWeekOfYearsAction(CultureTestData.Default[i]));

            var rule = WeekOfYearRuleKind.Iso8601;

            ParallelTool.ForWithStep(2000, 2020, 2,
                                     year => {
                                         const int step = 10;
                                         var prevResult = new YearAndWeek();

                                         var maxWeek = WeekTool.GetEndYearAndWeek(year, null, rule);

                                         for(var week = 1; week < maxWeek.Week; week += step) {
                                             for(var addWeeks = -maxAddWeeks; addWeeks <= maxAddWeeks; addWeeks += step) {
                                                 var current = new YearAndWeek(year, week);
                                                 var result = WeekTool.AddWeekOfYears(current, addWeeks, null, rule);

                                                 if(addWeeks != 0 && prevResult.Week.HasValue) {
                                                     if(result.Year == prevResult.Year)
                                                         Assert.AreEqual(prevResult.Week + step, result.Week,
                                                                         @"Prev={0}, Result={1}, addWeeks={2}", prevResult, result,
                                                                         addWeeks);
                                                 }

                                                 result.Week.Should().Have.Value();
                                                 result.Week.Value.Should().Be.GreaterThan(0);
                                                 result.Week.Value.Should().Be.LessThanOrEqualTo(TimeSpec.MaxWeeksPerYear);

                                                 prevResult = result;

                                                 if(IsDebugEnabled)
                                                     log.Debug("Current=[{0}], Added=[{1}], AddWeeks=[{2}]", current, result, addWeeks);
                                             }
                                         }
                                     });
        }