2013-02-13 182 views

回答

8

您需要使用DayOfTheWeek(來自DateUtils單位)和一個計數器,從開始日期到結束日期迭代。 (您也可能會需要假期表,以排除那些從數也。)

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; 

您可以通過不擔心參數的順序(換句話說加強這一點,它不無論開始是在結束還是在結束之前開始之前,該功能仍將工作):

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

我看到謝謝......我不需要假期,因爲他們不會大幅影響週轉時間..但週末是問題。我會給它一個鏡頭。 – Sardukar 2013-02-13 02:28:09

+0

我使用了幾乎相同的功能。有太多可能的標本,所以如果很少有假期的問題,他們不會影響整體..謝謝你。 – Sardukar 2013-02-13 04:21:39

+7

如果沒有循環,這將是很好的。 – 2013-02-13 09:10:43

12

沒有循環所有日子和輸入參數而不依賴於順序。

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。太好了!我沒有機會看到一個非循環的解決方案 - 現在我絕對不需要這樣做。 :-) – 2013-02-13 17:10:23

+4

如果我測試'dt1:= Now'和'dt2:= IncYear(Now,3)',我會得到另外兩個不同的結果。 – kobik 2013-02-13 18:43:11

+5

@kobik,謝謝。正確的日期編號功能當然是'DayOfTheWeek()'。 – 2013-02-13 19:37:24

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; 

例行BusinessDaysSinceFixedDate計算,因爲固定日期的工作日數。具體的日期不相關,是1899年12月25日星期一。 它只是計算已經過去的星期數(X div 7)並將其乘以5. 然後它添加一個偏移量以根據當天一週中的。 注意,(X 7 MOD)將返回一個負值對於負日期,即12月30日之前的日期,1899年

例程BusinessDaysBetweenDates只是調用BusinessDaysSinceFixedDate的開始和結束日期和減去一個來自其他。

+4

+1。你可以在'BusinessDaysBetweenDates'的結果中添加'Abs'(所以Days的結果總是肯定的)。 – kobik 2013-02-13 18:39:53

相關問題