2012-01-16 10 views
7

Sto provando a creare uno strumento che calcoli qualcosa chiamato quota in base a quando i dipendenti sono programmati per funzionare e quando richiedono.Come trovo l'intersezione di due serie di tempi non contigui?

mio oggetto ShiftSet è un insieme di oggetti Spostamento che consistono di uno StartTime e EndTime (entrambi di tipo tempo (7). Ogni ShiftSet corrisponde a un giorno.

ScheduleExceptions sono volte in cui un dipendente ha spento. Ci può essere qualsiasi numero di ScheduleExceptions sovrapposti non sovrapposte o in un giorno sono del tipo di dati datetime

un esempio di uno ShiftSet:..
08: 00-10: 00
10: 00-12: 00
13: 00-15: 00
15:00 -17: 00

Un esempio di ScheduleExceptions per quello stesso giorno:
07: 30-10: 30
14: 35-16: 00

Cosa devo fare è trovare la quantità di tempo in cui il dipendente sta lavorando in un giorno. Il modo in cui posso capire di fare questo è calcolare l'intersezione di ShiftSet e l'inverso di ScheduleExceptions.

Come dovrei farlo con il tempo? Preferirei usare Linq se possibile.

+0

posso chiedere che tipo 'time (7)' è in C#? –

+0

È ora in sql, ma in C# è l'intervallo di tempo. –

+0

Hai bisogno di trovare il tempo totale o vuoi trovare le ore di inizio/fine effettive in cui un dipendente sta lavorando? – Abel

risposta

2

As InBetween menzionato, ci sono librerie là fuori che hanno risolto questo problema, ma risolvono anche molti problemi correlati. Se vuoi semplicemente affrontare questo particolare problema senza assumere un'altra dipendenza, puoi provare quanto segue.

// Finds ones with absolutely no overlap 
var unmodified = shifts.Where(s => !exceptions.Any(e => s.Start < e.End && s.End > e.Start)); 

// Finds ones entirely overlapped 
var overlapped = shifts.Where(s => exceptions.Any(e => e.End >= s.End && e.Start <= s.Start)); 

// Adjusted shifts 
var adjusted = shifts.Where(s => !unmodified.Contains(s) && !overlapped.Contains(s)) 
         .Select(s => new Shift 
         { 
          Start = exceptions.Where(e => e.Start <= s.Start && e.End > s.Start).Any() ? exceptions.Where(e => e.Start <= s.Start && e.End > s.Start).First().End : s.Start, 
          End = exceptions.Where(e => e.Start < s.End && e.End >= s.End).Any() ? exceptions.Where(e => e.Start < s.End && e.End >= s.End).First().Start : s.End 
         }); 

var newShiftSet = unmodified.Union(overlapped).Union(adjusted); 

E 'un esempio di base, anche se potrebbe essere compattato (anche se meno leggibile) e migliorato.

4

controlla questo article a CodeProject

E 'probabilmente troppo larga per il vostro problema specifico, ma probabilmente vi darà un buon punto di partenza su come risolverlo.

0

Non ho testato il codice del muggito, potrebbe esserci qualche bug, inoltre l'ho scritto nel textpad potrebbero esserci caratteri non validi, Idea è semplice, e cerco di usare variabili significative.

var orderedShifts = ShiftSets.OrderBy(x=>x.StartDate).ToList(); 

var compactShifts = new List<Shift>(); 
compactShifts.Add(orderedShifs[0]); 

foreach (var item in orderedShift) 
{ 
    if (item.Start <= compactShifts[compactShifts.Count-1].End 
     && item.End > compactShifts[compactShifts.Count-1].End) 
    { 
     compactShifts[compactShifts.Count-1].End = item.End; 
    } 
    else if (item.Start > compactShifts[compactShifts.Count-1].End) 
     compactShifts.Add(item); 
} 

//run similar procedure for schedule exceptions to create compact schedules. 

var validShifts = new List<Shift>(); 

foreach (var item in compactShifts) 
{ 
    var shiftCheatingPart = compactExceptions 
          .FirstOrDefault(x=>x.Start < item.Start 
             && x.End > item.End) 
    if (shiftCheatingPart != null) 
    { 
     if (item.End <= shiftCheatingPart.End) 
     continue; 

     validShifts.Add(new Shift{Start = shiftCheatingPart.End,End = item.End); 
    } 
} 

var totalTimes = validShifts.Sum(x=>x.End.Sunbtract(x.Start).TotalHours); 
0

Una soluzione molto grezzo sarebbe qualcosa di simile

void Main() 
{ 
    var workTime = new List<ShiftSet> { 
     new ShiftSet{StartTime= new TimeSpan(8,0,0),EndTime= new TimeSpan(10,0,0)}, 
     new ShiftSet{StartTime= new TimeSpan(10,0,0),EndTime= new TimeSpan(12,0,0)}, 
     new ShiftSet{StartTime= new TimeSpan(13,0,0),EndTime= new TimeSpan(15,0,0)}, 
     new ShiftSet{StartTime= new TimeSpan(15,0,0),EndTime= new TimeSpan(17,0,0)} 
     }; 


    var missingTime= new List<ShiftSet> { 
     new ShiftSet{StartTime= new TimeSpan(7,30,0),EndTime= new TimeSpan(10,30,0)}, 
     new ShiftSet{StartTime= new TimeSpan(14,35,0),EndTime= new TimeSpan(16,0,0)} 
     }; 


    Console.WriteLine(workTime.Sum(p=>p.Shift()) - missingTime.Sum(p=>p.Shift())); 
} 


public class ShiftSet 
{ 
    public TimeSpan StartTime {get;set;} 
    public TimeSpan EndTime {get;set;} 

    public double Shift() {return (EndTime-StartTime).TotalMinutes;} 
} 

ho calcolato un worktime nei minuti così posso riassumere più facilmente utilizzando LINQ

sto anche perdendo informazioni turno specifiche che credo non appartengono con ShiftSet classe

Because the employee is not scheduled to work from 7:30 to 8:00, we would not include that time

Problemi correlati