From: <ou...@us...> - 2007-06-10 08:39:54
|
Revision: 2033 http://svn.sourceforge.net/jcl/?rev=2033&view=rev Author: outchy Date: 2007-06-10 01:39:50 -0700 (Sun, 10 Jun 2007) Log Message: ----------- Mantis 4111: LastDayOfWeek returns wrong result. Moving Date and Time related functions from JclSchedule.pas to JclDateTime.pas. Modified Paths: -------------- trunk/jcl/source/common/JclDateTime.pas trunk/jcl/source/common/JclSchedule.pas Modified: trunk/jcl/source/common/JclDateTime.pas =================================================================== --- trunk/jcl/source/common/JclDateTime.pas 2007-06-09 20:52:48 UTC (rev 2032) +++ trunk/jcl/source/common/JclDateTime.pas 2007-06-10 08:39:50 UTC (rev 2033) @@ -200,6 +200,28 @@ function UnixTimeToFileTime(const AValue: TJclUnixTime32): TFileTime; {$ENDIF MSWINDOWS} +// Time stamps (formerly in JclSchedule) +function NullStamp: TTimeStamp; +function CompareTimeStamps(const Stamp1, Stamp2: TTimeStamp): Int64; +function EqualTimeStamps(const Stamp1, Stamp2: TTimeStamp): Boolean; +function IsNullTimeStamp(const Stamp: TTimeStamp): Boolean; +function TimeStampDOW(const Stamp: TTimeStamp): Integer; + +// Day of week (formerly in JclSchedule) +function FirstWeekDay(const Year, Month: Integer; var DOW: Integer): Integer; overload; +function FirstWeekDay(const Year, Month: Integer): Integer; overload; +function LastWeekDay(const Year, Month: Integer; var DOW: Integer): Integer; overload; +function LastWeekDay(const Year, Month: Integer): Integer; overload; +function IndexedWeekDay(const Year, Month: Integer; Index: Integer): Integer; +function FirstWeekendDay(const Year, Month: Integer; var DOW: Integer): Integer; overload; +function FirstWeekendDay(const Year, Month: Integer): Integer; overload; +function LastWeekendDay(const Year, Month: Integer; var DOW: Integer): Integer; overload; +function LastWeekendDay(const Year, Month: Integer): Integer; overload; +function IndexedWeekendDay(const Year, Month: Integer; Index: Integer): Integer; +function FirstDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; +function LastDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; +function IndexedDayOfWeek(const Year, Month, DayOfWeek, Index: Integer): Integer; + type EJclDateTimeError = class(EJclError); @@ -1204,6 +1226,264 @@ {$ENDIF MSWINDOWS} +// Time stamps utilities + +// Utility functions +function NullStamp: TTimeStamp; +begin + Result.Date := 0; + Result.Time := -1; +end; + +function CompareTimeStamps(const Stamp1, Stamp2: TTimeStamp): Int64; +begin + if Stamp1.Date < Stamp2.Date then + Result := -1 + else + if Stamp1.Date = Stamp2.Date then + begin + if Stamp1.Time < Stamp2.Time then + Result := -1 + else + if Stamp1.Time = Stamp2.Time then + Result := 0 + else // If Stamp1.Time > Stamp2.Time then + Result := 1; + end + else // if Stamp1.Date > Stamp2.Date then + Result := 1; +// Result := Int64(Stamp1) - Int64(Stamp2); +end; + +function EqualTimeStamps(const Stamp1, Stamp2: TTimeStamp): Boolean; +begin + Result := CompareTimeStamps(Stamp1, Stamp2) = 0; +end; + +function IsNullTimeStamp(const Stamp: TTimeStamp): Boolean; +begin + Result := CompareTimeStamps(NullStamp, Stamp) = 0; +end; + +function TimeStampDOW(const Stamp: TTimeStamp): Integer; +begin + Result := (Stamp.Date - 1) mod 7 + 1 +end; + +// day of week utilities + +function FirstWeekDay(const Year, Month: Integer; var DOW: Integer): Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, 1)); + if DOW > 5 then + begin + Result := 9 - DOW; + DOW := 1; + end + else + Result := 1; +end; + +function FirstWeekDay(const Year, Month: Integer): Integer; +var + Dummy: Integer; +begin + Result := FirstWeekDay(Year, Month, Dummy); +end; + +function LastWeekDay(const Year, Month: Integer; var DOW: Integer): Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, DaysInMonth(EncodeDate(Year, Month, 1)))); + if DOW > 5 then + begin + Result := DaysInMonth(EncodeDate(Year, Month, 1)) - (DOW - 5); + DOW := 5; + end + else + Result := DaysInMonth(EncodeDate(Year, Month, 1)); +end; + +function LastWeekDay(const Year, Month: Integer): Integer; +var + Dummy: Integer; +begin + Result := LastWeekDay(Year, Month, Dummy); +end; + +function IndexedWeekDay(const Year, Month: Integer; Index: Integer): Integer; +var + DOW: Integer; +begin + if Index > 0 then + Result := FirstWeekDay(Year, Month, DOW) + else + if Index < 0 then + Result := LastWeekDay(Year, Month, DOW) + else + Result := 0; + if Index > 1 then // n-th weekday from start of month + begin + Dec(Index); + if DOW > 1 then // adjust to first monday + begin + if Index < (5 - DOW) then + begin + Inc(Result, Index); + Index := 0; + end + else + begin + Dec(Index, 6 - DOW); + Inc(Result, 8 - DOW); + end; + end; + Result := Result + (7 * (Index div 5)) + (Index mod 5); + end + else + if Index < -1 then // n-th weekday from end of month + begin + Index := Abs(Index) - 1; + if DOW < 5 then // adjust to last friday + begin + if Index < DOW then + begin + Dec(Result, Index); + Index := 0; + end + else + begin + Dec(Index, DOW); + Dec(Result, DOW + 2); + end; + end; + Result := Result - (7 * (Index div 5)) - (Index mod 5); + end; + if (Result < 0) or (Result > DaysInMonth(EncodeDate(Year, Month, 1))) then + Result := 0; +end; + +function FirstWeekendDay(const Year, Month: Integer; var DOW: Integer): Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, 1)); + if DOW < 6 then + begin + Result := 7 - DOW; + DOW := 6; + end + else + Result := 1; +end; + +function FirstWeekendDay(const Year, Month: Integer): Integer; +var + Dummy: Integer; +begin + Result := FirstWeekendDay(Year, Month, Dummy); +end; + +function LastWeekendDay(const Year, Month: Integer; var DOW: Integer): Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, DaysInMonth(EncodeDate(Year, Month, 1)))); + if DOW < 6 then + begin + Result := DaysInMonth(EncodeDate(Year, Month, 1)) - DOW; + DOW := 7; + end + else + Result := DaysInMonth(EncodeDate(Year, Month, 1)); +end; + +function LastWeekendDay(const Year, Month: Integer): Integer; +var + Dummy: Integer; +begin + Result := LastWeekendDay(Year, Month, Dummy); +end; + +function IndexedWeekendDay(const Year, Month: Integer; Index: Integer): Integer; +var + DOW: Integer; +begin + if Index > 0 then + Result := FirstWeekendDay(Year, Month, DOW) + else + if Index < 0 then + Result := LastWeekendDay(Year, Month, DOW) + else + Result := 0; + if Index > 1 then // n-th weekend day from the start of the month + begin + if (DOW > 6) and not Odd(Index) then // Adjust to first saturday + begin + Inc(Result, 6); + Dec(Index); + end; + if Index > 1 then + begin + Dec(Index); + Result := Result + (7 * (Index div 2)) + (Index mod 2); + end; + end + else + if Index < -1 then // n-th weekend day from the start of the month + begin + Index := Abs(Index); + if (DOW < 7) and not Odd(Index) then // Adjust to last sunday + begin + Dec(Result, 6); + Dec(Index); + end; + if Index > 1 then + begin + Dec(Index); + Result := Result - (7 * (Index div 2)) - (Index mod 2); + end; + end; + if (Result < 0) or (Result > DaysInMonth(EncodeDate(Year, Month, 1))) then + Result := 0; +end; + +function FirstDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; +var + DOW: Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, 1)); + if DOW > DayOfWeek then + Result := 8 + DayOfWeek - DOW + else + if DOW < DayOfWeek then + Result := 1 + DayOfWeek - DOW + else + Result := 1; +end; + +function LastDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; +var + DOW: Integer; +begin + DOW := ISODayOfWeek(EncodeDate(Year, Month, DaysInMonth(EncodeDate(Year, Month, 1)))); + if DOW > DayOfWeek then + Result := DaysInMonth(EncodeDate(Year, Month, 1)) - (DOW - DayOfWeek) + else + if DOW < DayOfWeek then + Result := DaysInMonth(EncodeDate(Year, Month, 1)) - (7 - DayOfWeek + DOW) + else + Result := DaysInMonth(EncodeDate(Year, Month, 1)); +end; + +function IndexedDayOfWeek(const Year, Month, DayOfWeek, Index: Integer): Integer; +begin + if Index > 0 then + Result := FirstDayOfWeek(Year, Month, DayOfWeek) + 7 * (Index - 1) + else + if Index < 0 then + Result := LastDayOfWeek(Year, Month, DayOfWeek) - 7 * (Abs(Index) - 1) + else + Result := 0; + if (Result < 0) or (Result > DaysInMonth(EncodeDate(Year, Month, 1))) then + Result := 0; +end; + {$IFDEF UNITVERSIONING} initialization RegisterUnitVersion(HInstance, UnitVersioning); Modified: trunk/jcl/source/common/JclSchedule.pas =================================================================== --- trunk/jcl/source/common/JclSchedule.pas 2007-06-09 20:52:48 UTC (rev 2032) +++ trunk/jcl/source/common/JclSchedule.pas 2007-06-10 08:39:50 UTC (rev 2033) @@ -174,10 +174,6 @@ end; function CreateSchedule: IJclSchedule; -function NullStamp: TTimeStamp; -function CompareTimeStamps(const Stamp1, Stamp2: TTimeStamp): Int64; -function EqualTimeStamps(const Stamp1, Stamp2: TTimeStamp): Boolean; -function IsNullTimeStamp(const Stamp: TTimeStamp): Boolean; {$IFDEF UNITVERSIONING} const @@ -257,265 +253,6 @@ {$ENDIF ~RTL140_UP} -// Utility functions -function NullStamp: TTimeStamp; -begin - Result.Date := 0; - Result.Time := -1; -end; - -function CompareTimeStamps(const Stamp1, Stamp2: TTimeStamp): Int64; -begin - if Stamp1.Date < Stamp2.Date then - Result := -1 - else - if Stamp1.Date = Stamp2.Date then - begin - if Stamp1.Time < Stamp2.Time then - Result := -1 - else - if Stamp1.Time = Stamp2.Time then - Result := 0 - else // If Stamp1.Time > Stamp2.Time then - Result := 1; - end - else // if Stamp1.Date > Stamp2.Date then - Result := 1; -// Result := Int64(Stamp1) - Int64(Stamp2); -end; - -function EqualTimeStamps(const Stamp1, Stamp2: TTimeStamp): Boolean; -begin - Result := CompareTimeStamps(Stamp1, Stamp2) = 0; -end; - -function IsNullTimeStamp(const Stamp: TTimeStamp): Boolean; -begin - Result := CompareTimeStamps(NullStamp, Stamp) = 0; -end; - -function TimeStampDOW(const Stamp: TTimeStamp): Integer; -begin - Result := (Stamp.Date - 1) mod 7 + 1 -end; - -function ISODayOfWeek(DateTime: TDateTime): Integer; -begin - Result := (DayOfWeek(DateTime - 2 + 7) mod 7) + 1; -end; - -function FirstWeekDayPrim(const Year, Month: Integer; var DOW: Integer): Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, 1)); - if DOW > 5 then - begin - Result := 9 - DOW; - DOW := 1; - end - else - Result := 1; -end; - -function LastWeekDayPrim(const Year, Month: Integer; var DOW: Integer): Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)))); - if DOW > 5 then - begin - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)) - (DOW - 5); - DOW := 5; - end - else - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)); -end; - -function FirstWeekendDayPrim(const Year, Month: Integer; var DOW: Integer): Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, 1)); - if DOW < 6 then - begin - Result := 7 - DOW; - DOW := 6; - end - else - Result := 1; -end; - -function LastWeekendDayPrim(const Year, Month: Integer; var DOW: Integer): Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)))); - if DOW < 6 then - begin - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)) - DOW; - DOW := 7; - end - else - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)); -end; - -function FirstWeekDay(const Year, Month: Integer): Integer; -var - Dummy: Integer; -begin - Result := FirstWeekDayPrim(Year, Month, Dummy); -end; - -function LastWeekDay(const Year, Month: Integer): Integer; -var - Dummy: Integer; -begin - Result := LastWeekDayPrim(Year, Month, Dummy); -end; - -function IndexedWeekDay(const Year, Month: Integer; Index: Integer): Integer; -var - DOW: Integer; -begin - if Index > 0 then - Result := FirstWeekDayPrim(Year, Month, DOW) - else - if Index < 0 then - Result := LastWeekDayPrim(Year, Month, DOW) - else - Result := 0; - if Index > 1 then // n-th weekday from start of month - begin - Dec(Index); - if DOW > 1 then // adjust to first monday - begin - if Index < (5 - DOW) then - begin - Inc(Result, Index); - Index := 0; - end - else - begin - Dec(Index, 6 - DOW); - Inc(Result, 8 - DOW); - end; - end; - Result := Result + (7 * (Index div 5)) + (Index mod 5); - end - else - if Index < -1 then // n-th weekday from end of month - begin - Index := Abs(Index) - 1; - if DOW < 5 then // adjust to last friday - begin - if Index < DOW then - begin - Dec(Result, Index); - Index := 0; - end - else - begin - Dec(Index, DOW); - Dec(Result, DOW + 2); - end; - end; - Result := Result - (7 * (Index div 5)) - (Index mod 5); - end; - if (Result < 0) or (Result > DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1))) then - Result := 0; -end; - -function FirstWeekendDay(const Year, Month: Integer): Integer; -var - Dummy: Integer; -begin - Result := FirstWeekendDayPrim(Year, Month, Dummy); -end; - -function LastWeekendDay(const Year, Month: Integer): Integer; -var - Dummy: Integer; -begin - Result := LastWeekendDayPrim(Year, Month, Dummy); -end; - -function IndexedWeekendDay(const Year, Month: Integer; Index: Integer): Integer; -var - DOW: Integer; -begin - if Index > 0 then - Result := FirstWeekendDayPrim(Year, Month, DOW) - else - if Index < 0 then - Result := LastWeekendDayPrim(Year, Month, DOW) - else - Result := 0; - if Index > 1 then // n-th weekend day from the start of the month - begin - if (DOW > 6) and not Odd(Index) then // Adjust to first saturday - begin - Inc(Result, 6); - Dec(Index); - end; - if Index > 1 then - begin - Dec(Index); - Result := Result + (7 * (Index div 2)) + (Index mod 2); - end; - end - else - if Index < -1 then // n-th weekend day from the start of the month - begin - Index := Abs(Index); - if (DOW < 7) and not Odd(Index) then // Adjust to last sunday - begin - Dec(Result, 6); - Dec(Index); - end; - if Index > 1 then - begin - Dec(Index); - Result := Result - (7 * (Index div 2)) - (Index mod 2); - end; - end; - if (Result < 0) or (Result > DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1))) then - Result := 0; -end; - -function FirstDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; -var - DOW: Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, 1)); - if DOW > DayOfWeek then - Result := 8 + DayOfWeek - DOW - else - if DOW < DayOfWeek then - Result := 1 + DayOfWeek - DOW - else - Result := 1; -end; - -function LastDayOfWeek(const Year, Month, DayOfWeek: Integer): Integer; -var - DOW: Integer; -begin - DOW := ISODayOfWeek(JclDateTime.EncodeDate(Year, Month, DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)))); - if DOW > DayOfWeek then - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)) - (DOW - DayOfWeek) - else - if DOW < DayOfWeek then - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)) - (7 + DayOfWeek - DOW) - else - Result := DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1)); -end; - -function IndexedDayOfWeek(const Year, Month, DayOfWeek, Index: Integer): Integer; -begin - if Index > 0 then - Result := FirstDayOfWeek(Year, Month, DayOfWeek) + 7 * (Index - 1) - else - if Index < 0 then - Result := LastDayOfWeek(Year, Month, DayOfWeek) - 7 * (Abs(Index) - 1) - else - Result := 0; - if (Result < 0) or (Result > DaysInMonth(JclDateTime.EncodeDate(Year, Month, 1))) then - Result := 0; -end; - //=== { TScheduleAggregate } ================================================= type This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |