|
Вопрос # 6 648/ вопрос открыт / |
|
Доброго времени суток, уважаемые эксперты!
Подскажите кто знает, нужно выводить к-во отработанных лет,месяцев,дней (другими словами высчитать стаж). Сделал так, ниже код, но проблема с февралем, нужно трактовать занятый месяц: 1 месяц = 28, 29, 30, 31 дней? Вдобавок, дело осложняется с высокосностью годов.
Если поставить с 01.02 по 28.02 должно получится 0 лет 1 месяц 0 дней (получается 0 лет 0 месяцев 28 дней), а с 01.02 по 01.03 0лет 1 месяц 1 день (получается 0 лет 0 месяцев 29 дней), 2й вариант с DecodeDate тоже не корректно работает
Приложение: Переключить в обычный режим-
- function StrBetweenDate(Date1, Date2: TDate): string;
- var
- id, im, iy: Integer;
- d: TDate;
- begin
- Result:= '';
- if Date1 < Date2 then
- begin
- d:= Date1;
- Date1:= Date2;
- Date2:= d;
- Date1:= Date1 + 1;
- end;
- d:= DaysBetween(Date1 + 1, Date2);
- id:= DayOf(d);
- im:= MonthOf(d)-1;
- iy:= YearOf(d);
- iy:= iy - 1900;
-
- if im = 12 then
- begin
- im:= 0;
- inc(iy);
- end;
-
-
- if id = 31 then
- begin
- id:= 0;
- inc(im);
-
- if im = 12 then
- begin
- im:= 0;
- inc(iy);
- end;
- end;
- Result:= (IntToStr(iy)+ StrYears(iy) + IntToStr(im) +
- StrMonths(im) + IntToStr(id)+ StrDays(id));
- end;
-
- procedure TForm1.Button1Click(Sender: TObject);
- var
- aDate, date1: TDateTime;
-
- begin
- aDate := DateTimePicker1.Date;
- date1 := DateTimePicker2.Date;
-
- label5.Caption := StrBetweenDate(aDate, date1);
-
-
- var
- aDate, date1,dtDiff: TDateTime;
- dd, mm, yy, days: Word;
- str: string;
- begin
- aDate := DateTimePicker1.Date;
- date1 := DateTimePicker2.Date;
-
- days := DayOfTheYear(aDate) - 1;
- DecodeDate((date1 - Days), yy, mm, dd);
- yy := yy - YearOf(aDate);
- str := Format('Year: %d', [yy]) + #13#10 +
- Format('Month: %d', [mm]) + #13#10 +
- Format('Day: %d', [dd]);
- ShowMessage(str);
|
Вопрос задал: casio (статус: Посетитель)
Вопрос отправлен: 12 февраля 2017, 16:23
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: DNK
Здравствуйте, casio!
function TForm1.DaysOfMonth( mm, yy: integer ): integer;
begin
if mm = 2 then
begin
Result := 28;
if IsLeapYear( yy ) then Result := 29;
end
else
begin
if mm < 8 then
begin
if ( mm mod 2 ) = 0 then
Result := 30
else
Result := 31;
end
else
begin
if ( mm mod 2 ) = 0 then
Result := 31
else
Result := 30;
end;
end;
end;
function TForm1.StrBetweenDate(Date1, Date2: TDate): string;
var
to_date, from_date: TDateTime;
y1, y2, m1, m2, d1, d2, Full_Months, Days: Integer;
begin
to_date:=DateTimePicker1.DateTime;
from_date:=DateTimePicker2.DateTime;
DecodeDate(from_date,y1,m1,d1);
DecodeDate(to_date,y2,m2,d2);
Full_Months:=(y1-y2)*12+(m1-m2);
// если дни в конечной дате меньше чем в начальной
If d1<d2 then begin
// вычитаем один месяц
Full_Months:=Full_Months-1;
// из количества дней в предпоследнем месяце вычитаем дни начальной даты и прибавляем дни конечной
Days := MonthDays(m1 - 1, y1) - d2 + d1;
end else
// иначе просто находим разницу в днях
Days := d1 - d2;
Inc(Days);
Result := Format('Month: %d'#13#10'Day: %d', [Full_Months, Days]);
end;
|
Ответ отправил: DNK (статус: Студент)
Время отправки: 20 февраля 2017, 21:06
|
Мини-форум вопроса
Всего сообщений: 11; последнее сообщение — 19 февраля 2017, 16:19; участников в обсуждении: 2.
|
DNK (статус: Студент), 12 февраля 2017, 19:29 [#1]:
Тут надо сначала декодировать обе даты и потом отдельно вычитать сначала года, потом месяцы и потом дни. Если при вычитании месяцев или дней получается отрицательное число, занять 1 у предыдущей части результата.
"Digital Networked Knight"
|
|
casio (статус: Посетитель), 12 февраля 2017, 22:36 [#2]:
DNK: спасибо, разобрался, считает верно, подскажите как сделать для моего варианта что бы было в первом варианте 28 дней/29 дней, а во втором 1месяц 1день
1) с 01.02.17 по 28.08.17 - отображает 27 дней
2) с 01.02.17 по 01.03.17 показывает 1 месяц,
to_date:=DateTimePicker1.DateTime;
from_date:=DateTimePicker2.DateTime;
DecodeDate(from_date,y1,m1,d1);
DecodeDate(to_date,y2,m2,d2);
Full_Months:=(y1-y2)*12+(m1-m2);
If d1<d2 then
Full_Months:=Full_Months-1;
Days:=Round(from_date-to_date);
For i:=1 to Full_Months do
begin
DayTable:=MonthDays[IsLeapYear(y2)];
k:=DayTable[m2];
Days:=Days-k;
m2:=m2+1;
If m2>12 then
begin
y2:=y2+1;
m2:=1;
end;
end;
|
|
DNK (статус: Студент), 12 февраля 2017, 23:12 [#3]:
If d1<d2 then
Full_Months:=Full_Months-1;
Вот до этих строчек всё четко. Дальше хрень полная. Я бы сделал примерно так:
// если дни в конечной дате меньше чем в начальной
If d1<d2 then begin
// вычитаем один месяц
Full_Months:=Full_Months-1;
// из количества дней в предпоследнем месяце вычитаем дни начальной даты и прибавляем дни конечной
Days := MonthDays(m1 - 1, y1) - d2 + d1;
end else
// иначе просто находим разницу в днях
Days := d1 - d2;
"Digital Networked Knight"
|
|
casio (статус: Посетитель), 12 февраля 2017, 23:30 [#4]:
DNK: Days := MonthDays(m1 - 1, y1) - d2 + d1; выбивает в этой строке ошибку
|
|
DNK (статус: Студент), 12 февраля 2017, 23:36 [#5]:
И догадываюсь какую... Функцию нахождения количества дней в месяце сам реализовывать способен?
"Digital Networked Knight"
|
|
casio (статус: Посетитель), 12 февраля 2017, 23:45 [#6]:
DNK:
вроде этого?
function TForm1.DaysOfMonth( mm, yy: integer ): integer;
begin
if mm = 2 then
begin
Result := 28;
if IsLeapYear( yy ) then Result := 29;
end
else
begin
if mm < 8 then
begin
if ( mm mod 2 ) = 0 then
Result := 30
else
Result := 31;
end
else
begin
if ( mm mod 2 ) = 0 then
Result := 31
else
Result := 30;
end;
end;
end;
|
|
casio (статус: Посетитель), 12 февраля 2017, 23:56 [#7]:
DNK: согласно вашему коду сократилось на 11 стр кода, спасибо))) но не получилось все равно реализовать задуманное,
1) с 01.02.17 по 28.08.17 - отображает 27 дней (должно быть 28 дней)
2) с 01.02.17 по 01.03.17 показывает 1 месяц(должно быть 1месяц 1 день)
|
|
DNK (статус: Студент), 13 февраля 2017, 00:46 [#8]:
следуя этой логике: с 1.02.17 по 1.02.17 должно быть 1 день?
хочешь странного...
"Digital Networked Knight"
|
|
casio (статус: Посетитель), 14 февраля 2017, 10:48 [#9]:
DNK: Как не странно но так и есть, в рабочий стаж зачитывается день увольнения, праздничные,выходные.
вот пример с онлайн калькулятора http://savepic.ru/12962179.jpg
|
|
DNK (статус: Студент), 14 февраля 2017, 20:57 [#10]:
Очевидно же, к дням надо единичку прибавить
"Digital Networked Knight"
|
|
casio (статус: Посетитель), 19 февраля 2017, 16:19 [#11]:
DNK: спасибо,вроде получилось!
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|