NOTE: You need do add the unit "DateUtils" to the uses clause (where DayOfTheWeek is declared).
//----------------------------------------------------------------
type
TWeeks = (wFirst, wSecond, wThird, wFourth, wLast);
TWeekDays = (wdMonday, wdTuesday, wdWednesday, wdThursday,
wdFriday, wdSaturday, wdSunday);
//Examples:
//ShowMessage(DateTimeToStr(GetDayOfMonth(Now, wLast, wdTuesday)));
//ShowMessage(DateTimeToStr(GetDayOfMonth(Now, wFirst, wdSunday)));
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;
function GetDayOfMonth(DT: TDateTime; Weeks: TWeeks; WeekDays: TWeekDays): TDateTime;
var
aDateTime: TDateTime;
aDayOfWeek, bDayOfWeek: Word;
AYear, AMonth, ADay: Word;
begin
DecodeDate(DT, AYear, AMonth, ADay);
aDateTime := EncodeDate(AYear, AMonth, 1); //Returns the 1st day of the month
//-DayOfTheWeek-
//1 - Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, 7 - Sunday
aDayOfWeek := DayOfTheWeek(aDateTime);
//-WeekDays-
//0 - Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, 6 - Sunday
bDayOfWeek := Ord(WeekDays) +1;
if aDayOfWeek <= bDayOfWeek //The day we want is still yet to come
then ADay := (bDayOfWeek - aDayOfWeek)
else ADay := 7 - (aDayOfWeek - bDayOfWeek);
//-Weeks-
//0 - first, 1 - second, 2 - third, 3 - fourth, 4 - last
ADay := ADay + Ord(Weeks) * 7;
if Ord(Weeks) = 4 then
if (ADay+1 > DaysPerMonth(AYear, AMonth))
or ( (ADay+1 <= DaysPerMonth(AYear, AMonth))
and (bDayOfWeek <> DayOfTheWeek(EncodeDate(AYear, AMonth, ADay+1))) )
then ADay := ADay - 7;
Result := aDateTime + ADay;
end;
//----------------------------------------------------------------
I'm sure there are better ways to deal with this problem so please let me know if you happen to know any.
0 comments:
Post a Comment