2017-06-02 76 views
1

我想將正確的小時數綁定到正確的工作時間段。工作周從週一到週日。根據當天的工作時間不同的價格。根據當天的時間完成的工作價格稱爲期間。我們使用24小時時間格式。根據工作日和小時+假日添加工作時間以更正價格類別

實施例:

  • PERIOD1:週一 - 週五,00:00 - 07:00
  • PERIOD2:週一 - 週五,07:00 - 20:00
  • Period3:週一 - 週五, 20:00 - 22:00
  • Period4:週一 - 週五,22:00 - 23:59(午夜)
  • Period5:星期六 - 星期日,00:00 - 07:00
  • Period6:星期六 - 太陽,07:00 - 22:00
  • Period7:星期六 - 星期日,22:00 - 23:59(午夜)
  • Period8:假日00:00 - 23:59

週期是這樣表示:

public class Period 
{ 
    public Period() 
    { 
    } 

    public string Name { get; set; } 
    public int Days { get; set; } 
    public bool Holiday { get; set; } 
    public TimeSpan Start { get; set; } 
    public TimeSpan End { get; set; } 
} 

天爲int,但值將來自該枚舉:

[Flags] 
public enum Workweek 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64 
} 

當週期Days屬性爲62這意味着I期有效期爲星期一至星期五,星期幾爲:65期間爲星期六至星期日。當Days是:6期間是從星期一到星期二。

Holiday爲真時表示該期間僅在休假日有效。節假日覆蓋正常的一天或週末。

工作班次是這樣表示:

public class Work 
{ 
    public Work() 
    { 
    } 

    public string Name { get; set; } 
    public DateTime Start { get; set; } 
    public DateTime End { get; set; } 
} 

假設我有一個List<Work>List<Period>我如何可以將綁定在工作時間以正確的期間?每個期間都有不同的定價。

例子:

案例1:如果你之間在週一工作班次:15:00和23:00,那麼工作班次將是這樣的:

  • PERIOD2:5小時
  • Period3:2小時
  • Period4:1小時

情況1。1:如果特定的星期一,節日,那麼這將是:

  • Period8 8小時

案例2:如果不是工作在週一開始於20:00,結束於04: 00第二天結果將是:

  • Period3:1小時
  • Period4:1小時
  • PERIOD1:四小時

案例2.2:如果星期一是假日,這將是:

  • Period8:四小時
  • PERIOD1:四小時

假期日子如List<DateTime>

我怎樣才能匹配正確的時間段?

我試過到目前爲止:

Work work = new Work() 
{ 
    Name = Demo, 
    Star = new DateTime(2017,05,02,15,00,00); 
    End = new DateTime(2017,05,02,23,00,00); 
}; 

List<Period> periods = new List<Period>(); 

foreach (var period in periods) 
{ 
    Workweek shiftDay = (Workweek)Enum.Parse(typeof(Workweek), work.Start.DayOfWeek, true); // i think this is wrong, because in the case where the end date is in the next day 


    Workweek periodDay = (Workweek)period.Days; 

    if ((shiftDay & periodDay) == shiftDay) 
    { 
     // the work matches the period 
    } 

} 

我想我應該使用foreach循環,並通過每個第二起始日期和結束日期之間,並檢查如果第二期天相匹配。

事情是這樣的:

public static IEnumerable<DateTime> EachSecond(this Work work) 
    { 
     DateTime currentSecond = new DateTime(work.Start.Year, work.Start.Month, work.Start.Day, work.Start.Hour, work.Start.Minute, work.Start.Second, work.Start.Millisecond); 
     while (currentSecond <= wor.kEnd) 
     { 
      yield return currentSecond; 
      currentSecond = currentSecond.AddSeconds(1); 
     } 
    } 

    Work work = new Work() 
    { 
     Name = Demo, 
     Star = new DateTime(2017,05,02,15,00,00); 
     End = new DateTime(2017,05,02,23,00,00); 
    }; 

    List<Period> periods = new List<Period>(); 

    foreach (var second in work.EachSecond()) 
    { 
      Workweek shiftSecond = (Workweek)Enum.Parse(typeof(Workweek), second.DayOfWeek, true); 

      foreach (var period in periods) 
      { 
       Workweek periodDay = (Workweek)period.Days; 

       if ((shiftSecond & periodDay) == shiftSecond) 
       { 

       } 
      } 
    } 
+2

你需要顯示至少一些試圖解決這個問題,計算器不是代碼編寫售後服務所有。 – Evk

+0

@Evk:更新了問題 – user2818430

+0

我認爲這個方法並不是太過於簡單。從我的頭頂我看到兩件事:1.你真的需要重複幾秒鐘?這段時間是基於分鐘的,所以我也會在匹配過程中使用分鐘。 2.您也可以查看[DateTime.CompareTo](https://msdn.microsoft.com/de-de/library/system.datetime.compare(v = vs.110).aspx),然後使用保存持續時間在這兩者之間可以節省循環,但可能需要更多的代碼。目前我無法生成示例:/ –

回答

1

工作例如:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Diagnostics; 

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var periods = new List<Period> { 
      new Period("1", Days.Workdays, TimeSpan.FromHours(0), TimeSpan.FromHours(7)), 
      new Period("2", Days.Workdays, TimeSpan.FromHours(7), TimeSpan.FromHours(20)), 
      new Period("3", Days.Workdays, TimeSpan.FromHours(20), TimeSpan.FromHours(22)), 
      new Period("4", Days.Workdays, TimeSpan.FromHours(22), TimeSpan.FromHours(24)), 
      new Period("5", Days.Weekend, TimeSpan.FromHours(0), TimeSpan.FromHours(7)), 
      new Period("6", Days.Weekend, TimeSpan.FromHours(7), TimeSpan.FromHours(22)), 
      new Period("7", Days.Weekend, TimeSpan.FromHours(22), TimeSpan.FromHours(24)), 
      new Period("8", Days.Holiday, TimeSpan.FromHours(0), TimeSpan.FromHours(24)), 
     }; 
     var holidays = new List<DateTime> { 
      new DateTime(2017, 1, 1), 
      new DateTime(2017, 1, 3), 
      new DateTime(2017, 1, 6), 
     }; 

     var sc = new ShiftCalculator(periods, holidays); 

     var shiftperiods = sc.GetShiftPeriods(new DateTime(2016, 12, 31, 22, 00, 00), new DateTime(2017, 01, 07, 08, 00, 00)).ToList(); 

     foreach (var sp in shiftperiods) 
     { 
      Console.WriteLine("{0} - {1} - {2} - {3:00.00}h", sp.Period.Name, sp.Period.Days, sp.Start, sp.Duration.TotalHours); 
     } 

    } 
} 

[Flags] 
enum Days : byte 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64, 
    Holiday = 128, 

    Workdays = Monday | Tuesday | Wednesday | Thursday | Friday, 
    Weekend = Saturday | Sunday, 
} 

[DebuggerDisplay("{Name}: {Days} ({Start}-{End})")] 
class Period 
{ 
    public Period(string name, Days days, TimeSpan start, TimeSpan end) 
    { 
     if (days.HasFlag(Days.Holiday) && days != Days.Holiday) 
      throw new ArgumentException("days"); 

     if (start > end) 
      throw new ArgumentException("end"); 

     Name = name; 
     Days = days; 
     Start = start; 
     End = end; 
    } 

    public string Name { get; private set; } 
    public Days Days { get; private set; } 
    public TimeSpan Start { get; private set; } 
    public TimeSpan End { get; private set; } 
} 

class ShiftPeriod 
{ 
    public Period Period { get; set; } 
    public DateTime Start { get; set; } 
    public TimeSpan Duration { get; set; } 
} 

class ShiftCalculator 
{ 
    private readonly List<Period> _periods; 
    private readonly List<DateTime> _holidays; 

    public ShiftCalculator(IEnumerable<Period> periods, IEnumerable<DateTime> holidays) 
    { 
     _periods = periods.ToList(); 
     _holidays = holidays.Select(e => e.Date).ToList(); 
    } 

    public IEnumerable<ShiftPeriod> GetShiftPeriods(DateTime start, DateTime end) 
    { 
     if (start > end) throw new ArgumentException("end"); 

     var current = start; 

     while (current < end) 
     { 
      var period = GetPeriodByDateTime(current); 

      var next = current.Date + period.End; 

      if (next > end) 
      { 
       next = end; 
      } 

      yield return new ShiftPeriod 
      { 
       Period = period, 
       Start = current, 
       Duration = next - current, 
      }; 

      current = next; 
     } 

    } 

    private Days GetDayFromDateTime(DateTime datetime) 
    { 
     Days day; 
     if (_holidays.Contains(datetime.Date)) 
     { 
      day = Days.Holiday; 
     } 
     else 
     { 
      switch (datetime.DayOfWeek) 
      { 
       case DayOfWeek.Sunday: 
       day = Days.Sunday; 
       break; 
       case DayOfWeek.Monday: 
       day = Days.Monday; 
       break; 
       case DayOfWeek.Tuesday: 
       day = Days.Tuesday; 
       break; 
       case DayOfWeek.Wednesday: 
       day = Days.Wednesday; 
       break; 
       case DayOfWeek.Thursday: 
       day = Days.Thursday; 
       break; 
       case DayOfWeek.Friday: 
       day = Days.Friday; 
       break; 
       case DayOfWeek.Saturday: 
       day = Days.Saturday; 
       break; 
       default: 
       throw new InvalidOperationException(); 
      } 
     } 
     return day; 
    } 

    private Period GetPeriodByDateTime(DateTime datetime) 
    { 
     var day = GetDayFromDateTime(datetime); 
     var timeOfDay = datetime.TimeOfDay; 
     var period = _periods.Where(
      e => e.Days.HasFlag(day) && e.Start <= timeOfDay && e.End > timeOfDay) 
      .FirstOrDefault(); 
     if (period == null) 
     { 
      throw new InvalidOperationException(); 
     } 
     return period; 
    } 
} 

.net fiddle

生成的輸出

 
7 - Weekend - 12/31/2016 10:00:00 PM - 02.00h 
8 - Holiday - 1/1/2017 12:00:00 AM - 24.00h 
1 - Workdays - 1/2/2017 12:00:00 AM - 07.00h 
2 - Workdays - 1/2/2017 7:00:00 AM - 13.00h 
3 - Workdays - 1/2/2017 8:00:00 PM - 02.00h 
4 - Workdays - 1/2/2017 10:00:00 PM - 02.00h 
8 - Holiday - 1/3/2017 12:00:00 AM - 24.00h 
1 - Workdays - 1/4/2017 12:00:00 AM - 07.00h 
2 - Workdays - 1/4/2017 7:00:00 AM - 13.00h 
3 - Workdays - 1/4/2017 8:00:00 PM - 02.00h 
4 - Workdays - 1/4/2017 10:00:00 PM - 02.00h 
1 - Workdays - 1/5/2017 12:00:00 AM - 07.00h 
2 - Workdays - 1/5/2017 7:00:00 AM - 13.00h 
3 - Workdays - 1/5/2017 8:00:00 PM - 02.00h 
4 - Workdays - 1/5/2017 10:00:00 PM - 02.00h 
8 - Holiday - 1/6/2017 12:00:00 AM - 24.00h 
5 - Weekend - 1/7/2017 12:00:00 AM - 07.00h 
6 - Weekend - 1/7/2017 7:00:00 AM - 01.00h 
+0

如果我們添加一個跨越午夜的時間段,我們如何才能使其工作如此:'新時期(「100」,Days.Workdays,TimeSpan.FromHours(22),TimeSpan .FromHours(07)'注意開始時間是22:00,結束時間是07:00。 – user2818430

1

嘗試這樣的事情。我不知道爲什麼當你使用標準的DayOfWeek時你需要定製的工作周。把我按照你的要求。

using System.Collections.ObjectModel; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Text.RegularExpressions; 

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

     } 

    } 
    public class Period 
    { 
     public static List<Period> periods = new List<Period>() { 
      new Period() { Name = "Period1", Days = new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(0,0,0), End = new TimeSpan(7,0,0)}, 
      new Period() { Name = "Period2", Days = new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(7,0,0), End = new TimeSpan(20,0,0)}, 
      new Period() { Name = "Period3", Days = new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(20,0,0), End = new TimeSpan(22,0,0)}, 
      new Period() { Name = "Period4", Days = new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(22,0,0), End = new TimeSpan(24,0,0)}, 
      new Period() { Name = "Period5", Days = new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(0,0,0), End = new TimeSpan(7,0,0)}, 
      new Period() { Name = "Period6", Days = new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(7,0,0), End = new TimeSpan(22,0,0)}, 
      new Period() { Name = "Period7", Days = new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(22,0,0), End = new TimeSpan(24,0,0)}, 
      new Period() { Name = "Period8", Days = null, Holiday = true, Start = new TimeSpan(0,0,0), End = new TimeSpan(24,0,0)}, 
     }; 

     public string Name { get; set; } 
     public Workweek[] Days { get; set; } 
     public bool Holiday { get; set; } 
     public TimeSpan Start { get; set; } 
     public TimeSpan End { get; set; } 

     public static string GetName(DateTime startTime, DateTime endTime, Boolean holiday) 
     { 
      string name = ""; 

      if (holiday) 
      { 
       name = "Period8"; 
      } 
      else 
      { 

       foreach (Period period in periods) 
       { 
        Boolean dayMatch = period.Days.Select(x => x == (Workweek)(2^(int)startTime.DayOfWeek)).Any(); 
        if (dayMatch) 
        { 
         if ((startTime.TimeOfDay > period.Start) && (endTime.TimeOfDay < period.End)) 
         { 
          name = period.Name; 
          break; 
         } 
        } 

       } 
      } 

      return name; 
     } 
    } 
    public enum Workweek 
    { 
     Sunday = 1, 
     Monday = 2, 
     Tuesday = 4, 
     Wednesday = 8, 
     Thursday = 16, 
     Friday = 32, 
     Saturday = 64 
    } 
    public class Work 
    { 

     public string Name { get; set; } 
     public DateTime Start { get; set; } 
     public DateTime End { get; set; } 
    } 


} 
+0

dayMatch我錯過了一個等號。應該是「x => x ==」 – jdweng

相關問題