2011-06-30 72 views
7

Tôi có một phương pháp C# như thế này:Số ngày trong phạm vi ngày, trừ ngày cuối tuần và các ngày khác, trong C#

public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates) 
{ 
} 

gì đó là nghĩa vụ phải làm là tính toán số ngày giữa STARTDATE và ENDDATE, nhưng tùy chọn cần phải loại trừ các ngày cuối tuần và các ngày khác (được chuyển thành chuỗi ngày phân cách bằng dấu phẩy).

Tôi hoàn toàn không biết cách giải quyết vấn đề này. Bản năng ruột của tôi sẽ lặp lại từ startDate thành endDate và thực hiện một số so sánh chuỗi, nhưng từ những gì tôi có thể tìm ra, C# không cho phép lặp qua các ngày theo cách đó - hoặc ít nhất nó không phải là cách làm việc rất tao nhã.

+0

một O tốt hơn (1) giải pháp có thể được tìm thấy ở đây: stackoverflow.com/questions/1044688 –

Trả lời

8

Dưới đây là một ví dụ bao gồm ngày bị loại trừ, ngày cuối tuần và vòng lặp. Tôi đã thay đổi chuỗi excludeDates thành một List mặc dù. Một số kiểm tra null nên được thêm vào.

public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, List<DateTime> excludeDates) 
    { 
     int count = 0; 
     for (DateTime index = startDate; index < endDate; index = index.AddDays(1)) 
     { 
      if (excludeWeekends && index.DayOfWeek != DayOfWeek.Sunday && index.DayOfWeek != DayOfWeek.Saturday) 
      { 
       bool excluded = false; ; 
       for (int i = 0; i < excludeDates.Count; i++) 
       { 
        if (index.Date.CompareTo(excludeDates[i].Date) == 0) 
        { 
         excluded = true; 
         break; 
        } 
       } 

       if (!excluded) 
       { 
        count++; 
       } 
      } 
     } 

     return count; 
    } 

EDIT: Tôi muốn chỉ ra rằng tôi sẽ xem xét phương pháp này nhanh chóng và bẩn - nếu bạn không phải làm điều này thường xuyên. Nếu bạn thực hiện điều này rất nhiều và khoảng cách giữa startDate và endDate là khá lớn, nó sẽ tốt hơn nhiều để thực hiện phép toán như đã nêu trong một trong các câu trả lời khác. Điều này được đề xuất để có được cảm giác cho các ngày lặp lại.

+0

Thay vì thực hiện một vòng lặp 'cho (int i = 0; i Alex

1

Thư viện đường cận âm có rất nhiều người trợ giúp để xử lý thao tác DateTime.

Bạn có thể tìm danh sách đầy đủ trên Subsonic site và mã nguồn nằm trong github.

10

Oh nó thực sự dễ dàng để lặp qua ngày - đó không phải là vấn đề gì cả:

// I'm assuming you want <= to give an *inclusive* end date... 
for (DateTime date = start; date <= end; date = date.AddDays(1)) 
{ 
    // Do stuff with date 
} 

Bạn có thể dễ dàng viết một IEnumerable<DateTime> quá, và sử dụng foreach.

Tôi cố gắng tránh thực hiện các thao tác chuỗi tại đây nếu có thể - về cơ bản những ngày này không phải là chuỗi, vì vậy nếu bạn có thể làm việc trong miền có vấn đề càng nhiều càng tốt.

Tất nhiên, có thể có nhiều cách hiệu quả hơn lặp lại, nhưng chúng sẽ khó khăn hơn để có được quyền. Nếu vòng lặp là ổn về hiệu suất, tôi muốn dính vào đó.

Là một plugin nhanh cho dự án nguồn mở của riêng tôi, Noda Time có tập hợp các loại ngày càng đa dạng đại diện cho ngày và giờ - trong trường hợp này bạn sẽ sử dụng LocalDate. Bằng cách đó bạn không phải lo lắng về những gì sẽ xảy ra nếu thời gian trong "bắt đầu" là muộn hơn thời gian trong "kết thúc" vv Mặt khác, Noda Thời gian là không thực sự hoàn thành được ... các bit bạn cần cho điều này đã sẵn sàng và sẽ hoạt động tốt, nhưng có thể API vẫn có thể thay đổi trong tương lai.

EDIT: Nếu bạn làm cần phải lặp qua ngày thường xuyên, bạn có thể muốn một cái gì đó giống như phương pháp này mở rộng (đặt nó trong một lớp tĩnh top-level phi generic):

public static IEnumerable<DateTime> To(this DateTime start, DateTime end) 
{ 
    Date endDate = end.Date; 
    for (DateTime date = start.Date; date <= endDate; date = date.AddDays(1)) 
    { 
     yield return date;    
    } 
} 

Sau đó:

foreach (DateTime date in start.To(end)) 
{ 
    ... 
} 
+0

Để tránh việc so sánh chuỗi để loại trừ ngày tháng, tất cả bạn cần làm là tìm số ngày bạn đang loại trừ (giả sử không có ngày cuối tuần) mà bạn có thể tìm ra với: excludeDates.split (','). Sau đó trừ số này khỏi số ngày. – macleojw

+0

Các ngày loại trừ có thể không nhất thiết phải rơi vào ngày bắt đầu và ngày kết thúc, vì vậy cần phải kiểm tra ở đây - đây là một phần của khó khăn và có nghĩa là tôi không thể thực hiện theo cách bạn đề xuất. – Dan

0

Dưới đây là mã giả cho một cách tiếp cận khác nhau mà tôi đã sử dụng trong SQL:

Find the total number of days between the two datessố Subtract của cuối tuần
Hủy bỏ một ngày nếu ngày bắt đầu là một chủ nhật
Hủy bỏ một ngày nếu ngày bắt đầu là một thứ bảy
Hủy bỏ bất kỳ những ngày khác bạn không muốn (xem nhận xét của tôi ở trên về cách làm này trong C#)

0

này có thể làm việc và tránh một O (n) gõ giải pháp:

public int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates) 
{ 

    //Work out days in range 
    int days = (int)endDate.Subtract(startDate).TotalDays + 1; 

    if (excludeWeekends) 
    { 
     //Remove most weekends by removing 2 in 7 days (rounded down) 
     days -= ((int)Math.Floor((decimal)(days/7)) * 2); 

     if (startDate.DayOfWeek == DayOfWeek.Sunday) days -= 1; 
     if (startDate.DayOfWeek == DayOfWeek.Saturday) days -= 2; 
    }     

    return days; 

} 

nó không triệt thử nghiệm mặc dù.

Để xử lý các ngày loại trừ, bạn có thể lặp qua các loại trừ và loại trừ chúng ở đâu giữa đầu và cuối (và không phải là ngày cuối tuần nếu thích hợp). Đây sẽ là một vòng lặp ngắn hơn so với trải qua tất cả các ngày giữa bắt đầu và kết thúc.

0

Kết hợp với các biểu thức LINQ,

 public int GetNoOfLeaveDays(DateTime fromDate, DateTime toDate, Boolean excludeWeekends, List<DateTime> excludeDates) 
    { 
     var count = 0; 
     for (DateTime index = fromDate; index <= toDate; index = index.AddDays(1)) 
     { 
      if (!excludeWeekends || index.DayOfWeek == DayOfWeek.Saturday || index.DayOfWeek == DayOfWeek.Sunday) continue; 
      var excluded = excludeDates.Any(t => index.Date.CompareTo(t.Date) == 0); 
      if (!excluded) count++; 
     } 
     return count; 
    } 
0
private int workingdays(int month,int year) 
{ 
    int daysInMonth = 0; 
    int days = DateTime.DaysInMonth(year, month); 
    for (int i = 1; i <= days; i++) 
    { 
     DateTime day = new DateTime(year, month, i); 
     if (day.DayOfWeek != DayOfWeek.Sunday && day.DayOfWeek != DayOfWeek.Saturday) 
     { 
      daysInMonth++; 
     } 
    } 
    return daysInMonth; 
} 
Các vấn đề liên quan