2013-02-13 59 views
11

Tôi cần tính toán số ngày làm việc (ngày làm việc) giữa hai ngày nhất định. Ngày làm việc là tất cả các ngày trong tuần trừ thứ Bảy và Chủ Nhật. Tôi không xem xét ngày lễ vào số này.Cách tính số ngày làm việc giữa hai ngày?

Cách tính số ngày làm việc giữa hai ngày?

Trả lời

8

Bạn cần sử dụng DayOfTheWeek (từ đơn vị DateUtils) và bộ đếm, lặp lại từ ngày bắt đầu đến ngày kết thúc. (Bạn cũng sẽ có lẽ cần một bảng các ngày lễ, để loại trừ những từ đếm của bạn cũng.)

function BusinessDaysBetween(const StartDate, EndDate: TDateTime): Integer; 
var 
    CurrDate : TDateTime; 
begin 
    CurrDate := StartDate; 
    Result := 0; 
    while (CurrDate <= EndDate) do 
    begin 
    // DayOfTheWeek returns 1-5 for Mon-Fri, so 6 and 7 are weekends 
    if DayOfTheWeek(CurrDate) < 6 then 
     Inc(Result); 
    CurrDate := CurrDate + 1; 
    end; 
end; 

Bạn có thể nâng cao này một chút bằng cách không lo lắng về thứ tự của các thông số (hay nói cách khác, nó doesn không quan trọng nếu bắt đầu trước khi kết thúc hoặc kết thúc là trước khi bắt đầu, chức năng sẽ vẫn hoạt động):

function BusinessDaysBetween(const FirstDate, SecondDate: TDateTime): Integer; 
var 
    CurrDate : TDateTime; 
    StartDate, EndDate: TDateTime; 
begin 
    if SecondDate > FirstDate then 
    begin 
    StartDate := FirstDate; 
    EndDate := SecondDate; 
    end 
    else 
    begin 
    StartDate := SecondDate; 
    EndDate := FirstDate; 
    end; 

    CurrDate := StartDate; 
    Result := 0; 

    while (CurrDate <= EndDate) do 
    begin 
    if DayOfTheWeek(CurrDate) < 6 then 
     Inc(Result); 
    CurrDate := CurrDate + 1; 
    end; 
end; 
+0

Tôi thấy cảm ơn ... Tôi không cần ngày nghỉ vì chúng sẽ không ảnh hưởng đến thời gian quay vòng đáng kể ... nhưng cuối tuần là vấn đề. Tôi sẽ cho nó một shot. – Sardukar

+0

Tôi đã sử dụng gần như cùng một chức năng..hoạt động tuyệt vời. có cách quá có thể mẫu vì vậy nếu ít có vấn đề với ngày lễ họ sẽ không ảnh hưởng đến tổng thể .. cảm ơn bạn. – Sardukar

+7

Sẽ tốt hơn nếu làm điều này mà không cần lặp lại. –

12

Không lặp lại tất cả các ngày và tham số đầu vào không phụ thuộc vào thứ tự.

Uses DateUtils,Math; 

function WorkingDaysBetween(const firstDate,secondDate : TDateTime) : Integer; 
var 
    startDate,stopDate : TDateTime; 
    startDow,stopDow : Integer; 
begin 
    if (firstDate < secondDate) then 
    begin 
    startDate := firstDate; 
    stopDate := secondDate; 
    end 
    else 
    begin 
    startDate := secondDate; 
    stopDate := firstDate; 
    end; 
    startDow := DayOfTheWeek(startDate); 
    stopDow := DayOfTheWeek(stopDate); 
    if (stopDow >= startDow) then 
    stopDow := Min(stopDow,6) 
    else 
    Inc(stopDow,5); 

    Result := 
    5*WeeksBetween(stopDate,startDate) + 
    (stopDow - Min(startDow,6)); 
end; 
+3

+1. Tốt đẹp! Tôi không có cơ hội để xem xét một giải pháp không lặp lại - bây giờ tôi chắc chắn không cần phải làm như vậy. :-) –

+4

Tôi nhận được các kết quả khác nhau từ hai hàm còn lại, với hàm của bạn, nếu tôi kiểm tra 'dt1: = Now' và' dt2: = IncYear (Now, 3) '. – kobik

+5

@kobik, cảm ơn. Hàm đánh số ngày đúng là tất nhiên 'DayOfTheWeek()'. –

13
function BusinessDaysSinceFixedDate (const nDate : tDateTime) : integer; 
const 
    Map : array [ -6 .. 6 ] of integer 
     = ( 0, 0, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9); 
var 
    X : integer; 
begin 
    X := trunc (nDate); 
    Result := 5 * (X div 7) + Map [ X mod 7 ]; 
end; 

function BusinessDaysBetweenDates (const nStartDate : tDateTime; 
            const nEndDate : tDateTime) : integer; 
begin 
    Result := BusinessDaysSinceFixedDate (nEndDate) 
      - BusinessDaysSinceFixedDate (nStartDate); 
end; 

Các BusinessDaysSinceFixedDate thói quen tính toán số ngày làm việc kể từ khi một ngày cố định. Ngày cụ thể, không liên quan, là Thứ Hai, 25 Tháng Mười Hai, 1899. Đơn giản chỉ đếm số tuần đã trôi qua (X div 7) và nhân số đó với 5. Sau đó, nó sẽ thêm một khoản bù vào đúng dựa vào ngày trong tuần. Lưu ý rằng (X mod 7) sẽ trả lại giá trị âm cho một ngày phủ định, nghĩa là ngày trước ngày 30 tháng 12 năm 1899.

BusinessDaysBetweenDates chỉ đơn giản gọi BusinessDaysSinceFixedNgày cho ngày bắt đầu và ngày kết thúc và trừ một từ ngày khác.

+4

+1. Bạn có thể thêm 'Abs' vào kết quả của' BusinessDaysBetweenDates' (do đó kết quả của Days sẽ luôn dương). – kobik

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