求一个难度比较高的关于时间计算的函数,给250分。(250分)

  • 主题发起人 主题发起人 boyuanus
  • 开始时间 开始时间
B

boyuanus

Unregistered / Unconfirmed
GUEST, unregistred user!
函数的目的是为了得到两个Datetime值之间的实际的工作小时数。

函数要求是这样的:
1. 四个参数,分别是WorkhourStart(TTime), WorkhourEnd(TTime), StartAt(TDateTime), EndAt(TDateTime).
各自的含义如下:
WorkhourStart, WorkhourEnd:分别表示上下班时间,例如:WorkhourStart 是上午9:00, WorkhourEnd是下午5:00。
StartAt,EndAt:开始时间和结束时间。
2. 输出:要求是按照小时计算(包括小数)。要求得到StartAt和EndAt之间的工作小时数。

如果分数不够,还可以再加。
思路越清晰越好。

多谢!
 
var
DifTime: TDateTime;
Hour, Min, Sec, MSec: Word;
begin
DifTime := EndAt - StartAt;
DecodeTime(DifTime, Hour, Min, Sec, MSec);

Result := Hour + Min/60 + Sec/3600 + MSec/(3600*1000);
end;
 
(EndDateTime - BeginDateTime) * 24
 
uses DateUtils;

1.计算StartAt(TDateTime)到EndAt(TDateTime)的时间(小时),精度到分(我想够了)
MinutesBetween(StartAt, EndAt)/60;
2.计算StartAt(TDateTime)到EndAt(TDateTime)的工作日
3.计算StartAt(TDateTime)到EndAt(TDateTime)的休息时间
4.这样就可以得到StartAt和EndAt之间的工作小时数了.

DateUtils单元中有很多的计算时间的函数可以用
具体计算中还要加很多的判断.
 
上面两位没有看清楚问题。
:)
 
我的理解对吗
 
我不明白的是,WorkhourStart(TTime), WorkhourEnd(TTime), 这二个参数有什么作用?
 
我理解是StartAt和EndAt可能会相隔多天.而工作时间只有在WorkhourStart(TTime), WorkhourEnd(TTime)之间 也就是说上班时间有效.
楼主:我的理解对吗
 
to yostgxf:
你好厉害啊!
 
老兄,你挖苦我呀,还没得到楼主的肯定呢 哈哈...
学习,学习
 
思路:
1. 计算整数天(每过 24 小时就有一个整数天)
2. 计算余数
3. 1 + 2 即为所求。

代码:
function HoursBetween(WorkhourStart, WorkhourEnd: TTime
StartAt, EndAt: TDateTime): Double;

// 指定时间的不足一天部分
function HoursOfTime(d: Double): Double;
begin
Result := d - Trunc(d);
end;

const
HOURS_OF_DAY = 24;

var
dHoursOfDay, dDaysInt, dDaysRemain: Double
// 每天工作时间,工作的整数天,不足一天的小时数

begin
// 确保 WorkHourStart, WorkHourEnd 及 StartAt, EndAt 大小顺序
// ...

/////////////////////////////////////////////////////////////
// 整数天小时数
dHoursOfDay := WorkHourEnd - WorkHourStart;
dDaysInt := Trunc(EndAt - StartAt);

StartAt := HoursOfTime(StartAt);
EndAt := HoursOfTime(EndAt);

/////////////////////////////////////////////////////////////
// 余数: 一天内
if StartAt < EndAt then
begin
if StartAt < WorkHourStart then // 提前上班,不算加班?
StartAt := WorkHourStart
else if StartAt > WorkHourEnd then // 下班后才上班, 白上
StartAt := WorkHourEnd;

if EndAt < WorkHourStart then // 上班前就下班,白上
EndAt := WorkHourStart
else if EndAt > WorkHourEnd then // 推迟下班,不算加班?
EndAt := WorkHourEnd;

dDaysRemain := EndAt - StartAt;
end
// 余数: 跨天
else if StartAt > EndAt then
begin
// 注:以下 StartAt 和 EndAt 作为了临时变量,分别保存前、后半天的工作时间

// 前半天
if StartAt < WorkHourStart then // 提前上班,一整天
StartAt := dHoursOfDay
else if StartAt < WorkHourEnd then // 迟到
StartAt := WorkHourEnd - StartAt
else if StartAt > WorkHourEnd then // 下班时间后上班,白上
StartAt := 0.0;

// 后半天
if EndAt < WorkHourStart then // 上班时间后下班,白上
EndAt := 0.0
else if EndAt < WorkHourEnd then // 早退
EndAt := EndAt - WorkHourStart
else if EndAt > WorkHourEnd then // 延后下班,一整天
EndAt := dHoursOfDay;

dDaysRemain := StartAt + EndAt;
end
// 余数: 重合
else
begin
dDaysRemain := 0.0;
end;

/////////////////////////////////////////////////////////////
// 结果
Result := (dHoursOfDay * dDaysInt + dDaysRemain) * HOURS_OF_DAY;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
WorkhourStart, WorkhourEnd: TTime;
StartAt, EndAt: TDateTime;
begin
WorkhourStart := StrToTime('9:00');
WorkhourEnd := StrToTime('17:00');
StartAt := StrToDateTime('2004-3-1 20:00');
EndAt := StrToDateTime('2004-3-3 5:00');

ShowMessage(Format('%f', [HoursBetween(WorkhourStart, WorkhourEnd, StartAt, EndAt)]));
end;

后记:
这是第三次贴的代码了,希望不会再错 :(
 
楼主,问题一点都不难,只是要看实际情况处理,像yostgxf说的跨天的,说实在,在我公司已经是旷工了,[:D]只能算打卡的时间的半天,所以,我只是给出大概思路,就按你说的思路!我看倒要具体的源码。[8D]
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
916
SUNSTONE的Delphi笔记
S
后退
顶部