private static ProjectTaskTimeSheet CreateTimeSheet() { var timeRange = new TimeRange(DateTime.Today.AddDays(Rnd.Next(0, 356)), TimeSpan.FromDays(1)); return new ProjectTaskTimeSheet(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()) { StartTime = timeRange.Start, EndTime = timeRange.End, PlanCostValue = Rnd.Next(0, 100).AsDecimal(), PlanProgressValue = Rnd.Next(0, 100), PlanWeightValue = Rnd.Next(0, 100).AsDecimal(), PlanWorkValue = Rnd.Next(0, 100).AsDecimal(), ActualCostValue = Rnd.Next(0, 100).AsDecimal(), ActualProgressValue = Rnd.Next(0, 100), ActualWeightValue = Rnd.Next(0, 100).AsDecimal(), ActualWorkValue = Rnd.Next(0, 100).AsDecimal(), Creator = "debop", LastUpdator = "debop", CreateDate = DateTime.Today }; }
public TimeRangePeriodRelationTestData(DateTime start, DateTime end, TimeSpan offset) { Guard.Assert<ArgumentOutOfRangeException>(offset >= TimeSpan.Zero, "offset은 0 이상의 기간을 가져야 합니다."); Reference = new TimeRange(start, end, true); var beforeEnd = start.Subtract(offset); var beforeStart = beforeEnd.Subtract(Reference.Duration); var insideStart = start.Add(offset); var insideEnd = end.Subtract(offset); var afterStart = end.Add(offset); var afterEnd = afterStart.Add(Reference.Duration); After = new TimeRange(beforeStart, beforeEnd, true); StartTouching = new TimeRange(beforeStart, start, true); StartInside = new TimeRange(beforeStart, insideStart, true); InsideStartTouching = new TimeRange(start, afterStart, true); EnclosingStartTouching = new TimeRange(start, insideEnd, true); Enclosing = new TimeRange(insideStart, insideEnd, true); EnclosingEndTouching = new TimeRange(insideStart, end, true); ExactMatch = new TimeRange(start, end, true); Inside = new TimeRange(beforeStart, afterEnd, true); InsideEndTouching = new TimeRange(beforeStart, end, true); EndInside = new TimeRange(insideEnd, afterEnd, true); EndTouching = new TimeRange(end, afterEnd, true); Before = new TimeRange(afterStart, afterEnd, true); _allPeriods.Add(Reference); _allPeriods.Add(After); _allPeriods.Add(StartTouching); _allPeriods.Add(StartInside); _allPeriods.Add(InsideStartTouching); _allPeriods.Add(EnclosingStartTouching); _allPeriods.Add(Enclosing); _allPeriods.Add(EnclosingEndTouching); _allPeriods.Add(ExactMatch); _allPeriods.Add(Inside); _allPeriods.Add(InsideEndTouching); _allPeriods.Add(EndInside); _allPeriods.Add(EndTouching); _allPeriods.Add(Before); }
protected virtual void CreateUserLoginHistory() { // 1년동안 매일 로그인 했다고 설정 // var dateRange = new TimeRange(DateTime.Now, DurationUtil.Days(30)); var activeProducts = NAccessContext.Domains.ProductRepository.FindAllActiveProduct(); var activeCompanys = NAccessContext.Domains.OrganizationRepository.FindAllActiveCompany(); dateRange .ForEachDays() .AsParallel() .AsOrdered() .RunEach(loginTime => { foreach(var product in activeProducts) foreach(var company in activeCompanys) foreach(var user in NAccessContext.Domains.OrganizationRepository.FindAllUserByCompany(company)) NAccessContext.Domains.LoggingRepository .InsertUserLoginLog(product, user, null, loginTime.Start); }); }
public void WeekOfYearCalendarTest() { var period = new TimeRange(new DateTime(2007, 12, 31), new DateTime(2009, 12, 31)); var moments = TimeTool.ForEachDays(period) #if !SILVERLIGHT .AsParallel() .AsOrdered() #endif .Select(p => p.Start); foreach(var culture in CultureTestData.Default) { var rule = WeekTool.GetWeekOfYearRuleKind(culture.DateTimeFormat.CalendarWeekRule, culture.DateTimeFormat.FirstDayOfWeek); if(rule == WeekOfYearRuleKind.Iso8601) continue; foreach(var moment in moments) { var calendarWeekOfYear = culture.Calendar.GetWeekOfYear(moment, culture.DateTimeFormat.CalendarWeekRule, culture.DateTimeFormat.FirstDayOfWeek); var yearAndWeek = TimeTool.GetWeekOfYear(moment, culture, WeekOfYearRuleKind.Calendar); Assert.AreEqual(calendarWeekOfYear, yearAndWeek.Week, "calendar WeekOfYear=[{0}], yearAndWeek=[{1}], culture=[{2}], momnent=[{3}], weekRule=[{4}], FirstDayOfWeek=[{5}]", calendarWeekOfYear, yearAndWeek, culture, moment, culture.DateTimeFormat.CalendarWeekRule, culture.DateTimeFormat.FirstDayOfWeek); } } }
/// <summary> /// <paramref name="yearAndWeek"/> 주차에 해당하는 기간을 <see cref="WeekRange"/> 로 반환합니다. (예: 2011년 28주차의 실제 기간) /// </summary> /// <param name="yearAndWeek">년도와 주차 정보</param> /// <param name="timeCalendar">TimeCalendar 옵션</param> /// <returns>주차에 해당하는 한주의 기간</returns> public static WeekRange GetWeekRange(this YearAndWeek yearAndWeek, ITimeCalendar timeCalendar) { //var timeCalendar = new TimeCalendar(new TimeCalendarConfig // { // Culture = culture, // WeekOfYearRule = GetWeekOfYearRuleKind(weekRule, firstDayOfWeek), // EndOffset = TimeSpan.Zero // }); yearAndWeek.Year = yearAndWeek.Year ?? 0; var endYearAndWeek = GetEndYearAndWeek(yearAndWeek.Year.Value, timeCalendar); yearAndWeek.Week = Math.Max(1, Math.Min(yearAndWeek.Week.Value, endYearAndWeek.Week.Value)); // 년/주에 가장 가까운 월을 선택해서 2개월만 검사한다. // 1년 범위는 너무 느리다. // var searchDays = RwDate.GetStartOfYear(yearWeek.Year).GetYearRange(); // 년/주에 가장 가까운 월을 선택해서 2개월만 검사한다. var nearMonth = yearAndWeek.Year.Value .GetStartOfMonth(Math.Max(1, Math.Min(TimeSpec.MonthsPerYear, (yearAndWeek.Week.Value - 1) / 4 + 1))) .GetMonthRange(); var searchDays = new TimeRange(nearMonth.GetPreviousMonth().Start, nearMonth.GetNextMonth().End); var weekPeriod = new TimeRange(); // 년도 경계 때문에 전년도 마지막 7일, 후년 첫 7일을 검색에 포함시킨다. //if (yearWeek.Week == 1) // searchDays.Start = searchDays.Start.Value.AddDays(-7); //else if (yearWeek.Week > 50) // searchDays.End = searchDays.End.Value.AddDays(7); // 지정 년도의 주차에 해당하는 날짜를 계산한다. var dayCount = 0; foreach(TimeRange dayRange in searchDays.ForEachDays()) { var startDay = dayRange.Start; var dayYearWeek = GetYearAndWeek(startDay, timeCalendar); if(dayYearWeek.Equals(yearAndWeek)) { if(weekPeriod.HasStart == false) { weekPeriod.Start = startDay; if(timeCalendar.WeekOfYearRule == WeekOfYearRuleKind.Iso8601) { weekPeriod.End = startDay.AddDays(TimeSpec.DaysPerWeek); break; } } else weekPeriod.End = startDay; dayCount++; } else if(dayCount > 0) { // 연속된 날짜 이후가 같은 주차가 아니라면 더 찾을 필요가 없다. break; } } if(weekPeriod.HasStart && weekPeriod.HasEnd == false) { // 다음해 새해 첫날이 첫주라면, 12월31로 끝나야 하고, 아니면 마지막 주의 끝은 다음해의 토요일까지이다. weekPeriod.End = (timeCalendar.CalendarWeekRule == CalendarWeekRule.FirstDay) ? weekPeriod.Start : weekPeriod.Start.AddDays(TimeSpec.DaysPerWeek); } Guard.Assert(weekPeriod.HasPeriod, "해당 주차의 범위를 찾지 못했습니다. YearAndWeek=[{0}]", yearAndWeek); return new WeekRange(weekPeriod, timeCalendar); }
/// <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; }
/// <summary> /// 두 기간의 합집합 기간을 반환한다. /// </summary> /// <param name="period"></param> /// <param name="target"></param> /// <returns></returns> public static TimeRange GetUnionRange(this ITimePeriod period, ITimePeriod target) { target.ShouldNotBeNull("target"); TimeRange unionPeriod = null; if(period.HasPeriod && target.HasPeriod) { unionPeriod = new TimeRange(period.StartAsNullable < target.StartAsNullable ? period.StartAsNullable : target.StartAsNullable, period.EndAsNullable > target.EndAsNullable ? period.EndAsNullable : target.EndAsNullable, period.IsReadOnly); } else { var start = (period.StartAsNullable.HasValue && target.StartAsNullable.HasValue) ? Min(period.Start, target.Start) : (period.StartAsNullable ?? target.StartAsNullable); var end = (period.EndAsNullable.HasValue && target.EndAsNullable.HasValue) ? Max(period.End, target.End) : (period.EndAsNullable ?? target.EndAsNullable); unionPeriod = new TimeRange(start, end, period.IsReadOnly); } if(IsDebugEnabled) log.Debug("period[{0}]와 target[{1}] 의 합집합 TimeRange [{2}]를 구했습니다!!!", period.AsString(), target.AsString(), unionPeriod.AsString()); return unionPeriod; }
/// <summary> /// 두 기간의 공통되는 기간을 반환한다. (교집합) /// </summary> /// <param name="period"></param> /// <param name="target"></param> /// <returns></returns> public static TimeRange GetIntersectionRange(this ITimePeriod period, ITimePeriod target) { target.ShouldNotBeNull("target"); TimeRange intersectionPeriod = null; if(IntersectsWith(period, target)) { var start = Max(period.Start, target.Start); var end = Min(period.End, target.End); intersectionPeriod = new TimeRange(start, end, period.IsReadOnly); } if(IsDebugEnabled) log.Debug("period[{0}]와 target[{1}] 의 교집합 TimeRange [{2}]를 구했습니다!!!", period.AsString(), target.AsString(), intersectionPeriod.AsString()); return intersectionPeriod; }