2012-01-16 27 views
7

Tôi đang cố gắng xây dựng một công cụ tính toán thứ gọi là hạn ngạch dựa trên thời điểm nhân viên được lên lịch làm việc và khi họ yêu cầu.Làm cách nào để tìm giao lộ của hai bộ Thời gian không tiếp giáp?

đối tượng ShiftSet của tôi là một tập các đối tượng phím Shift trong đó bao gồm một StartTime và EndTime (cả hai loại thời gian (7). Mỗi ShiftSet tương ứng với một ngày.

ScheduleExceptions những lúc mà một nhân viên có tắt. Có có thể là bất kỳ số ScheduleExceptions không trùng lặp chồng chéo hoặc trong một ngày Họ là các kiểu dữ liệu datetime

một ví dụ về ShiftSet:..
08: 00-10: 00
10: 00-12: 00
13: 00-15: 00
15:00 -17: 00

Một ví dụ về ScheduleExceptions cho rằng cùng ngày:
07: 30-10: 30
14: 35-16: 00

Những gì tôi cần làm là để tìm số lượng thời gian mà nhân viên làm việc trong một ngày. Cách tôi có thể hình dung để làm điều này là tính toán giao điểm của ShiftSet và nghịch đảo của ScheduleExceptions.

Tôi làm như thế nào với thời gian? Tôi muốn sử dụng LINQ nếu có thể.

+0

Tôi có thể hỏi kiểu 'time (7)' trong C# không? –

+0

Đó là thời gian trong sql, nhưng trong C# đó là timespan. –

+0

Bạn có cần tìm tổng thời gian hay bạn muốn tìm giờ bắt đầu/kết thúc thực tế mà một nhân viên đang làm việc? – Abel

Trả lời

2

Như InBetween đã đề cập, có các thư viện ở đó đã giải quyết được vấn đề này, nhưng chúng cũng giải quyết được nhiều vấn đề liên quan. Nếu bạn chỉ muốn giải quyết vấn đề cụ thể này mà không phải chịu sự phụ thuộc khác, bạn có thể thử những điều sau đây.

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

Đây là ví dụ cơ bản, mặc dù nó có thể được đầm chặt (mặc dù ít đọc được) và được cải thiện.

4

Check-out lớn article này tại CodeProject

Đây có thể là cách quá rộng cho vấn đề cụ thể của bạn, nhưng nó có lẽ sẽ cung cấp cho bạn một điểm khởi đầu tốt về làm thế nào để giải quyết nó.

0

Tôi không kiểm tra mã dưới, có thể có một số lỗi, Ngoài ra tôi đã viết nó trong textpad có thể có các ký tự không hợp lệ, Ý tưởng là đơn giản và tôi cố gắng sử dụng các biến có ý nghĩa.

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

Một giải pháp rất thô sẽ là một cái gì đó giống như

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

tôi tính toán một WorkTime trong vài phút vì vậy tôi có thể tóm tắt một cách dễ dàng hơn khi sử dụng LINQ

Tôi cũng thiếu thông tin thay đổi cụ thể mà tôi nghĩ không thuộc về ShiftSet lớp

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

Các vấn đề liên quan