Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 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 тоже не корректно работает

Приложение:
  1.  
  2. function StrBetweenDate(Date1, Date2: TDate): string;
  3. var
  4. id, im, iy: Integer;
  5. d: TDate;
  6. begin
  7. Result:= '';
  8. if Date1 < Date2 then
  9. begin
  10. d:= Date1;
  11. Date1:= Date2;
  12. Date2:= d;
  13. Date1:= Date1 + 1;
  14. end;
  15. d:= DaysBetween(Date1 + 1, Date2);
  16. id:= DayOf(d);
  17. im:= MonthOf(d)-1;
  18. iy:= YearOf(d);
  19. iy:= iy - 1900;
  20.  
  21. if im = 12 then
  22. begin
  23. im:= 0;
  24. inc(iy);
  25. end;
  26.  
  27.  
  28. if id = 31 then
  29. begin
  30. id:= 0;
  31. inc(im);
  32.  
  33. if im = 12 then
  34. begin
  35. im:= 0;
  36. inc(iy);
  37. end;
  38. end;
  39. Result:= (IntToStr(iy)+ StrYears(iy) + IntToStr(im) +
  40. StrMonths(im) + IntToStr(id)+ StrDays(id));
  41. end;
  42.  
  43. procedure TForm1.Button1Click(Sender: TObject);
  44. var
  45. aDate, date1: TDateTime;
  46.  
  47. begin
  48. aDate := DateTimePicker1.Date;
  49. date1 := DateTimePicker2.Date;
  50.  
  51. label5.Caption := StrBetweenDate(aDate, date1);
  52.  
  53.  
  54. var
  55. aDate, date1,dtDiff: TDateTime;
  56. dd, mm, yy, days: Word;
  57. str: string;
  58. begin
  59. aDate := DateTimePicker1.Date;
  60. date1 := DateTimePicker2.Date;
  61.  
  62. days := DayOfTheYear(aDate) - 1;
  63. DecodeDate((date1 - Days), yy, mm, dd);
  64. yy := yy - YearOf(aDate);
  65. str := Format('Year: %d', [yy]) + #13#10 +
  66. Format('Month: %d', [mm]) + #13#10 +
  67. Format('Day: %d', [dd]);
  68. ShowMessage(str);


casio Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: 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 // вычитаем один месяц
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

DNK (статус: Студент), 12 февраля 2017, 19:29 [#1]:

Тут надо сначала декодировать обе даты и потом отдельно вычитать сначала года, потом месяцы и потом дни. Если при вычитании месяцев или дней получается отрицательное число, занять 1 у предыдущей части результата.
"Digital Networked Knight"
casio

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
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

DNK (статус: Студент), 12 февраля 2017, 23:12 [#3]:

If d1 Full_Months:=Full_Months-1;

Вот до этих строчек всё четко. Дальше хрень полная. Я бы сделал примерно так:

// если дни в конечной дате меньше чем в начальной
If d1 // вычитаем один месяц
Full_Months:=Full_Months-1;
// из количества дней в предпоследнем месяце вычитаем дни начальной даты и прибавляем дни конечной
Days := MonthDays(m1 - 1, y1) - d2 + d1;
end else
// иначе просто находим разницу в днях
Days := d1 - d2;
"Digital Networked Knight"
casio

casio (статус: Посетитель), 12 февраля 2017, 23:30 [#4]:

DNK:
Days := MonthDays(m1 - 1, y1) - d2 + d1;
выбивает в этой строке ошибку
DNK

DNK (статус: Студент), 12 февраля 2017, 23:36 [#5]:

И догадываюсь какую... Функцию нахождения количества дней в месяце сам реализовывать способен?
"Digital Networked Knight"
casio

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

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

DNK (статус: Студент), 13 февраля 2017, 00:46 [#8]:

следуя этой логике: с 1.02.17 по 1.02.17 должно быть 1 день?
хочешь странного...
"Digital Networked Knight"
casio

casio (статус: Посетитель), 14 февраля 2017, 10:48 [#9]:

DNK: Как не странно но так и есть, в рабочий стаж зачитывается день увольнения, праздничные,выходные.
вот пример с онлайн калькулятора http://savepic.ru/12962179.jpg
DNK

DNK (статус: Студент), 14 февраля 2017, 20:57 [#10]:

Очевидно же, к дням надо единичку прибавить
"Digital Networked Knight"
casio

casio (статус: Посетитель), 19 февраля 2017, 16:19 [#11]:

DNK: спасибо,вроде получилось!

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 20 ноября 2018, 09:12
Выполнено за 0.05 сек.
Рейтинг@Mail.ru