Sto provando a calcolare una data di scadenza per un contratto di livello di servizio e, allo stesso tempo, devo anche calcolare l'accordo sul livello di servizio nell'altro direzione.Calcolo del "tempo di lavoro" utilizzando CalendarPeriodCollector di TimePeriod.NET fornisce risultati imprevisti
Sono stato alle prese con i calcoli per "orario di lavoro" (vale a dire il tempo in cui il lavoro è possibile durante un set di giorni) e ho deciso di utilizzare una libreria di terze parti chiamata TimePeriodLibrary.NET per l'attività. Ho bisogno di essere in grado di fare due cose:
- Dato un inizio ed una
DateTime
TimeSpan
, si dovrebbero ricevere unDateTime
di quando una data contratto di servizio è dovuto (data di scadenza). - Dato un inizio
DateTime
e una fineDateTime
, si dovrebbe ricevere unTimeSpan
di quanto tempo deve essere preso questo accordo sul livello di servizio.
Tutto il codice sorgente (progetto di prova è GitHub). Ho una classe ServiceLevelManager
che fa tutto il lavoro. Prende una lista di WorkDays
e HolidayPeriods
, per capire quali ore sono disponibili per essere lavorate. La classe CalendarPeriodCollector
sta dando risultati imprevisti. Le aspettative che funzionano nel determinare la data di scadenza da un intervallo di tempo, non vengono calcolate correttamente al momento del calcolo.
Qualcuno può vedere se sto facendo qualcosa di sbagliato, o se la biblioteca ha un bug?
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);
}
}
}
i test di unità che non riescono vengono estratti di seguito:
[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.");
}
}
uscita di questo test è
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
Voglio sapere se sto usando il collettore in modo non corretto, o se il collezionista ha un bug.
Si prega di aggiungere dettagli per cosa intendete esattamente con "non calcolare correttamente". Fornire input di esempio, output previsto e output effettivo. Grazie. –
Ricorda inoltre che questa particolare libreria ha avuto problemi con DST e fusi orari in passato. Vedo nel loro log delle modifiche che la v1.7.0 ha creato degli alloggi per questo, ma c'è molto poco in termini di documentazione. –
@MattJohnson L'unit test nel codice sorgente (Github) mostra le aspettative. Se esegui i test unitari, vedrai quelli che falliscono. – Junto