2015-09-15 33 views
0

我有一個問題處理日期時間段,當一天在不同時段開始的班次劃分。我正在尋求解決這個在c#如何處理不同時段一天開始的時段?

例1: 我有一個事件,從20150901 06:00到20150902 03:00。我的工作班次是D(06:00至18:00)和N(18:00至06:00)。我想將事件分配給班次日期時間值。

START DATETIME  END DATETIME 
20150901 0600  20150902 0300 

SHIFT START END 
D  0600 1800 
N  1800 0600 

,我應該得到的時隙是:

DATE  SHIFT STARTTIME ENDTIME 
20150901 D  0600   1800 
20150901 N  1800   0300 

例2: 當天在四個換檔分,但在當天06:00(01開頭:0600-1200,02 :1200-1800,03:1800-2400,04:0000-0600)。本次活動由20150901上午08:00去20150903 10:00

START DATETIME  END DATETIME 
20150901 0800  20150903 1000 

SHIFT START END 
01  0600 1159 
02  1200 1759 
03  1800 2359 
04  0000 0559 

的時隙我應該得到的是:

DATE  SHIFT STARTTIME ENDTIME 
20150901 01  0800  1200 
20150901 02  1200  1800 
20150901 03  1800  0000 
20150901 04  0000  0600 
20150902 01  0600  1200 
20150902 02  1200  1800 
20150902 03  1800  0000 
20150902 04  0000  0600 
20150903 01  0600  1000 

例3: 當天在四個換檔分,但一天從06:00開始(01:0600-1200,02:1200-1800,03:1800-2400,04:0000-0600)。本次活動由20150901上午02點去20150902 10:00

START DATETIME  END DATETIME 
20150901 0200  20150902 1000 

SHIFT START END 
01  0600 1159 
02  1200 1759 
03  1800 2359 
04  0000 0559 

的時隙我應該得到的是:

DATE  SHIFT STARTTIME ENDTIME 
20150831 04  0200  0600 
20150901 01  0800  1200 
20150901 02  1200  1800 
20150901 03  1800  0000 
20150901 04  0000  0600 
20150902 01  0600  1000 

編輯1:補充一點,我的源代碼。

編輯2:添加例如3和糾正由馬特·約翰遜提出了一些點

的代碼適用於某些情況下,但我仍然有錯誤時,該事件是某種轉變邊界之外(活動開始例如第一次輪班之前)。

public class slot 
    { 
     public DateTime date; 
     public TimeSpan startHour; 
     public TimeSpan endHour; 
     public string shiftCode; 
    } 


    public List<slot> getSlots() 
    { 
     slot[] shifts = new slot[4]; 
     shifts[0] = new slot(); 
     shifts[0].startHour = new TimeSpan(06, 00, 00); 
     shifts[0].endHour = new TimeSpan(12, 00, 00); 
     shifts[0].shiftCode = "01"; 
     shifts[1] = new slot(); 
     shifts[1].startHour = new TimeSpan(12, 00, 00); 
     shifts[1].endHour = new TimeSpan(18, 00, 00); 
     shifts[1].shiftCode = "02"; 
     shifts[2] = new slot(); 
     shifts[2].startHour = new TimeSpan(18, 00, 00); 
     shifts[2].endHour = new TimeSpan(00, 00, 00); 
     shifts[2].shiftCode = "03"; 
     shifts[3] = new slot(); 
     shifts[3].startHour = new TimeSpan(00, 00, 00); 
     shifts[3].endHour = new TimeSpan(06, 00, 00); 
     shifts[3].shiftCode = "04"; 

     DateTime startEvent = new DateTime(2015, 09, 01, 08, 00, 00); 
     DateTime endEvent = new DateTime(2015, 09, 03, 10, 00, 00); 

     int i = 0; 
     //To find the starting shift for the event 
     while (!(
       shifts[i].startHour <= shifts[i].endHour 
        ? (startEvent.TimeOfDay >= shifts[i].startHour && startEvent.TimeOfDay < shifts[i].endHour) 
        : (startEvent.TimeOfDay >= shifts[i].startHour || startEvent.TimeOfDay < shifts[i].endHour) 
       )) 
      i++; 

     DateTime slotStart = startEvent; 
     DateTime slotEnd = slotStart.Date + shifts[i].endHour; 

     List<slot> slotList = new List<slot>(); 

     while(endEvent >= slotEnd) 
     { 
      slot newSlot = new slot(); 
      newSlot.date = slotStart; 
      newSlot.startHour = slotStart.TimeOfDay; 
      newSlot.endHour = shifts[i].endHour; 
      newSlot.shiftCode = shifts[i].shiftCode; 
      slotList.Add(newSlot); 
      i++; 

      if (i >= shifts.Length) 
       i = 0; 

      if (shifts[i].startHour < newSlot.endHour) 
       slotStart = slotStart.Date.AddDays(1); 

      slotEnd = slotStart.Date + shifts[i].endHour; 
      slotStart = slotStart.Date + shifts[i].startHour; 
     } 

     slot lastSlot = new slot(); 
     lastSlot.date = slotStart; 
     lastSlot.startHour = slotStart.TimeOfDay; 
     lastSlot.endHour = endEvent.TimeOfDay; 
     lastSlot.shiftCode = shifts[i].shiftCode; 
     slotList.Add(lastSlot); 

     return slotList; 
    } 
+2

你有沒有嘗試過任何東西?我們可以提供指導但不完整的解決方案。 – jjczopek

+0

對不起,我忘了添加它。這是迄今爲止我得到的。我想知道是否有更簡單/更好的方法可以解決前沿問題。 –

回答

0

爲了幫助你一起,頂循環可以是這樣的:

var currentTime = startTime; 
while(currentTime < endTime) { 
    var shift = FindShift(currentTime); 
    if (shift.EndTime > endTime) { 
     shift.EndTime = endTime; 
    } 
    Print(shift); 
    currentTime = shift.EndTime; 
} 
1

有幾件事情:

  1. 您需要的日期增量從倒班分離重置:

    您有:

    if (i >= shifts.Length) 
    { 
        i = 0; 
        slotStart = slotStart.AddDays(1); 
    } 
    

    哪些應改爲:

    if (i >= shifts.Length) 
    { 
        i = 0; 
    } 
    
    if (shifts[i].startHour < newSlot.startHour) 
    { 
        slotStart = slotStart.Date.AddDays(1); 
    } 
    

    這是主要的罪魁禍首。

  2. 在開始時間測試中,邏輯稍微偏離。它應該是:

    while (!(
        shifts[i].startHour <= shifts[i].endHour 
         ? (startEvent.TimeOfDay >= shifts[i].startHour && startEvent.TimeOfDay < shifts[i].endHour) 
         : (startEvent.TimeOfDay >= shifts[i].startHour || startEvent.TimeOfDay < shifts[i].endHour) 
        )) 
        i++; 
    

    你寫的東西略有不同。您正在使用&&將第一個測試與真實部分合並,但與等式的其餘部分混合時,這不會在邏輯上保持不變。

  3. 通常,您應該考慮調整代碼以使用半開範圍。應該從06:00到17:59,而不是從06:00到18:00。然後在測試終點時使用獨佔運算符。換句話說start <= testValue < end。這有幾個優點,包括可以很容易地減去以獲得持續時間,並防止精度錯誤(因爲17:59:59.999仍在範圍內)。 注意:這一點基於編輯前的原始問題。

  4. 你可以通過使用LINQ而不是那些循環來節省很多麻煩。此外,您的命名約定與正常的C#樣式不匹配。

  5. 這些類型的問題往往是比較容易的原因有關使用Noda Time類型時,如LocalDateLocalTimeLocalDateTime。如果以後您需要考慮時區,夏令時等 - 您將處於更好的位置,以便映射到ZonedDateTime值,計算Duration值或投影到Instant值。

  6. 您是否考慮過在班次不滿的情況下該怎麼辦?您可能需要計算缺失的時間段,並將其顯示爲錯誤輸出或「UNASSIGNED」切換代碼。

+0

謝謝。 1)它解決了時間分配問題,但日期仍然是一個問題(參見新的例子3)。 2年3)感謝您指出這一點。 4 y 5)從來沒有與此工作,我會檢查看看如何6)我沒有想到這一點,但是,這可能是一個問題。 你能指出我c#風格的約定嗎? –

+0

WRT約定,您應該使用公共屬性,而不是公共字段,而方法,類和屬性名稱應該是'PascalCased'而不是'camelCased'。有關詳細信息,請參見[框架設計指南](https://msdn.microsoft.com/zh-cn/library/ms229042.aspx)。 –

+0

看我的編輯。比較兩者上的'startHour'就行了。 –

0

這是我現在使用的結果代碼。到目前爲止,我用幾個數據對它進行了測試,其工作正常,即使在時間邊界。

我遵循了馬特約翰遜給我的一些指導,讓它工作,所以謝謝你馬特。

要考慮的是,輪班日期從第一班StartHour開始。這意味着如果輪班組在上午06:00開始,則前一天的小時數屬於前一天。

例如: 當天分爲四班。活動從20150901 02:00至20150902 04:00。所以,即使它似乎根據移位日開始在20150902的20150901和結束這將是20150931和20150901

START DATETIME  END DATETIME 
20150901 0200  20150902 0400 

SHIFT START END 
01  0600 1159 
02  1200 1759 
03  1800 2359 
04  0000 0559 

的時隙我應該得到的是:

DATE  SHIFT STARTTIME ENDTIME 
20150831 04  0200  0600 
20150901 01  0800  1200 
20150901 02  1200  1800 
20150901 03  1800  0000 
20150901 04  0000  0400 

的源代碼:

public class Slot 
    { 
     public DateTime Date; 
     public TimeSpan StartHour; 
     public TimeSpan EndHour; 
     public string ShiftCode; 
    } 

    public List<Slot> GetSlots() 
    { 
     //Shifts Array 
     Slot[] shifts = new Slot[4]; 
     shifts[0] = new Slot(); 
     shifts[0].StartHour = new TimeSpan(06, 00, 00); 
     shifts[0].EndHour = new TimeSpan(12, 00, 00); 
     shifts[0].ShiftCode = "01"; 
     shifts[1] = new Slot(); 
     shifts[1].StartHour = new TimeSpan(12, 00, 00); 
     shifts[1].EndHour = new TimeSpan(18, 00, 00); 
     shifts[1].ShiftCode = "02"; 
     shifts[2] = new Slot(); 
     shifts[2].StartHour = new TimeSpan(18, 00, 00); 
     shifts[2].EndHour = new TimeSpan(24, 00, 00); 
     shifts[2].ShiftCode = "03"; 
     shifts[3] = new Slot(); 
     shifts[3].StartHour = new TimeSpan(00, 00, 00); 
     shifts[3].EndHour = new TimeSpan(06, 00, 00); 
     shifts[3].ShiftCode = "04"; 

     //Event TimeStamps 
     DateTime startEvent = new DateTime(2015, 09, 01, 02, 00, 00); 
     DateTime endEvent = new DateTime(2015, 09, 03, 08, 00, 00); 

     if (endEvent < startEvent) 
      return null; 

     int i = 0; 
     //To find the starting shift for the event 
     while (!(
       shifts[i].StartHour <= shifts[i].EndHour 
        ? (startEvent.TimeOfDay >= shifts[i].StartHour && startEvent.TimeOfDay < shifts[i].EndHour) 
        : (startEvent.TimeOfDay >= shifts[i].StartHour || startEvent.TimeOfDay < shifts[i].EndHour) 
       )) 
      i++; 

     //to establish the date part of the datetime according to the starttime of the shift day 
     startEvent = startEvent.AddTicks(-shifts[0].StartHour.Ticks).Date + startEvent.TimeOfDay; 
     endEvent = endEvent.AddTicks(-shifts[0].StartHour.Ticks).Date + endEvent.TimeOfDay; 

     DateTime slotStart = startEvent; 
     DateTime slotEnd = slotStart.Date + shifts[i].EndHour; 

     List<Slot> slotList = new List<Slot>(); 

     while (endEvent.Date > slotEnd.Date || (endEvent.Date == slotEnd.Date && !(
       shifts[i].StartHour <= shifts[i].EndHour 
        ? (endEvent.TimeOfDay >= shifts[i].StartHour && endEvent.TimeOfDay < shifts[i].EndHour) 
        : (endEvent.TimeOfDay >= shifts[i].StartHour || endEvent.TimeOfDay < shifts[i].EndHour) 
       ))) 
     { 
      Slot newSlot = new Slot(); 
      newSlot.Date = slotStart.Date; 
      newSlot.StartHour = slotStart.TimeOfDay; 
      newSlot.EndHour = shifts[i].EndHour; 
      newSlot.ShiftCode = shifts[i].ShiftCode; 
      slotList.Add(newSlot); 
      i++; 

      if (i >= shifts.Length) 
      { 
       i = 0; 
       slotStart = slotStart.Date.AddDays(1); 
      } 

      slotEnd = slotStart.Date + shifts[i].EndHour; 
      slotStart = slotStart.Date + shifts[i].StartHour; 
     } 

     Slot lastSlot = new Slot(); 
     lastSlot.Date = slotStart; 
     lastSlot.StartHour = slotStart.TimeOfDay; 
     lastSlot.EndHour = endEvent.TimeOfDay; 
     lastSlot.ShiftCode = shifts[i].ShiftCode; 
     slotList.Add(lastSlot); 

     return slotList; 
    } 
相關問題