Próbuję obliczyć termin dla umowy o poziomie usług, a jednocześnie muszę również z powrotem obliczyć umowę o poziomie usług w innym kierunek.Obliczanie "czasu pracy" za pomocą TimePeriod.NET CalendarPeriodCollector daje nieoczekiwane wyniki
Zmagałem się z obliczeniami dotyczącymi "czasu pracy" (tj. Czasu, w którym praca jest możliwa w ciągu zestawu dni), i zdecydowałem się użyć do tego celu biblioteki strony trzeciej o nazwie TimePeriodLibrary.NET. Muszę być w stanie zrobić dwie rzeczy:
- Biorąc początek
DateTime
iTimeSpan
powinieneś otrzymaćDateTime
, kiedy data Service Level Agreement wynika (data powodu). - Po rozpoczęciu
DateTime
i końcuDateTime
, powinieneś otrzymaćTimeSpan
, jak długo powinna obowiązywać umowa o poziomie usług.
Cały kod źródłowy (testowy projekt jest na GitHub). Mam klasę ServiceLevelManager
, która wykonuje całą pracę. Sporządza listę WorkDays
i HolidayPeriods
, aby ustalić, które godziny są dostępne do pracy. Klasa CalendarPeriodCollector
daje nieoczekiwane wyniki. Oczekiwania, które działają w ustalaniu terminu z określonego przedziału czasowego, nie są obliczane poprawnie po ich obliczeniu.
Czy ktoś może sprawdzić, czy robię coś nie tak, czy biblioteka ma błąd?
namespace ServicePlanner
{
using System;
using System.Collections.Generic;
using Itenso.TimePeriod;
public class ServicePlannerManager
{
public ServicePlannerManager(IEnumerable<WorkDay> workDays, IEnumerable<HolidayPeriod> holidays)
{
this.WorkDays = workDays;
this.Holidays = holidays;
}
public IEnumerable<WorkDay> WorkDays { get; set; }
public IEnumerable<HolidayPeriod> Holidays { get; set; }
public TimeSpan GetRemainingWorkingTime(DateTime start, DateTime dueDate)
{
var filter = new CalendarPeriodCollectorFilter();
foreach (var dayOfWeek in this.WorkDays)
{
filter.CollectingDayHours.Add(new DayHourRange(dayOfWeek.DayOfWeek, new Time(dayOfWeek.StartTime), new Time(dayOfWeek.EndTime)));
}
foreach (var holiday in this.Holidays)
{
filter.ExcludePeriods.Add(new TimeBlock(holiday.StartTime, holiday.EndTime));
}
var range = new CalendarTimeRange(start, dueDate);
var collector = new CalendarPeriodCollector(filter, range);
collector.CollectHours();
var duration = collector.Periods.GetTotalDuration(new TimeZoneDurationProvider(TimeZoneInfo.FindSystemTimeZoneById("UTC")));
return duration;
//var rounded = Math.Round(duration.TotalMinutes, MidpointRounding.AwayFromZero);
//return TimeSpan.FromMinutes(rounded);
}
}
}
testy jednostkowe, które są upadających są wyodrębniane poniżej:
[TestFixture]
public class ServicePlannerManagerTest
{
[Test, TestCaseSource("LocalSource")]
public void GetRemainingWorkingTimeWithHolidayShouldOnlyEnumerateWorkingTime(DateTime startTime, TimeSpan workingHours, DateTime expectedDueDate, string expectation)
{
// Arrange
var workDays = new List<WorkDay>
{
new WorkDay(DayOfWeek.Monday, new DateTime(1, 1, 1, 9, 0, 0), new DateTime(1, 1, 1, 17, 0, 0)),
new WorkDay(DayOfWeek.Tuesday, new DateTime(1, 1, 1, 9, 0, 0), new DateTime(1, 1, 1, 17, 0, 0)),
new WorkDay(DayOfWeek.Wednesday, new DateTime(1, 1, 1, 9, 0, 0), new DateTime(1, 1, 1, 17, 0, 0)),
new WorkDay(DayOfWeek.Thursday, new DateTime(1, 1, 1, 9, 0, 0), new DateTime(1, 1, 1, 17, 0, 0)),
new WorkDay(DayOfWeek.Friday, new DateTime(1, 1, 1, 9, 0, 0), new DateTime(1, 1, 1, 17, 0, 0)),
};
var holidayPeriods = new List<HolidayPeriod>
{
new HolidayPeriod(new DateTime(2015, 9, 15, 00, 0, 0), new DateTime(2015, 9, 16, 0, 0, 0))
};
var service = new ServicePlannerManager(workDays, holidayPeriods);
// Act
var result = service.GetRemainingWorkingTime(startTime, expectedDueDate);
// Assert -
Assert.AreEqual(workingHours.TotalHours, result.TotalHours, expectation);
}
protected IEnumerable LocalSource()
{
yield return
new TestCaseData(
new DateTime(2015, 9, 14, 9, 0, 0),
new TimeSpan(23, 0, 0),
new DateTime(2015, 9, 17, 16, 0, 0),
"5. Expected 23 hours of working time to end on the 17/09/2015 16:00. Monday to Thursday evening. Just short of 3 full working days by one hour. Tuesday is holiday.");
}
}
wyjściowa tego testu jest
5. Expected 23 hours of working time to end on the 17/09/2015 16:00. Monday to Thursday evening. Just short of 3 full working days by one hour. Tuesday is holiday.
Expected: 23.0d
But was: 15.999999999944444d
Chcę wiedzieć, czy jestem nieprawidłowo stosując kolektor, lub jeśli kolektor ma błąd.
Proszę podać szczegóły, co dokładnie oznacza "nie obliczaj poprawnie". Podaj przykładowe dane wejściowe, oczekiwane wyniki i rzeczywiste wyniki. Dzięki. –
Należy również pamiętać, że w tej konkretnej bibliotece wystąpiły problemy z czasem letnim i strefami czasowymi w przeszłości. W ich dzienniku zmian widzę, że v1.7.0 zrobiło dla nich miejsce, ale dokumentacja jest bardzo ograniczona. –
@MattJohnson Testy jednostki w kodzie źródłowym (Github) pokazują oczekiwania. Jeśli przeprowadzisz testy jednostkowe, zobaczysz te, które zawiodły. – Junto