public void Contains_ShouldReturnValidResult_ForRange() { // Arrange. var start = new DateTime(2001, 1, 1, 1, 0, 0, 0, DateTimeKind.Local); var tomorrow = start.AddDays(1); var nextWeek = start.AddDays(7); var nextYear = start.AddYears(1); var nextCentury = start.AddYears(100); var targetOne = new DateTimeRange(start, nextYear); var targetTwo = new DateTimeRange(start, tomorrow); var targetThree = new DateTimeRange(nextWeek, nextYear); var targetFour = new DateTimeRange(tomorrow, nextWeek); var targetFive = new DateTimeRange(nextWeek, nextCentury); // Act. var resultOne = targetOne.Contains(targetOne); var resultTwo = targetOne.Contains(targetTwo); var resultThree = targetOne.Contains(targetThree); var resultFour = targetOne.Contains(targetFour); var resultFive = targetOne.Contains(targetFive); // Assert. resultOne.Should().BeTrue(); resultTwo.Should().BeTrue(); resultThree.Should().BeTrue(); resultFour.Should().BeTrue(); resultFive.Should().BeFalse(); }
public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForOneYearRange() { // Arrange. var start = new DateTime(2001, 1, 1, 1, 0, 0, 0, DateTimeKind.Local); var end = start.AddYears(1); var midpoint = start.AddMonths(6); var outlier = end.AddYears(3); // Act. var target = new DateTimeRange(start, end); // Assert. target.Start.Should().Be(start); target.End.Should().Be(end); target.Contains(start).Should().BeTrue(); target.Contains(end).Should().BeTrue(); target.Contains(midpoint).Should().BeTrue(); target.Contains(outlier).Should().BeFalse(); target.LengthInYears.Should().Be(1); target.LengthInMonths.Should().Be(12); target.LengthInWeeks.Should().Be(52); target.LengthInDays.Should().Be(365); target.LengthInHours.Should().Be(8760); target.LengthInMinutes.Should().Be(525600); target.LengthInSeconds.Should().Be(31536000); target.LengthInMilliseconds.Should().Be(31536000000); }
public void TestContains() { TimeSpan step = new TimeSpan(30, 0, 0, 0); DateTimeRange range = new DateTimeRange(new DateTime(2009, 1, 1), new DateTime(2010, 4, 20), step); Assert.IsTrue(range.Contains(range.Start + step)); Assert.IsFalse(range.Contains(range.End.AddDays(1))); }
public void Contains_Test() { // Arrange DateTimeRange dateTimeRange = new DateTimeRange(DateTime.Now, DateTime.Now.AddDays(2)); DateTime dateTime = DateTime.Now.AddDays(1); // Act var result = dateTimeRange.Contains(dateTime: dateTime, excludeStart: true, excludeEnd: true); // Assert Assert.That(result); }
private ImmutableList <Break> LoadBreaksToSmooth( DateTimeRange dateTimeRange, string salesAreaName) { return(_threadSafeCollections.BreaksForAllSalesAreasForSmoothPeriod .Where(BreakIsInSalesAreaAndDateRange) .ToImmutableList()); // Local function bool BreakIsInSalesAreaAndDateRange(Break aBreak) => aBreak.SalesArea.Equals(salesAreaName, StringComparison.InvariantCultureIgnoreCase) && dateTimeRange.Contains(aBreak.ScheduledDate); }
public void FunctionalLifeSpanTest_ShouldProduceDesiredResults_ForComplexRange() { // Arrange. var start = new DateTime(1997, 11, 6, 14, 7, 46, 482, DateTimeKind.Local); var end = new DateTime(2024, 2, 29, 17, 41, 10, 193, DateTimeKind.Local); // Act. var target = new DateTimeRange(start, end); // Assert. target.Start.Should().Be(start); target.End.Should().Be(end); target.Contains(start).Should().BeTrue(); target.Contains(end).Should().BeTrue(); target.Contains(target.Midpoint).Should().BeTrue(); target.LengthInYears.Should().Be(26); target.LengthInMonths.Should().Be(315); target.LengthInWeeks.Should().Be(1373); target.LengthInDays.Should().Be(9611); target.LengthInHours.Should().Be(230667); target.LengthInMinutes.Should().Be(13840053); target.LengthInSeconds.Should().Be(830403203); target.LengthInMilliseconds.Should().Be(830403203711); }
Check_if_a_DateTimeRange_contains_a_specific_DateTime( DateTime dateRangeStart, DateTime dateRangeEnd, DateTime sample, bool expected ) { // Arrange DateTimeRange labrat = (dateRangeStart, dateRangeEnd); // Act bool result = labrat.Contains(sample); // Assert _ = result.Should().Be(expected, becauseArgs: null); }
public void ContainsTest() { var time0 = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); var time1 = new DateTime(2015, 12, 31, 0, 0, 0, DateTimeKind.Utc); var range = new DateTimeRange(time0, time1); Assert.IsFalse(range.Contains(DateTime.MinValue)); Assert.IsFalse(range.Contains(new DateTime(1999, 12, 31, 0, 0, 0, DateTimeKind.Utc))); Assert.IsTrue(range.Contains(time0)); Assert.IsTrue(range.Contains(new DateTime(2000, 6, 30, 0, 0, 0, DateTimeKind.Utc))); Assert.IsTrue(range.Contains(time1)); Assert.IsFalse(range.Contains(new DateTime(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc))); Assert.IsFalse(range.Contains(DateTime.MaxValue)); }
public void ShouldReturnFalseWhenCurrentRangeDoNotContainsDate() { // For DateTimeRange currentRange = new DateTimeRange { Start = new DateTime(2020, 04, 01), End = new DateTime(2020, 04, 30) }; DateTimeRange newRange = currentRange; // Given DateTime date = new DateTime(2020, 03, 01); bool value = newRange.Contains(date); // Assert Assert.IsFalse(value); }
public void ShouldReturnFalseWhenCurrentRangeDoNotContainsRange(int month) { // For DateTimeRange currentRange = new DateTimeRange { Start = new DateTime(2020, 04, 01), End = new DateTime(2020, 04, 30) }; DateTimeRange newRange = currentRange; // Given DateTimeRange range = new DateTimeRange { Start = new DateTime(2020, month, 01), End = new DateTime(2020, month, 30) }; bool value = newRange.Contains(range); // Assert Assert.IsFalse(value); }
public void ShouldReturnTrueWhenCurrentRangeContainsRange(int firstDay, int secondDay) { // For DateTimeRange currentRange = new DateTimeRange { Start = new DateTime(2020, 04, 01), End = new DateTime(2020, 04, 30) }; DateTimeRange newRange = currentRange; // Given DateTimeRange range = new DateTimeRange { Start = new DateTime(2020, 04, firstDay), End = new DateTime(2020, 04, secondDay) }; bool value = newRange.Contains(range); // Assert Assert.IsTrue(value); }
private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data) { // TODO: Add slack daily summaries var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary && !String.Equals(n.Key, Project.NotificationIntegrations.Slack)).Select(n => n.Key).ToList(); if (userIds.Count == 0) { _logger.LogInformation("Project {ProjectName} has no users to send summary to.", project.Name); return(false); } var results = await _userRepository.GetByIdsAsync(userIds, o => o.Cache()).AnyContext(); var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList(); if (users.Count == 0) { _logger.LogInformation("Project {ProjectName} has no users to send summary to.", project.Name); return(false); } // TODO: What should we do about suspended organizations. var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, o => o.Cache()).AnyContext(); if (organization == null) { _logger.LogInformation("The organization {organization} for project {ProjectName} may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name); return(false); } _logger.LogInformation("Sending daily summary: users={UserCount} project={project}", users.Count, project.Id); var sf = new AppFilter(project, organization); var systemFilter = new RepositoryQuery <PersistentEvent>().AppFilter(sf).DateRange(data.UtcStartTime, data.UtcEndTime, (PersistentEvent e) => e.Date).Index(data.UtcStartTime, data.UtcEndTime); string filter = "type:error (status:open OR status:regressed)"; var result = await _eventRepository.CountAsync(q => q.SystemFilter(systemFilter).FilterExpression(filter).EnforceEventStackFilter().AggregationsExpression("terms:(first @include:true) terms:(stack_id~3) cardinality:stack_id sum:count~1")).AnyContext(); double total = result.Aggregations.Sum("sum_count")?.Value ?? result.Total; double newTotal = result.Aggregations.Terms <double>("terms_first")?.Buckets.FirstOrDefault()?.Total ?? 0; double uniqueTotal = result.Aggregations.Cardinality("cardinality_stack_id")?.Value ?? 0; bool hasSubmittedEvents = total > 0 || project.IsConfigured.GetValueOrDefault(); bool isFreePlan = organization.PlanId == _plans.FreePlan.Id; string fixedFilter = "type:error status:fixed"; var fixedResult = await _eventRepository.CountAsync(q => q.SystemFilter(systemFilter).FilterExpression(fixedFilter).EnforceEventStackFilter().AggregationsExpression("sum:count~1")).AnyContext(); double fixedTotal = fixedResult.Aggregations.Sum("sum_count")?.Value ?? fixedResult.Total; var range = new DateTimeRange(data.UtcStartTime, data.UtcEndTime); var usages = project.OverageHours.Where(u => range.Contains(u.Date)).ToList(); int blockedTotal = usages.Sum(u => u.Blocked); int tooBigTotal = usages.Sum(u => u.TooBig); IReadOnlyCollection <Stack> mostFrequent = null; var stackTerms = result.Aggregations.Terms <string>("terms_stack_id"); if (stackTerms?.Buckets.Count > 0) { mostFrequent = await _stackRepository.GetByIdsAsync(stackTerms.Buckets.Select(b => b.Key).ToArray()).AnyContext(); } IReadOnlyCollection <Stack> newest = null; if (newTotal > 0) { newest = (await _stackRepository.FindAsync(q => q.AppFilter(sf).FilterExpression(filter).SortExpression("-first").DateRange(data.UtcStartTime, data.UtcEndTime, "first"), o => o.PageLimit(3)).AnyContext()).Documents; } foreach (var user in users) { _logger.LogInformation("Queuing {ProjectName} daily summary email ({UtcStartTime}-{UtcEndTime}) for user {EmailAddress}.", project.Name, data.UtcStartTime, data.UtcEndTime, user.EmailAddress); await _mailer.SendProjectDailySummaryAsync(user, project, mostFrequent, newest, data.UtcStartTime, hasSubmittedEvents, total, uniqueTotal, newTotal, fixedTotal, blockedTotal, tooBigTotal, isFreePlan).AnyContext(); } _logger.LogInformation("Done sending daily summary: users={UserCount} project={ProjectName} events={EventCount}", users.Count, project.Name, total); return(true); }
public IEnumerable <Break> Search(DateTimeRange scheduledDatesRange, IEnumerable <string> salesAreaNames) { return(GetAllByType <Break>(_folder, _type, currentItem => scheduledDatesRange.Contains(currentItem.ScheduledDate) && salesAreaNames.Contains(currentItem.SalesArea))); }
private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data) { // TODO: Add slack daily summaries var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary && !String.Equals(n.Key, Project.NotificationIntegrations.Slack)).Select(n => n.Key).ToList(); if (userIds.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name).Write(); return(false); } var results = await _userRepository.GetByIdsAsync(userIds, o => o.Cache()).AnyContext(); var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList(); if (users.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name); return(false); } // TODO: What should we do about suspended organizations. var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, o => o.Cache()).AnyContext(); if (organization == null) { _logger.Info().Project(project.Id).Message("The organization \"{0}\" for project \"{1}\" may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name); return(false); } _logger.Info("Sending daily summary: users={0} project={1}", users.Count, project.Id); var sf = new ExceptionlessSystemFilter(project, organization); var systemFilter = new RepositoryQuery <PersistentEvent>().SystemFilter(sf).DateRange(data.UtcStartTime, data.UtcEndTime, (PersistentEvent e) => e.Date).Index(data.UtcStartTime, data.UtcEndTime); string filter = $"{EventIndexType.Alias.Type}:{Event.KnownTypes.Error} {EventIndexType.Alias.IsHidden}:false {EventIndexType.Alias.IsFixed}:false"; var result = await _eventRepository.CountBySearchAsync(systemFilter, filter, "terms:(first @include:true) terms:(stack_id~3) cardinality:stack_id sum:count~1").AnyContext(); double total = result.Aggregations.Sum("sum_count").Value ?? result.Total; double newTotal = result.Aggregations.Terms <double>("terms_first")?.Buckets.FirstOrDefault()?.Total ?? 0; double uniqueTotal = result.Aggregations.Cardinality("cardinality_stack_id")?.Value ?? 0; bool hasSubmittedEvents = total > 0 || project.IsConfigured.GetValueOrDefault(); bool isFreePlan = organization.PlanId == BillingManager.FreePlan.Id; string fixedFilter = $"{EventIndexType.Alias.Type}:{Event.KnownTypes.Error} {EventIndexType.Alias.IsHidden}:false {EventIndexType.Alias.IsFixed}:true"; var fixedResult = await _eventRepository.CountBySearchAsync(systemFilter, fixedFilter, "sum:count~1").AnyContext(); double fixedTotal = fixedResult.Aggregations.Sum("sum_count").Value ?? fixedResult.Total; var range = new DateTimeRange(data.UtcStartTime, data.UtcEndTime); var usages = project.OverageHours.Where(u => range.Contains(u.Date)).ToList(); int blockedTotal = usages.Sum(u => u.Blocked); int tooBigTotal = usages.Sum(u => u.TooBig); IReadOnlyCollection <Stack> mostFrequent = null; var stackTerms = result.Aggregations.Terms <string>("terms_stack_id"); if (stackTerms?.Buckets.Count > 0) { mostFrequent = await _stackRepository.GetByIdsAsync(stackTerms.Buckets.Select(b => b.Key).ToArray()).AnyContext(); } IReadOnlyCollection <Stack> newest = null; if (newTotal > 0) { newest = (await _stackRepository.GetByFilterAsync(sf, filter, "-first", "first", data.UtcStartTime, data.UtcEndTime, o => o.PageLimit(3)).AnyContext()).Documents; } foreach (var user in users) { _logger.Info().Project(project.Id).Message("Queuing \"{0}\" daily summary email ({1}-{2}) for user {3}.", project.Name, data.UtcStartTime, data.UtcEndTime, user.EmailAddress); await _mailer.SendProjectDailySummaryAsync(user, project, mostFrequent, newest, data.UtcStartTime, hasSubmittedEvents, total, uniqueTotal, newTotal, fixedTotal, blockedTotal, tooBigTotal, isFreePlan).AnyContext(); } _logger.Info().Project(project.Id).Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Name, total); return(true); }
/// <summary> /// Creates a list of timelines from the provided time bands; only using /// valid sponsorships that meet sales area and time stamp /// </summary> private List <SmoothSponsorshipTimeline> CreateTimelinesFromTimeBands( IEnumerable <SponsoredItem> sponsoredItems) { var smoothTimelines = new List <SmoothSponsorshipTimeline>(); foreach (var currentDate in _dateTimeRange) { foreach (var sponsoredItem in sponsoredItems) { foreach (var sponsorship in sponsoredItem.SponsorshipItems) { DateTimeRange dateRange = (sponsorship.StartDate, sponsorship.EndDate); foreach (var dayPart in sponsorship.DayParts) { AddSmoothTimelineByDate( sponsoredItem, currentDate, dateRange, dayPart); } } } } return(smoothTimelines); bool TimeBandIsOnValidDayOfWeek(string[] daysOfWeek, DateTime date) => DayOfWeekHelper.DateFallsOnDayOfWeek(daysOfWeek, date); void AddSmoothTimelineByDate( SponsoredItem sponsoredItem, DateTime currentDate, DateTimeRange dateRange, SponsoredDayPart dayPart) { if (!(TimeBandIsOnValidDayOfWeek(dayPart.DaysOfWeek, currentDate) && dateRange.Contains(currentDate.Date))) { return; } var start = DateHelper.ConvertBroadcastToStandard(currentDate.Date, dayPart.StartTime); var end = DateHelper.ConvertBroadcastToStandard(currentDate.Date, dayPart.EndTime); List <(string advertiserIdentifier, int restrictionValue)> advertiserExclusivities = GetAdvertiserReferenceAndRestrictionValue( sponsoredItem.AdvertiserExclusivities, sponsoredItem.RestrictionValue ?? 0); List <(string clashExternalReference, int restrictionValue)> clashExclusivities = GetClashReferenceAndRestrictionValue( sponsoredItem.ClashExclusivities, sponsoredItem.RestrictionValue ?? 0); smoothTimelines.Add(new SmoothSponsorshipTimeline() { DateTimeRange = (start, end), AdvertiserIdentifiers = advertiserExclusivities, ClashExternalReferences = clashExclusivities, SponsoredProducts = sponsoredItem.Products, Applicability = sponsoredItem.Applicability ?? SponsorshipApplicability.AllCompetitors, CalculationType = sponsoredItem.CalculationType }); }