x
Solved

# # of months between 2 dates

Posted on 2000-03-21
Medium Priority
479 Views
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?
0
Question by:binho
• 3
• 2
• 2

LVL 4

Expert Comment

ID: 2641317
hello pasted from the rxlib :

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

LVL 13

Expert Comment

ID: 2641370
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;
0

Author Comment

ID: 2641491
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...
0

LVL 4

Expert Comment

ID: 2641530
Why ? the fact is handled with :
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special }  No ?
Still a problem ?
0

LVL 13

Accepted Solution

Epsylon earned 150 total points
ID: 2641752
I modified it a little bit. May still not be what you want:

procedure TForm1.Button1Click(Sender: TObject);
var Date1, Date2: TDateTime;
y1, y2, m1, m2, d1, d2: Word;
begin
Date1 := Trunc(MonthCalendar1.Date);
Date2 := Trunc(MonthCalendar2.Date);
DecodeDate(Date1, y1 , m1, d1);
DecodeDate(Date2, y2 , m2, d2);
m1 := y1 * 12 + m1;
m2 := y2 * 12 + m2;
if (m1 <> m2) and (d1 > d2) then
Inc(m1);
Label1.Caption := IntToStr(m2 - m1) + ' months between the two dates';
Label2.Caption := FloatToStr((Date2 - Date1)) + ' days between the two dates';
end;
0

Author Comment

ID: 2642216
Epsylon worked out fine...
0

LVL 13

Expert Comment

ID: 2642265
I hope you're right  :o)

I did some testing but not excessively.

Cheers.
0

## Featured Post

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.