binho
asked on
# of months between 2 dates
How can I get the number of months between 2 dates?
For example: 01-jan-2000 and 02-feb-2000. I can have the # of days (Date2 - Date1). I can even "get" the # of months dividing it by 30, but it's not an EXACT calculation...
Any idea?
For example: 01-jan-2000 and 02-feb-2000. I can have the # of days (Date2 - Date1). I can even "get" the # of months dividing it by 30, but it's not an EXACT calculation...
Any idea?
I think this is better and 100% accurate:
procedure TForm1.Button1Click(Sender : TObject);
var Date1, Date2: TDateTime;
y1, y2, m1, m2, d1, d2: Word;
begin
Date1 := Round(MonthCalendar1.Date) ;
Date2 := Round(MonthCalendar2.Date) ;
DecodeDate(Date1, y1 , m1, d1);
DecodeDate(Date2, y2 , m2, d2);
Label1.Caption := IntToStr(m2 - m1) + ' months between the two dates';
Label2.Caption := FloatToStr((Date2 - Date1))
+ ' days between the two dates';
end;
procedure TForm1.Button1Click(Sender
var Date1, Date2: TDateTime;
y1, y2, m1, m2, d1, d2: Word;
begin
Date1 := Round(MonthCalendar1.Date)
Date2 := Round(MonthCalendar2.Date)
DecodeDate(Date1, y1 , m1, d1);
DecodeDate(Date2, y2 , m2, d2);
Label1.Caption := IntToStr(m2 - m1) + ' months between the two dates';
Label2.Caption := FloatToStr((Date2 - Date1))
+ ' days between the two dates';
end;
ASKER
Epsylon:
I don't think this works. If I take 31-jan-2000 as Date1 and 01-feb-2000 as Date2, the code you wrote returns 1 months, but it's wrong!...
And if I take 01-jan-2000 and 15-jan-2001, it returns 0 months, but it should be 12...
Jeurk:
If I have a 29 day february, I have a problem with your code...
I don't think this works. If I take 31-jan-2000 as Date1 and 01-feb-2000 as Date2, the code you wrote returns 1 months, but it's wrong!...
And if I take 01-jan-2000 and 15-jan-2001, it returns 0 months, but it should be 12...
Jeurk:
If I have a 29 day february, I have a problem with your code...
Why ? the fact is handled with :
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special } No ?
Still a problem ?
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special } No ?
Still a problem ?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Epsylon worked out fine...
I hope you're right :o)
I did some testing but not excessively.
Cheers.
I did some testing but not excessively.
Cheers.
function DaysPerMonth(AYear, AMonth: Integer): Integer;
const
DaysInMonth: array[1..12] of Integer =
(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
Result := DaysInMonth[AMonth];
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special }
end;
procedure DateDiff(Date1, Date2: TDateTime; var Days, Months, Years: Word);
{ Corrected by Anatoly A. Sanko (2:450/73) }
var
DtSwap: TDateTime;
Day1, Day2, Month1, Month2, Year1, Year2: Word;
begin
if Date1 > Date2 then begin
DtSwap := Date1;
Date1 := Date2;
Date2 := DtSwap;
end;
DecodeDate(Date1, Year1, Month1, Day1);
DecodeDate(Date2, Year2, Month2, Day2);
Years := Year2 - Year1;
Months := 0;
Days := 0;
if Month2 < Month1 then begin
Inc(Months, 12);
Dec(Years);
end;
Inc(Months, Month2 - Month1);
if Day2 < Day1 then begin
Inc(Days, DaysPerMonth(Year1, Month1));
if Months = 0 then begin
Dec(Years);
Months := 11;
end
else Dec(Months);
end;
Inc(Days, Day2 - Day1);
end;
function MonthsBetween(Date1, Date2: TDateTime): Double;
var
D, M, Y: Word;
begin
DateDiff(Date1, Date2, D, M, Y);
Result := 12 * Y + M;
if (D > 1) and (D < 7) then Result := Result + 0.25
else if (D >= 7) and (D < 15) then Result := Result + 0.5
else if (D >= 15) and (D < 21) then Result := Result + 0.75
else if (D >= 21) then Result := Result + 1;
end;
this should be it...