2016-03-24 7 views
0

Ich habe ein Wörterbuch Spezifizierungswochenarbeitszeitintervalle für Tag wie MSProject bietet: enter image description hereIterieren Zeitintervalle von DayOfWeek Arbeitszeit Kalender

Wörterbuch des folgenden Typs ist:

new Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> 
{ 
    [DayOfWeek.Monday] = new[] 
    { 
     Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
     Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
    }, 
    [DayOfWeek.Tuesday] = new[] 
    { 
     Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
     Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
    }, 
... 

Mein Ziel ist zu implementieren einen Iterator ergibt Datum-Zeit-Intervalle beginnend mit Datum, das als Argument übergeben wurde:

IEnumerable<Tuple<DateTime, TimeSpan>> IterateTimeslots(DateTime startingFrom); 

Test Case # 1:

das Wörterbuch hat Tupeln von Arbeitsstunden (08.00 bis 12.00), (13.00 bis 17.00 Uhr) für jeden Tag der Woche außer Sonntag und Samstag, Executing

IterateTimeslots (DateTime.Parse ("2016.03.20 00.00")) // Sonntag

zurückkehren sollte:

(03/21/2016 8AM, 4hrs) 
(03/21/2016 1PM, 4hrs) 
(03/22/2016 8AM, 4Hrs) 
(03/22/2016 8AM, 4Hrs) 
... (endless iteration) 

Testfall # 2 (Benachbarte Intervalle fusionierten): Wörterbuch können Intervalle repräsentieren, die, wie die folgenden zum nächsten Tag geht:

[Monday] = (12AM-9AM),(9PM-12AM)  //Ending 12AM = TimeSpan.FromHours(24) 
[Tuesday] = (12AM-9AM),(9PM-12AM) 
... 

Iterator zu einer Einheit verschmelzen sollte benachbarte Intervalle. Also für startdate „2016.03.20 00.00“ es wird die folgende zurück:

(03/21/2016 12AM, 9Hrs) 
(03/21/2016 9PM, 12Hrs) //Intervals crosses to next day 
(03/22/2016 9PM, 12Hrs) //Intervals crosses to next day 
(03/23/2016 9PM, 12Hrs) //Intervals crosses to next day 
... (endless enumeration) 

Testfall # 3 (24/7): 24/7 Arbeitsstunden sollten mit Timespan = Timespan einzelnes Intervall iterieren .MaxValue. Also für jeden Tag der Woche smth Wörterbuch enthalten wie folgt aus:

[Sunday] = (12AM-12AM) 
[Monday] = (12AM-12AM) 
[Tuesday] = (12AM-12AM) 
... 

Also für startdate „2016.03.20 08.00 Uhr“ es sollte enumerable zurückkehren mit nur einem Artikel:

(03/20/2016 8AM, TimeSpan.MaxValue) 

Wie zu implementieren IterateTimeslots Funktion? jede Hilfe ist appreaciated

+0

So Ihre 'TimeSpan's begrenzt sind von 0 - 24 Std denke ich? Und Tupel stellen einschließende Start-/exklusive Endzeitbereiche dar. –

+0

Das Wörterbuch Zeitspannen sind begrenzt, aber nicht die, die vom Iterator –

+0

zurückgegeben werden. Ja, das vom Iterator zurückgegebene Tupel repräsentiert das Intervall mit Inclusive Start und Exclusive End –

Antwort

0

Ich experimentierte dies und kam mit folgenden. Entschuldigung, mehr als die Hälfte des Codes sind die Testdaten, aber ich habe sie hinzugefügt, damit das ganze Programm schnell ausgeführt werden kann. Außerdem habe ich den in der Frage genau erwähnten Code nicht strukturiert. Der Code konzentriert sich hauptsächlich auf die Produktion IEnumerable<Tuple<DateTime, TimeSpan>>, die Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> als Eingabe gegeben wird.

public class Program 
{ 
    public static void Main(string[] args) 
    { 

     Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> workHours = new Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> 
     { 
      { 
       DayOfWeek.Sunday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      }, 
      { 
       DayOfWeek.Monday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      }, 
      { 
       DayOfWeek.Tuesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      } 
      , 
      { 
       DayOfWeek.Wednesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      } 
      , 
      { 
       DayOfWeek.Thursday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      } 
      , 
      { 
       DayOfWeek.Friday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      } 
      , 
      { 
       DayOfWeek.Saturday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(8), TimeSpan.FromHours(12)), //8AM-12PM 
        Tuple.Create(TimeSpan.FromHours(13), TimeSpan.FromHours(17)) //1PM-5PM 
       } 
      } 
     }; 


     Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> workHours1 = new Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> 
     { 
      { 
       DayOfWeek.Sunday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      }, 
      { 
       DayOfWeek.Monday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      }, 
      { 
       DayOfWeek.Tuesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Wednesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Thursday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Friday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Saturday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(9)), //12AM-9AM 
        Tuple.Create(TimeSpan.FromHours(21), TimeSpan.FromHours(24)) //9PM-12AM 
       } 
      } 
     }; 


     Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> workHours2 = new Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> 
     { 
      { 
       DayOfWeek.Sunday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      }, 
      { 
       DayOfWeek.Monday, 
       new[] { 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      }, 
      { 
       DayOfWeek.Tuesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Wednesday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Thursday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Friday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      } 
      , 
      { 
       DayOfWeek.Saturday, 
       new[]{ 
        Tuple.Create(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) //12AM-12AM 
       } 
      } 
     }; 


     DateTime currDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day); 
     DateTime firstDateOfWeek = currDate.AddDays(-1 * (int)currDate.DayOfWeek); 

     Console.WriteLine("First Date Of Week " + firstDateOfWeek); 

     //this list will produce values of test case #1 
     List<Tuple<DateTime, TimeSpan>> dailyWorkHours = workHours.SelectMany(kvp => kvp.Value, 
      (k, v) => Tuple.Create<DateTime, TimeSpan> ( 
       firstDateOfWeek.AddDays((int)k.Key).AddHours(v.Item1.Hours), 
       v.Item2 - v.Item1 
      )).ToList(); 

     foreach (var item in dailyWorkHours) 
     { 
      Console.WriteLine(item.Item1 + " " + item.Item2); 
     } 

     //handle Test case #2 
     //Test case #3 is extension of test case #2 
     List<Tuple<DateTime, TimeSpan>> finalWorkHours = new List<Tuple<DateTime, TimeSpan>>(); 

     finalWorkHours.Add(dailyWorkHours.First()); 

     //idea is to compare current item in dailyWorkHours 
     //with the previous item (that is currently in finalWorkHours) 
     foreach (var item in dailyWorkHours) 
     { 
      if (dailyWorkHours.IndexOf(item) == 0) 
      { 
       continue; 
      } 

      Tuple<DateTime, TimeSpan> finalLast = finalWorkHours.Last(); 

      //handle Test case #2 merge last item in finalWorkHours with current item 
      //if last item's time span added to last item's date and it equals to current item date 
      if (DateTime.Compare(finalLast.Item1.AddHours(finalLast.Item2.TotalHours), item.Item1) == 0) 
      { 
       finalWorkHours.RemoveAt(finalWorkHours.Count - 1); 
       finalWorkHours.Add(Tuple.Create(finalLast.Item1, finalLast.Item2.Add(item.Item2))); 
      } 
      else { 
       finalWorkHours.Add(item); 
      } 
     } 

     Console.WriteLine("Final work hours"); 

     foreach (var item in finalWorkHours) 
     { 
      Console.WriteLine(item.Item1 + " " + item.Item2.TotalHours + " hrs"); 
     } 

     Console.ReadKey(); 
    } 
} 
0

Sie hier gehen (siehe die Kommentare in dem Code):

public static class Algorithms 
{ 
    public static IEnumerable<Tuple<DateTime, TimeSpan>> IterateTimeslots(
     this Dictionary<DayOfWeek, IEnumerable<Tuple<TimeSpan, TimeSpan>>> input, 
     DateTime startingFrom) 
    { 
     // Convert the input to ordered array of ranges containing 
     // absolute offsets from the beginning of the week 
     var ranges = input.SelectMany(e => e.Value.Select(v => new 
     { 
      Start = TimeSpan.FromDays((int)e.Key) + v.Item1, 
      End = TimeSpan.FromDays((int)e.Key) + v.Item2 
     })) 
     .OrderBy(e => e.Start) 
     .ToArray(); 
     // Corner case: empty input 
     if (ranges.Length == 0) yield break; 
     // Test case #2: merge adjacent ranges 
     int first = 0, last = first; 
     for (int i = 1; i < ranges.Length; i++) 
     { 
      if (ranges[i].Start > ranges[last].End) 
       ranges[++last] = ranges[i]; 
      else 
       ranges[last] = new { Start = ranges[last].Start, End = ranges[i].End }; 
     } 
     var weekLength = TimeSpan.FromDays(7); 
     if (ranges[last].End == weekLength && ranges[first].Start == TimeSpan.Zero) 
     { 
      // Test case #3: (24/7) 
      if (last == first) 
      { 
       yield return Tuple.Create(startingFrom, TimeSpan.MaxValue); 
       yield break; 
      } 
      ranges[last] = new { Start = ranges[last].Start, End = ranges[last].End + ranges[first].End }; 
      first++; 
     } 
     // Test case #1: Generate infinite intervals 
     var weekStart = new DateTime(startingFrom.Year, startingFrom.Month, startingFrom.Day, 
      0, 0, 0, startingFrom.Kind) - TimeSpan.FromDays((int)startingFrom.DayOfWeek); 
     for (int i = 0; ; i++) 
     { 
      if (i > last) 
      { 
       weekStart += weekLength; 
       i = first; 
      } 
      var start = weekStart + ranges[i].Start; 
      var end = weekStart + ranges[i].End; 
      if (end > startingFrom) 
      { 
       if (start < startingFrom) start = startingFrom; 
       yield return Tuple.Create(start, end - start); 
      } 
     } 
    } 
}