2013-02-13 179 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

相关问题