还是请教日期算法,qqjm请进 ( 积分: 300 )

  • 主题发起人 主题发起人 johnkan
  • 开始时间 开始时间
J

johnkan

Unregistered / Unconfirmed
GUEST, unregistred user!
TO:qqjm
先谢谢你上冷给我的算法,已经解决问题了,但是请问这组算法,如果一个星期只休息上一天夜班的话,到第四天后为休息日就出错了,结果显示为第五天,虽然问题已解决,做出于好奇,想问一下如何修改到,一天,两天,甚至连续七夜班都没有问题。

附上次的代码,如果谁能解决,都能解答,这个问题就谢谢大家帮忙了

来自:qqjm, 时间:2007-5-21 18:53:22, ID:3719821
用这个代码可以动态设置上班的时间。如星期一,四,或二,五,六。


var
d:TdateTime;
i,lsLeng,lsIdx,i1:integer;
ls:array of integer;
begin

//初始化日期。
d:= now();
i1:= 12 ;//班次


//加载上班时间列表(必需是已经按从小到大排好序的),星期天为1,周6为7
setLength(ls,3);
ls[0]:=2;
ls[1]:=4;
ls[2]:=6;
lsLeng:= Length(ls);
for i:=0 to lsLeng do
begin
if i= lsLeng then
begin
ShowMessage('日期错误:输入的日期非晚班时间,无法计算出休息日期!');
exit;
end;
if DayOfWeek(d)= ls then
begin
lsIdx:= i;//记录位置
break;
end;
end;


lsIdx:= (lsIdx+lsLeng-1) mod lsLeng;



//25天的来由(7*(12/3)-3),因为5-21号是星期一,最后那个晚班,与下次的首个晚班有3天的间隔所以7*4周-3天=25天。
//但是如果是从周三开始计的话就不同了应该是+26!

if ls[lsIdx mod lsLeng] > ls[(lsIdx +1) mod lsLeng] then //因为周是循环的不是简单的周6-周4=2这么简单,所以写成这样,没办法。
d:= d+ 7*(i1 div lsLeng) - (7 + ls[(lsIdx+1) mod lsLeng ]-ls[lsIdx mod lsLeng] )
else
d:=d+ 7*(i1 div lsLeng) -( ls[(lsIdx+1) mod lsLeng]-ls[lsIdx mod lsLeng]);



//这里解决半周问题
if(i1 mod lsLeng)>0 then //如果存在半周的问题的,那只能一个一个把各班的时间间隔加上去。
begin

for i:=lsIdx to lsIdx + (i1 mod lsLeng)-1 do/
begin
if ls[i mod lsLeng] > ls[(i +1) mod lsLeng] then
d:= d+ (7 + ls[(i+1) mod lsLeng ]-ls[i mod lsLeng] )
else
d:=d+ ls[(i+1) mod lsLeng]-ls[i mod lsLeng];
end;

end;



Showmessage('下个休息日:'+ DateToStr(d));

end;
 
简单点就是说,一个星期七天,任意天数不重复编排。
 
没有人肯帮忙吗?
 
幫你頂啊
 
问题已解决,但还希望还能多些完美的方法,继续等最好的算法
只要判断多一次lsIdx就可以了
 
可以設置班制啊!由班制和各個上下班時間得出班次,再根據班制設置每個人的應上的班。由每個人應該上的班知道此人的上下班時間、是否休息等信息,節假日可以單獨處理
 
主题问题再列出来看看,应该容易得出最优算法的。
 
不是说的很明白吗?
这是一个夜班值班的计算程序,如人员A,每个星期二、三晚上值班,然后在四个星期的最后一个晚班(每8个晚上)定为休息日期,也是就2*4=8。
我要写个程序,无论一个星期值多少天班,第四个星期的最后一天晚班为休息时间。
例如员工B每个星期一晚班,那4*1=4,第四个星期一就是休息时间
例如员工B每个星期二四六晚班,那4*3=12,第四个星期六就是休息时间
现在就是这样做,顺便也把每个晚班时间也打印出来
 
呵呵,只是一个判断的问题
if ls[lsIdx mod lsLeng] > ls[(lsIdx +1) mod lsLeng] then
改为if ls[lsIdx mod lsLeng] >= ls[(lsIdx +1) mod lsLeng] then
就可以计算一个星期只休息上一天夜班的时间了,因为当时没有考虑到一周上一天班的况,就没有使用>=。

///////////////////////////
var
d: TdateTime;
i , lsLeng //上班列表长度
, i1 //班次数
, iFirst //首班在上班列表中的位置
, iLast //尾班在上班列表中的位置
: integer;
ls: array of integer;
begin

//初始化日期。
d := now();
i1 := 12; //班次


//加载上班时间列表(必需是已经按从小到大排好序的),星期天为1,周6为7
setLength(ls, 3);
ls[0] := 2;
ls[1] := 4;
ls[2] := 6;

lsLeng := Length(ls);

for i := 0 to lsLeng do
begin
if i = lsLeng then
begin
ShowMessage('日期错误:输入的日期非晚班时间,无法计算出休息日期!');
exit;
end;
if DayOfWeek(d) = ls then
begin
iFirst := i; //记录位置
break;
end;
end;


iLast := (iFirst + lsLeng - 1) mod lsLeng;


//25天的来由(7*(12/3)-3),因为5-21号是星期一,最后那个晚班,与下次的首个晚班有3天的间隔所以7*4周-3天=25天。
//但是如果是从周三开始计的话就不同了应该是+26!
if ls[iLast] >= ls[iFirst] then
d := d + 7 * (i1 div lsLeng) - (7 + ls[iFirst] - ls[iLast])
else
d := d + 7 * (i1 div lsLeng) - (ls[iFirst] - ls[iLast]);



//这里解决半周问题
if (i1 mod lsLeng) > 0 then //如果存在半周的问题的,那只能一个一个把各班的时间间隔加上去。
begin

for i := iLast to iLast + (i1 mod lsLeng) - 1 do
begin
if ls[i mod lsLeng] > ls[(i + 1) mod lsLeng] then
d := d + (7 + ls[(i + 1) mod lsLeng] - ls[i mod lsLeng])
else
d := d + ls[(i + 1) mod lsLeng] - ls[i mod lsLeng];
end;

end;


Showmessage('下个休息日:' + DateToStr(d));

end;
 
接受答案了.
 
后退
顶部