2012-01-16 10 views
7

Estoy tratando de construir una herramienta que calcule algo llamado cuota en función de cuándo los empleados están programados para trabajar y cuándo solicitan la baja.¿Cómo encuentro la intersección de dos conjuntos de tiempos no contiguos?

Mi objeto ShiftSet es un conjunto de objetos de desplazamiento que consisten en una StartTime y EndTime (tanto de tipo tiempo (7). Cada ShiftSet corresponde a un día.

ScheduleExceptions veces que un empleado tiene apagado. Hay puede ser cualquier número de ScheduleExceptions solapantes no se solapan o en un día son del tipo de datos de fecha y hora

un ejemplo de un ShiftSet:..
08: 00-10: 00
10: 00-12: 00
13: 00-15: 00
15:00 -17: 00

Un ejemplo de ScheduleExceptions para ese mismo día:
07: 30-10: 30
14: 35-16: 00

Lo que tengo que hacer es encontrar la cantidad de tiempo que el empleado está trabajando en un día. La forma en que puedo hacer esto es calcular la intersección de ShiftSet y el inverso de ScheduleExceptions.

¿Cómo voy a hacer esto con el tiempo? Preferiría usar Linq si es posible.

+0

¿Puedo preguntar qué tipo de 'tiempo (7)' está en C#? –

+0

Es hora en sql, pero en C# es el intervalo de tiempo. –

+0

¿Necesita encontrar el tiempo total, o desea encontrar las horas reales de inicio/finalización que está trabajando un empleado? – Abel

Respuesta

2

Como se mencionó InBetween, hay bibliotecas por ahí que han resuelto este problema, pero que resuelven muchos problemas relacionados también. Si desea abordar este problema en particular sin asumir otra dependencia, puede intentar lo siguiente.

// 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); 

Es un ejemplo básico, aunque podría ser compactado (aunque menos legible) y mejorado.

4

Control hacia fuera este gran article en CodeProject

Es probablemente demasiado amplio para su problema específico, sino que probablemente le dará un buen punto de partida sobre cómo resolverlo.

0

No probé el código de la parte inferior, puede haber algunos errores, también lo escribí en el teclado de texto puede haber caracteres no válidos, la idea es simple y trato de usar variables significativas.

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 solución muy cruda sería algo así como

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;} 
} 

puedo calcular un tiempo de trabajo en cuestión de minutos, así que se puede resumir más fácilmente usando LINQ

También me falta información específica de cambio que creo no pertenecen a la clase ShiftSet

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

Cuestiones relacionadas