Нестандартные функции работы с датой/временем
Задача первая:
Что, получиться если мы вычтем одну дату из другой? Правильный ответ на этот вопрос, будет период работы, а что нам скажет Delphi?
23.01.07- 21.11.06= 03.03.1900 круто, да … и кто же из нас не прав, черт побери. Общепризнанной практикой исчисления стажа является, примерно такой алгоритм.
23.01.07 -
21.11.06
-------------
2
Итого 2 месяца 2 дня. Два месяца получились при переброске года в месяцы (12 месяцев). Вот этот алгоритм и требуется описать. Сразу сойдемся на мнении, что в году у нас 360 дней (12 месяцев по 30 дней), это, по-моему, еще из Excel вылезло. Алгоритм очень простой мы расщепляем дату на дни месяцы и годы, и производим, то, что выше указанно, а ответ мы вернем в виде строки.
function Period(BeginDate, EndDate: Tdatetime): string;
var
SubDate:Tdatetime;
md,mm,my:integer;
begin
SubDate:=EndDate-BeginDate;
md:=dayof(EndDate)-dayof(begindate);
mm:=monthof(EndDate)-monthof(begindate);
my:=yearof(EndDate)-yearof(begindate);
if md<0 then begin
md:=md+30;
mm:=mm-1;
end;
if mm<0 then begin
my:=my-1;
mm:=mm+12;
end;
Period:=inttostr(md)+'.'+inttostr(mm)+'.'+inttostr(my);
end;
Вот таким образом вы считаем период работы.
Задача вторая:
Что же дальше? Период мы почитали, а теперь надо сложить периоды, что бы не шокировать себя, складывать TDateTime'ы мы не станем. А сразу напишем функцию, которая сложит нам две даты, полученные в прошлой задачке.
function SummaPeriod(BeginDate, EndDate: string): string;
var
bd,bm,by:integer;
ed,em,ey:integer;
sd,sm,sy:integer;
begin
randomize;
bd:=dayof(strtodate(BeginDate));
bm:=monthof(strtodate(BeginDate));
by:=yearof(strtodate(BeginDate))-2000;
ed:=dayof(strtodate(EndDate));
em:=monthof(strtodate(EndDate));
ey:=yearof(strtodate(EndDate))-2000;
sd:=bd+ed;
sm:=bm+em;
sy:=by+ey;
if sd>=30 then
begin
sd:=sd-30;
sm:=sm+1;
end;
if sm>=12 then
begin
sm:=sm-12;
sy:=sy+1;
end;
SummaPeriod:=inttostr(sd)+'.'+inttostr(sm)+'.'+inttostr(sy);
end;
Сразу предвижу ваш вопрос, а что это за хрень? by:=yearof(strtodate(BeginDate))-2000; Вы можете разложить строку и получить то, же самое.
Задача третья:
Имеется период работы, описанный двумя переменными типа TdateTime (начало периода и конец периода) требуется определить входит некоторая дата в этот интервал. Сложность заключается, прежде всего, в том, что невозможно описать тип TdateTime без указания года. Как, например, в случае 23 февраля, 8 марта, новый год (самый веселый праздник). Для описания веселых "Красных дней календаря" будем использовать тип String. Функция, которая определяет вхождение даты в заданный диапазон, получилась примерно такой:
function Holydays(BeginDate, EndDate: Tdatetime;holyday: string): integer;
var
output:integer;
md:string;
begin
md:=holyday+'.'+inttostr(yearof(EndDate));
if (CompareDateTime(strtodate(md), EndDate)<=0) and
(CompareDateTime(BeginDate,strtodate(md))<=0)then
begin
output:=1;
end else output:=0;
if output=0 then
begin
md:=holyday+'.'+inttostr(yearof(BeginDate));
if (CompareDateTime(strtodate(md), EndDate)<=0) and
(CompareDateTime(BeginDate,strtodate(md))<=0)then
begin
output:=1;
end else output:=0;
end;
Holydays:=output;
end;
Если в результате выполнения получается "1", то дата в заданный диапазон входит, в противном случае нет.
Рассмотрим алгоритм действий данной функции поподробнее. BeginDate - начало периода, EndDate - окончание периода, holyday - собственно праздник (в формате "23.02") md:=holyday+'.'+inttostr(yearof(EndDate)); - приводим дату праздника в соответствие с типом TDateTime значение года берется из окончания периода (для случая, когда начало периода, было в одном году, а окончание уже в другом). После чего проводим проверку на вхождение в заданный диапазон:
if (CompareDateTime(strtodate(md), EndDate)<=0) and
(CompareDateTime(BeginDate,strtodate(md))<=0)then
begin
output:=1;
end else output:=0;
Но, не все так гладко как может показаться, в случае с входными данными вида начало периода- 27.11.06, окончание периода - 10.01.07, праздник 29.11 (маловероятно звучит, но у нас и такие чудеса бывают), а посему мы приводим дату в соответствие md:=holyday+'.'+inttostr(yearof(BeginDate)); и работает! Вот такая полезная статистическая функция получилась. Теперь можно создавать базу данных русских праздников и вычитать их из отпуска сотрудника. -- С уважением, Антон mailto:AntonCH82@mail.ru
Обсудить на форуме