git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@21 05c56307-c608-d34a-929d-697000501d7a
1231 lines
36 KiB
ObjectPascal
1231 lines
36 KiB
ObjectPascal
|
|
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ Express Cross Platform Library classes }
|
|
{ }
|
|
{ Copyright (c) 2000-2007 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSCROSSPLATFORMLIBRARY AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM }
|
|
{ ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxDateUtils;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
Windows;
|
|
|
|
type
|
|
TDay = (dSunday, dMonday, dTuesday, dWednesday, dThursday, dFriday, dSaturday);
|
|
TDays = set of TDay;
|
|
TDayOfWeek = 0..6;
|
|
TcxDateElement = (deYear, deMonth, deDay);
|
|
TcxFirstWeekOfYear = (fwySystem, fwyJan1, fwyFirstFullWeek, fwyFirstFourDays);
|
|
|
|
const
|
|
DATE_YEARMONTH = $00000008; // use year month picture
|
|
{$EXTERNALSYM DATE_YEARMONTH}
|
|
DATE_LTRREADING = $00000010; // add marks for left to right reading order layout
|
|
{$EXTERNALSYM DATE_LTRREADING}
|
|
DATE_RTLREADING = $00000020; // add marks for right to left reading order layout
|
|
{$EXTERNALSYM DATE_RTLREADING}
|
|
|
|
NullDate = -700000;
|
|
InvalidDate = NullDate + 1;
|
|
SmartTextToDateFunc: function(const AText: string; var ADate: TDateTime): Boolean = nil;
|
|
|
|
{$IFNDEF DELPHI7}
|
|
ApproxDaysPerMonth: Double = 30.4375;
|
|
ApproxDaysPerYear: Double = 365.25;
|
|
DaysPerWeek = 7;
|
|
WeeksPerFortnight = 2;
|
|
MonthsPerYear = 12;
|
|
YearsPerDecade = 10;
|
|
YearsPerCentury = 100;
|
|
YearsPerMillennium = 1000;
|
|
HoursPerDay = 24;
|
|
MinsPerHour = 60;
|
|
SecsPerMin = 60;
|
|
MSecsPerSec = 1000;
|
|
MinsPerDay = HoursPerDay * MinsPerHour;
|
|
SecsPerDay = MinsPerDay * SecsPerMin;
|
|
MSecsPerDay = SecsPerDay * MSecsPerSec;
|
|
DayMonday = 1;
|
|
DayTuesday = 2;
|
|
DayWednesday = 3;
|
|
DayThursday = 4;
|
|
DayFriday = 5;
|
|
DaySaturday = 6;
|
|
DaySunday = 7;
|
|
{$ENDIF}
|
|
|
|
var
|
|
MinYear: Integer = 100;
|
|
MaxYear: Integer = 9999;
|
|
cxMaxDateTime: Double = 2958465.99999; // 12/31/9999 11:59:59.999 PM
|
|
|
|
procedure AddDateRegExprMaskSmartInput(var AMask: string; ACanEnterTime: Boolean);
|
|
procedure DecMonth(var AYear, AMonth: Word);
|
|
procedure IncMonth(var AYear, AMonth: Word); overload;
|
|
procedure ChangeMonth(var AYear, AMonth: Word; Delta: Integer);
|
|
function GetMonthNumber(const ADate: TDateTime): Integer;
|
|
function GetDateElement(ADate: TDateTime; AElement: TcxDateElement): Integer;
|
|
function IsLeapYear(AYear: Integer): Boolean;
|
|
function DaysPerMonth(AYear, AMonth: Integer): Integer;
|
|
function CheckDay(AYear, AMonth, ADay: Integer): Integer;
|
|
function TimeOf(const AValue: TDateTime): TDateTime;
|
|
function DateOf(const AValue: TDateTime): TDateTime;
|
|
function DayOfWeekOffset(const AValue: TDateTime): TDayOfWeek;
|
|
|
|
function GetStartDateOfMonth(const ADate: TDateTime): TDateTime;
|
|
function GetStartOfWeek: Integer;
|
|
function GetEndDateOfMonth(const ADate: TDateTime; AIgnoreTime: Boolean): TDateTime;
|
|
function GetStartDateOfYear(const ADate: TDateTime): TDateTime;
|
|
function GetEndDateOfYear(const ADate: TDateTime; AIgnoreTime: Boolean): TDateTime;
|
|
|
|
{!!! TODO: adapt to .net}
|
|
function cxGetDateFormat(ADate: TDateTime; out AFormatDate: string; AFlags: Integer; AFormat: string = ''): Boolean;
|
|
function DateToLongDateStr(ADate: TDateTime): string;
|
|
function GetWeekNumber(ADate: TDateTime; AStartOfWeek: TDay;
|
|
AFirstWeekOfYear: TcxFirstWeekOfYear): Integer;
|
|
|
|
{$IFNDEF DELPHI6}
|
|
function HourOf(ADateTime: TDateTime): Word;
|
|
function IsPM(const AValue: TDateTime): Boolean;
|
|
function EncodeDateWeek(const AYear, AWeekOfYear: Word;
|
|
const ADayOfWeek: Word): TDateTime;
|
|
procedure DecodeDateWeek(const AValue: TDateTime; out AYear, AWeekOfYear,
|
|
ADayOfWeek: Word);
|
|
function DaysInAMonth(const AYear, AMonth: Word): Word;
|
|
function DaysInMonth(const AValue: TDateTime): Word;
|
|
function DayOf(const AValue: TDateTime): Word;
|
|
function DayOfTheMonth(const AValue: TDateTime): Word;
|
|
function DayOfTheWeek(const AValue: TDateTime): Word;
|
|
procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay,
|
|
AHour, AMinute, ASecond, AMilliSecond: Word);
|
|
function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
|
|
AMilliSecond: Word): TDateTime;
|
|
procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
|
|
function MinuteOf(const AValue: TDateTime): Word;
|
|
function MonthOf(const AValue: TDateTime): Word;
|
|
function StartOfTheYear(const AValue: TDateTime): TDateTime;
|
|
function StartOfTheMonth(const AValue: TDateTime): TDateTime;
|
|
function YearOf(const AValue: TDateTime): Word;
|
|
function YearsBetween(const ANow, AThen: TDateTime): Integer;
|
|
function MonthsBetween(const ANow, AThen: TDateTime): Integer;
|
|
function WeeksBetween(const ANow, AThen: TDateTime): Integer;
|
|
function DaysBetween(const ANow, AThen: TDateTime): Integer;
|
|
function IncYear(const AValue: TDateTime;
|
|
const ANumberOfYears: Integer = 1): TDateTime;
|
|
function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer): TDateTime; overload;
|
|
function IncWeek(const AValue: TDateTime;
|
|
const ANumberOfWeeks: Integer = 1): TDateTime;
|
|
function IncDay(const AValue: TDateTime;
|
|
const ANumberOfDays: Integer = 1): TDateTime;
|
|
function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64 = 1): TDateTime;
|
|
function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64 = 1): TDateTime;
|
|
function WeekOfTheMonth(const AValue: TDateTime): Word;
|
|
function WeekOf(AValue: TDateTime): Word;
|
|
function WeekOfTheYear(const AValue: TDateTime): Word;
|
|
function DayOfTheYear(AValue: TDateTime): Word;
|
|
function EndOfTheYear(AValue: TDateTime): TDateTime;
|
|
{$ENDIF}
|
|
|
|
function StrToDateDef(const ADateStr: string; ADefDate: TDateTime): TDateTime;
|
|
function SmartTextToDate(const AText: string; var ADate: TDateTime): Boolean;
|
|
function TextToDateEx(AText: string; var ADate: TDateTime): Boolean;
|
|
function cxDateTimeToText(ADate: TDateTime; AFourDigitYearNeeded: Boolean = False; AUseDelphiDateTimeFormats: Boolean = False): string;
|
|
function DateTimeToText(ADate: TDateTime; AFourDigitYearNeeded: Boolean = False): string;
|
|
function DateTimeToTextEx(const ADate: TDateTime; AIsMasked: Boolean;
|
|
AIsDateTimeEdit: Boolean = False; AFourDigitYearNeeded: Boolean = False): string;
|
|
function cxMinDateTime: Double;
|
|
function cxStrToDateTime(S: string; AUseOleDateFormat: Boolean;
|
|
out ADate: TDateTime): Boolean;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
DateUtils,
|
|
{$ENDIF}
|
|
SysUtils, Classes, cxClasses, cxFormats, cxLibraryStrs;
|
|
|
|
type
|
|
TcxDateEditSmartInput = (deiToday, deiYesterday, deiTomorrow,
|
|
deiSunday, deiMonday, deiTuesday, deiWednesday, deiThursday, deiFriday, deiSaturday,
|
|
deiFirst, deiSecond, deiThird, deiFourth, deiFifth, deiSixth, deiSeventh,
|
|
deiBOM, deiEOM, deiNow);
|
|
|
|
var
|
|
scxDateEditSmartInput: array [TcxDateEditSmartInput] of string;
|
|
|
|
function cxGetLocaleChar(ALocaleType: Integer; const ADefaultValue: Char): string;
|
|
begin
|
|
Result := cxGetLocaleInfo(GetThreadLocale, ALocaleType, ADefaultValue)[1];
|
|
end;
|
|
|
|
function cxGetLocaleStr(ALocaleType: Integer; const ADefaultValue: string = ''): string;
|
|
begin
|
|
Result := cxGetLocaleInfo(GetThreadLocale, ALocaleType, ADefaultValue);
|
|
end;
|
|
|
|
procedure CorrectTextForDateTimeConversion(var AText: string;
|
|
AOleConversion: Boolean);
|
|
|
|
procedure InternalStringReplace(var S: WideString; ASubStr: WideString);
|
|
begin
|
|
S := StringReplace(S, ASubStr, GetCharString(' ', Length(ASubStr)),
|
|
[rfIgnoreCase, rfReplaceAll]);
|
|
end;
|
|
|
|
procedure GetSpecialStrings(AList: TStringList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AOleConversion then
|
|
begin
|
|
AList.Add(cxGetLocaleStr(LOCALE_SDATE)[1]);
|
|
AList.Add(cxGetLocaleStr(LOCALE_STIME)[1]);
|
|
AList.Add(cxGetLocaleStr(LOCALE_S1159, 'am'));
|
|
AList.Add(cxGetLocaleStr(LOCALE_S2359, 'pm'));
|
|
end
|
|
else
|
|
begin
|
|
AList.Add(DateSeparator);
|
|
AList.Add(TimeSeparator);
|
|
AList.Add(TimeAMString);
|
|
AList.Add(TimePMString);
|
|
end;
|
|
for I := 0 to AList.Count - 1 do
|
|
AList[I] := AnsiUpperCase(Trim(AList[I]));
|
|
end;
|
|
|
|
procedure RemoveStringsThatInFormatInfo(var S: WideString;
|
|
const ADateTimeFormatInfo: TcxDateTimeFormatInfo);
|
|
var
|
|
ASpecialStrings: TStringList;
|
|
ASubStr: string;
|
|
I: Integer;
|
|
begin
|
|
ASpecialStrings := TStringList.Create;
|
|
try
|
|
GetSpecialStrings(ASpecialStrings);
|
|
for I := 0 to High(ADateTimeFormatInfo.Items) do
|
|
if ADateTimeFormatInfo.Items[I].Kind = dtikString then
|
|
begin
|
|
ASubStr := AnsiUpperCase(Trim(ADateTimeFormatInfo.Items[I].Data));
|
|
if (ASubStr <> '') and (ASpecialStrings.IndexOf(ASubStr) = -1) then
|
|
InternalStringReplace(S, ASubStr);
|
|
end;
|
|
finally
|
|
ASpecialStrings.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure RemoveUnnecessarySpaces(var S: WideString);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
S := Trim(S);
|
|
I := 2;
|
|
while I < Length(S) - 1 do
|
|
if (S[I] <= ' ') and (S[I + 1] <= ' ') then
|
|
Delete(S, I, 1)
|
|
else
|
|
Inc(I);
|
|
end;
|
|
|
|
var
|
|
S: WideString;
|
|
begin
|
|
S := AText;
|
|
RemoveStringsThatInFormatInfo(S, cxFormatController.DateFormatInfo);
|
|
RemoveStringsThatInFormatInfo(S, cxFormatController.TimeFormatInfo);
|
|
RemoveUnnecessarySpaces(S);
|
|
if AOleConversion then
|
|
InternalStringReplace(S, cxGetLocaleStr(LOCALE_SDATE)[1]);
|
|
AText := S;
|
|
end;
|
|
|
|
procedure InitSmartInputConsts;
|
|
begin
|
|
scxDateEditSmartInput[deiToday] := cxGetResourceString(@cxSDateToday);
|
|
scxDateEditSmartInput[deiYesterday] := cxGetResourceString(@cxSDateYesterday);
|
|
scxDateEditSmartInput[deiTomorrow] := cxGetResourceString(@cxSDateTomorrow);
|
|
scxDateEditSmartInput[deiSunday] := cxGetResourceString(@cxSDateSunday);
|
|
scxDateEditSmartInput[deiMonday] := cxGetResourceString(@cxSDateMonday);
|
|
scxDateEditSmartInput[deiTuesday] := cxGetResourceString(@cxSDateTuesday);
|
|
scxDateEditSmartInput[deiWednesday] := cxGetResourceString(@cxSDateWednesday);
|
|
scxDateEditSmartInput[deiThursday] := cxGetResourceString(@cxSDateThursday);
|
|
scxDateEditSmartInput[deiFriday] := cxGetResourceString(@cxSDateFriday);
|
|
scxDateEditSmartInput[deiSaturday] := cxGetResourceString(@cxSDateSaturday);
|
|
scxDateEditSmartInput[deiFirst] := cxGetResourceString(@cxSDateFirst);
|
|
scxDateEditSmartInput[deiSecond] := cxGetResourceString(@cxSDateSecond);
|
|
scxDateEditSmartInput[deiThird] := cxGetResourceString(@cxSDateThird);
|
|
scxDateEditSmartInput[deiFourth] := cxGetResourceString(@cxSDateFourth);
|
|
scxDateEditSmartInput[deiFifth] := cxGetResourceString(@cxSDateFifth);
|
|
scxDateEditSmartInput[deiSixth] := cxGetResourceString(@cxSDateSixth);
|
|
scxDateEditSmartInput[deiSeventh] := cxGetResourceString(@cxSDateSeventh);
|
|
scxDateEditSmartInput[deiBOM] := cxGetResourceString(@cxSDateBOM);
|
|
scxDateEditSmartInput[deiEOM] := cxGetResourceString(@cxSDateEOM);
|
|
scxDateEditSmartInput[deiNow] := cxGetResourceString(@cxSDateNow);
|
|
end;
|
|
|
|
procedure AddDateRegExprMaskSmartInput(var AMask: string; ACanEnterTime: Boolean);
|
|
|
|
procedure AddString(var AMask: string; const S: string);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := 1;
|
|
while I <= Length(S) do
|
|
if S[I] = '''' then
|
|
begin
|
|
AMask := AMask + '\''';
|
|
Inc(I);
|
|
end
|
|
else
|
|
begin
|
|
AMask := AMask + '''';
|
|
repeat
|
|
AMask := AMask + S[I];
|
|
Inc(I);
|
|
until (I > Length(S)) or (S[I] = '''');
|
|
AMask := AMask + '''';
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: TcxDateEditSmartInput;
|
|
begin
|
|
InitSmartInputConsts;
|
|
AMask := '(' + AMask + ')|(';
|
|
I := Low(TcxDateEditSmartInput);
|
|
if not ACanEnterTime and (I = deiNow) then
|
|
Inc(I);
|
|
AddString(AMask, scxDateEditSmartInput[I]);
|
|
while I < High(TcxDateEditSmartInput) do
|
|
begin
|
|
Inc(I);
|
|
if not(not ACanEnterTime and (I = deiNow)) then
|
|
begin
|
|
AMask := AMask + '|';
|
|
AddString(AMask, scxDateEditSmartInput[I]);
|
|
end;
|
|
end;
|
|
AMask := AMask + ')((\+|-)\d(\d(\d\d?)?)?)?';
|
|
end;
|
|
|
|
procedure DecMonth(var AYear, AMonth: Word);
|
|
begin
|
|
if AMonth = 1 then
|
|
begin
|
|
Dec(AYear);
|
|
AMonth := 12;
|
|
end
|
|
else Dec(AMonth);
|
|
end;
|
|
|
|
procedure IncMonth(var AYear, AMonth: Word);
|
|
begin
|
|
if AMonth = 12 then
|
|
begin
|
|
Inc(AYear);
|
|
AMonth := 1;
|
|
end
|
|
else Inc(AMonth);
|
|
end;
|
|
|
|
procedure ChangeMonth(var AYear, AMonth: Word; Delta: Integer);
|
|
var
|
|
Month: Integer;
|
|
begin
|
|
Inc(AYear, Delta div 12);
|
|
Month := AMonth;
|
|
Inc(Month, Delta mod 12);
|
|
if Month < 1 then
|
|
begin
|
|
Dec(AYear);
|
|
Month := 12 + Month;
|
|
end;
|
|
if Month > 12 then
|
|
begin
|
|
Inc(AYear);
|
|
Month := Month - 12;
|
|
end;
|
|
AMonth := Month;
|
|
end;
|
|
|
|
function GetMonthNumber(const ADate: TDateTime): Integer;
|
|
var
|
|
AYear, AMonth, ADay: Word;
|
|
begin
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
Result := (AYear - 1) * 12 + AMonth;
|
|
end;
|
|
|
|
function GetDateElement(ADate: TDateTime; AElement: TcxDateElement): Integer;
|
|
var
|
|
AYear, AMonth, ADay: Word;
|
|
begin
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
case AElement of
|
|
deYear: Result := AYear;
|
|
deMonth: Result := AMonth;
|
|
else
|
|
{deDay:} Result := ADay; // make compiler happy
|
|
end;
|
|
end;
|
|
|
|
function IsLeapYear(AYear: Integer): Boolean;
|
|
begin
|
|
Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0));
|
|
end;
|
|
|
|
function DaysPerMonth(AYear, AMonth: Integer): Integer;
|
|
const
|
|
ADaysInMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
|
begin
|
|
Result := ADaysInMonth[AMonth];
|
|
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result);
|
|
end;
|
|
|
|
function CheckDay(AYear, AMonth, ADay: Integer): Integer;
|
|
begin
|
|
if ADay < 1 then
|
|
Result := 1
|
|
else
|
|
if ADay > DaysPerMonth(AYear, AMonth) then
|
|
Result := DaysPerMonth(AYear, AMonth)
|
|
else
|
|
Result := ADay;
|
|
end;
|
|
|
|
function TimeOf(const AValue: TDateTime): TDateTime;
|
|
//to avoid problem
|
|
//var
|
|
// Hour, Min, Sec, MSec: Word;
|
|
begin
|
|
// DecodeTime(ADateTime, Hour, Min, Sec, MSec);
|
|
// Result := EncodeTime(Hour, Min, Sec, MSec);
|
|
Result := Frac(AValue);
|
|
end;
|
|
|
|
function DateOf(const AValue: TDateTime): TDateTime;
|
|
begin
|
|
//to avoid problem
|
|
// Result := Trunc(ADateTime + (2 * Byte(ADateTime >= 0) - 1) * 1E-11);
|
|
Result := Trunc(AValue);
|
|
end;
|
|
|
|
function DayOfWeekOffset(const AValue: TDateTime): TDayOfWeek;
|
|
var
|
|
AOffset: Integer;
|
|
begin
|
|
AOffset := DayOfWeek(AValue) - 1 - cxFormatController.StartOfWeek;
|
|
if AOffset < 0 then
|
|
Inc(AOffset, 7);
|
|
Result := AOffset;
|
|
end;
|
|
|
|
function GetStartDateOfMonth(const ADate: TDateTime): TDateTime;
|
|
var
|
|
AYear, AMonth, ADay: Word;
|
|
begin
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
Result := EncodeDate(AYear, AMonth, 1);
|
|
end;
|
|
|
|
function GetStartOfWeek: Integer;
|
|
begin
|
|
Result := StrToInt(cxGetLocaleInfo(GetThreadLocale, LOCALE_IFIRSTDAYOFWEEK, '0')) + 1;
|
|
if Result > 6 then
|
|
Result := 0;
|
|
end;
|
|
|
|
function GetEndDateOfMonth(const ADate: TDateTime; AIgnoreTime: Boolean): TDateTime;
|
|
var
|
|
AYear, AMonth, ADay: Word;
|
|
begin
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
Result := EncodeDate(AYear, AMonth, MonthDays[IsLeapYear(AYear), AMonth]);
|
|
if not AIgnoreTime then
|
|
Result := Result + EncodeTime(23, 59, 59, 999);
|
|
end;
|
|
|
|
function GetStartDateOfYear(const ADate: TDateTime): TDateTime;
|
|
begin
|
|
Result := EncodeDate(GetDateElement(ADate, deYear), 1, 1);
|
|
end;
|
|
|
|
function GetEndDateOfYear(const ADate: TDateTime; AIgnoreTime: Boolean): TDateTime;
|
|
begin
|
|
Result := EncodeDate(GetDateElement(ADate, deYear), 12, 31);
|
|
if not AIgnoreTime then
|
|
Result := Result + EncodeTime(23, 59, 59, 999);
|
|
end;
|
|
|
|
{!!! TODO: adapt to .net}
|
|
function cxGetDateFormat(ADate: TDateTime; out AFormatDate: string; AFlags: Integer; AFormat: string = ''): Boolean;
|
|
var
|
|
L: Integer;
|
|
P: PChar;
|
|
ASystemDate: TSystemTime;
|
|
Buffer: array[0..255] of Char;
|
|
begin
|
|
DateTimeToSystemTime(ADate, ASystemDate);
|
|
if Length(AFormat) = 0 then P := nil else P := PChar(AFormat);
|
|
L := GetDateFormat(GetThreadLocale, AFlags, @ASystemDate, P, Buffer, SizeOf(Buffer));
|
|
Result := L > 0;
|
|
if Result then SetString(AFormatDate, Buffer, L - 1) else AFormatDate := '';
|
|
end;
|
|
|
|
function DateToLongDateStr(ADate: TDateTime): string;
|
|
begin
|
|
if not cxGetDateFormat(ADate, Result, DATE_LONGDATE) then
|
|
Result := FormatDateTime('dddddd', Date);
|
|
end;
|
|
|
|
function GetWeekNumber(ADate: TDateTime; AStartOfWeek: TDay;
|
|
AFirstWeekOfYear: TcxFirstWeekOfYear): Integer;
|
|
|
|
function FindFirstDayOfWeekDate(ADate: TDateTime): TDateTime;
|
|
var
|
|
ADayOfWeek: TDay;
|
|
ADelta: Integer;
|
|
begin
|
|
ADayOfWeek := TDay(DayOfWeek(ADate) - 1);
|
|
ADelta := Ord(ADayOfWeek) - Ord(AStartOfWeek);
|
|
if ADelta < 0 then Inc(ADelta, 7);
|
|
Result := Trunc(ADate) - ADelta;
|
|
end;
|
|
|
|
var
|
|
AYear, AMonth, ADay: Word;
|
|
AStartWeekDate: TDateTime;
|
|
AStart: TDateTime;
|
|
begin
|
|
if AFirstWeekOfYear = fwySystem then
|
|
AFirstWeekOfYear := TcxFirstWeekOfYear(
|
|
StrToInt(cxGetLocaleChar(LOCALE_IFIRSTWEEKOFYEAR, '0')) + 1);
|
|
AStart := FindFirstDayOfWeekDate(StartOfTheYear(ADate));
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
case AFirstWeekOfYear of
|
|
fwyFirstFourDays:
|
|
if YearOf(AStart + 3) < AYear then AStart := AStart + 7;
|
|
fwyFirstFullWeek:
|
|
if YearOf(AStart) < AYear then AStart := AStart + 7;
|
|
end;
|
|
//DELPHI8! check Trunc()
|
|
Result := Trunc(Trunc(ADate) - AStart) div 7 + 1;
|
|
if AMonth = 12 then
|
|
begin
|
|
AStartWeekDate := FindFirstDayOfWeekDate(ADate);
|
|
case AFirstWeekOfYear of
|
|
fwyJan1:
|
|
if MonthOf(AStartWeekDate + 6) = 1 then
|
|
Result := 1;
|
|
fwyFirstFourDays:
|
|
if MonthOf(AStartWeekDate + 3) = 1 then
|
|
Result := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IFNDEF DELPHI6}
|
|
function HourOf(ADateTime: TDateTime): Word;
|
|
var
|
|
AMin, ASec, AMilliSec: Word;
|
|
begin
|
|
DecodeTime(ADateTime, Result, AMin, ASec, AMilliSec);
|
|
end;
|
|
|
|
function IsPM(const AValue: TDateTime): Boolean;
|
|
begin
|
|
Result := HourOf(AValue) >= 12;
|
|
end;
|
|
|
|
function DaysInAMonth(const AYear, AMonth: Word): Word;
|
|
begin
|
|
Result := MonthDays[(AMonth = 2) and IsLeapYear(AYear), AMonth];
|
|
end;
|
|
|
|
function DaysInMonth(const AValue: TDateTime): Word;
|
|
begin
|
|
Result := DaysInAMonth(YearOf(AValue), MonthOf(AValue));
|
|
end;
|
|
|
|
function DayOf(const AValue: TDateTime): Word;
|
|
var
|
|
AYear, AMonth: Word;
|
|
begin
|
|
DecodeDate(AValue, AYear, AMonth, Result);
|
|
end;
|
|
|
|
function DayOfTheMonth(const AValue: TDateTime): Word;
|
|
begin
|
|
Result := DayOf(AValue);
|
|
end;
|
|
|
|
function DayOfTheWeek(const AValue: TDateTime): Word;
|
|
begin
|
|
Result := (DateTimeToTimeStamp(AValue).Date - 1) mod 7 + 1;
|
|
end;
|
|
|
|
procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay,
|
|
AHour, AMinute, ASecond, AMilliSecond: Word);
|
|
begin
|
|
DecodeDate(AValue, AYear, AMonth, ADay);
|
|
DecodeTime(AValue, AHour, AMinute, ASecond, AMilliSecond);
|
|
end;
|
|
|
|
function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
|
|
AMilliSecond: Word): TDateTime;
|
|
begin
|
|
Result := EncodeDate(AYear, AMonth, ADay) +
|
|
EncodeTime(AHour, AMinute, ASecond, AMilliSecond);
|
|
end;
|
|
|
|
procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
|
|
var
|
|
DayTable: PDayTable;
|
|
Sign: Integer;
|
|
begin
|
|
if NumberOfMonths >= 0 then Sign := 1 else Sign := -1;
|
|
Year := Year + (NumberOfMonths div 12);
|
|
NumberOfMonths := NumberOfMonths mod 12;
|
|
Inc(Month, NumberOfMonths);
|
|
if Word(Month-1) > 11 then // if Month <= 0, word(Month-1) > 11)
|
|
begin
|
|
Inc(Year, Sign);
|
|
Inc(Month, -12 * Sign);
|
|
end;
|
|
DayTable := @MonthDays[IsLeapYear(Year)];
|
|
if Day > DayTable^[Month] then Day := DayTable^[Month];
|
|
end;
|
|
|
|
function MinuteOf(const AValue: TDateTime): Word;
|
|
var
|
|
AHour, ASecond, AMilliSecond: Word;
|
|
begin
|
|
DecodeTime(AValue, AHour, Result, ASecond, AMilliSecond);
|
|
end;
|
|
|
|
function MonthOf(const AValue: TDateTime): Word;
|
|
var
|
|
AYear, ADay: Word;
|
|
begin
|
|
DecodeDate(AValue, AYear, Result, ADay);
|
|
end;
|
|
|
|
function StartOfTheYear(const AValue: TDateTime): TDateTime;
|
|
begin
|
|
Result := EncodeDate(YearOf(AValue), 1, 1);
|
|
end;
|
|
|
|
function StartOfTheMonth(const AValue: TDateTime): TDateTime;
|
|
begin
|
|
Result := EncodeDate(YearOf(AValue), MonthOf(AValue), 1);
|
|
end;
|
|
|
|
function YearOf(const AValue: TDateTime): Word;
|
|
var
|
|
AMonth, ADay: Word;
|
|
begin
|
|
DecodeDate(AValue, Result, AMonth, ADay);
|
|
end;
|
|
|
|
const
|
|
DayMap: array [1..7] of Word = (7, 1, 2, 3, 4, 5, 6);
|
|
|
|
procedure DivMod(Dividend: Integer; Divisor: Word;
|
|
var Result, Remainder: Word);
|
|
asm
|
|
PUSH EBX
|
|
MOV EBX,EDX
|
|
MOV EDX,EAX
|
|
SHR EDX,16
|
|
DIV BX
|
|
MOV EBX,Remainder
|
|
MOV [ECX],AX
|
|
MOV [EBX],DX
|
|
POP EBX
|
|
end;
|
|
|
|
function DecodeDateFully(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean;
|
|
const
|
|
D1 = 365;
|
|
D4 = D1 * 4 + 1;
|
|
D100 = D4 * 25 - 1;
|
|
D400 = D100 * 4 + 1;
|
|
var
|
|
Y, M, D, I: Word;
|
|
T: Integer;
|
|
DayTable: PDayTable;
|
|
begin
|
|
T := DateTimeToTimeStamp(DateTime).Date;
|
|
if T <= 0 then
|
|
begin
|
|
Year := 0;
|
|
Month := 0;
|
|
Day := 0;
|
|
DOW := 0;
|
|
Result := False;
|
|
end else
|
|
begin
|
|
DOW := T mod 7 + 1;
|
|
Dec(T);
|
|
Y := 1;
|
|
while T >= D400 do
|
|
begin
|
|
Dec(T, D400);
|
|
Inc(Y, 400);
|
|
end;
|
|
DivMod(T, D100, I, D);
|
|
if I = 4 then
|
|
begin
|
|
Dec(I);
|
|
Inc(D, D100);
|
|
end;
|
|
Inc(Y, I * 100);
|
|
DivMod(D, D4, I, D);
|
|
Inc(Y, I * 4);
|
|
DivMod(D, D1, I, D);
|
|
if I = 4 then
|
|
begin
|
|
Dec(I);
|
|
Inc(D, D1);
|
|
end;
|
|
Inc(Y, I);
|
|
Result := IsLeapYear(Y);
|
|
DayTable := @MonthDays[Result];
|
|
M := 1;
|
|
while True do
|
|
begin
|
|
I := DayTable^[M];
|
|
if D < I then Break;
|
|
Dec(D, I);
|
|
Inc(M);
|
|
end;
|
|
Year := Y;
|
|
Month := M;
|
|
Day := D + 1;
|
|
end;
|
|
end;
|
|
|
|
procedure DecodeDateWeek(const AValue: TDateTime; out AYear, AWeekOfYear,
|
|
ADayOfWeek: Word);
|
|
var
|
|
ADayOfYear: Integer;
|
|
AMonth, ADay: Word;
|
|
AStart: TDateTime;
|
|
AStartDayOfWeek, AEndDayOfWeek: Word;
|
|
ALeap: Boolean;
|
|
begin
|
|
ALeap := DecodeDateFully(AValue, AYear, AMonth, ADay, ADayOfWeek);
|
|
ADayOfWeek := DayMap[ADayOfWeek];
|
|
AStart := EncodeDate(AYear, 1, 1);
|
|
ADayOfYear := Trunc(AValue - AStart + 1);
|
|
AStartDayOfWeek := DayOfTheWeek(AStart);
|
|
if AStartDayOfWeek in [DayFriday, DaySaturday, DaySunday] then
|
|
Dec(ADayOfYear, 8 - AStartDayOfWeek)
|
|
else
|
|
Inc(ADayOfYear, AStartDayOfWeek - 1);
|
|
if ADayOfYear <= 0 then
|
|
DecodeDateWeek(AStart - 1, AYear, AWeekOfYear, ADay)
|
|
else
|
|
begin
|
|
AWeekOfYear := ADayOfYear div 7;
|
|
if ADayOfYear mod 7 <> 0 then
|
|
Inc(AWeekOfYear);
|
|
if AWeekOfYear > 52 then
|
|
begin
|
|
AEndDayOfWeek := AStartDayOfWeek;
|
|
if ALeap then
|
|
begin
|
|
if AEndDayOfWeek = DaySunday then
|
|
AEndDayOfWeek := DayMonday
|
|
else
|
|
Inc(AEndDayOfWeek);
|
|
end;
|
|
if AEndDayOfWeek in [DayMonday, DayTuesday, DayWednesday] then
|
|
begin
|
|
Inc(AYear);
|
|
AWeekOfYear := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function EncodeDateWeek(const AYear, AWeekOfYear: Word;
|
|
const ADayOfWeek: Word): TDateTime;
|
|
var
|
|
ADayOfYear: Integer;
|
|
AStartDayOfWeek: Word;
|
|
begin
|
|
Result := EncodeDate(AYear, 1, 1);
|
|
AStartDayOfWeek := DayOfTheWeek(Result);
|
|
ADayOfYear := (AWeekOfYear - 1) * 7 + ADayOfWeek - 1;
|
|
if AStartDayOfWeek in [DayFriday, DaySaturday, DaySunday] then
|
|
Inc(ADayOfYear, 8 - AStartDayOfWeek)
|
|
else
|
|
Dec(ADayOfYear, AStartDayOfWeek - 1);
|
|
Result := Result + ADayOfYear;
|
|
end;
|
|
|
|
function SpanOfNowAndThen(const ANow, AThen: TDateTime): TDateTime;
|
|
begin
|
|
if ANow < AThen then
|
|
Result := AThen - ANow
|
|
else
|
|
Result := ANow - AThen;
|
|
end;
|
|
|
|
function DaySpan(const ANow, AThen: TDateTime): Double;
|
|
begin
|
|
Result := SpanOfNowAndThen(ANow, AThen);
|
|
end;
|
|
|
|
function YearSpan(const ANow, AThen: TDateTime): Double;
|
|
begin
|
|
Result := DaySpan(ANow, AThen) / ApproxDaysPerYear;
|
|
end;
|
|
|
|
function MonthSpan(const ANow, AThen: TDateTime): Double;
|
|
begin
|
|
Result := DaySpan(ANow, AThen) / ApproxDaysPerMonth;
|
|
end;
|
|
|
|
function WeekSpan(const ANow, AThen: TDateTime): Double;
|
|
begin
|
|
Result := DaySpan(ANow, AThen) / DaysPerWeek;
|
|
end;
|
|
|
|
function YearsBetween(const ANow, AThen: TDateTime): Integer;
|
|
begin
|
|
Result := Trunc(YearSpan(ANow, AThen));
|
|
end;
|
|
|
|
function MonthsBetween(const ANow, AThen: TDateTime): Integer;
|
|
begin
|
|
Result := Trunc(MonthSpan(ANow, AThen));
|
|
end;
|
|
|
|
function WeeksBetween(const ANow, AThen: TDateTime): Integer;
|
|
begin
|
|
Result := Trunc(WeekSpan(ANow, AThen));
|
|
end;
|
|
|
|
function DaysBetween(const ANow, AThen: TDateTime): Integer;
|
|
begin
|
|
Result := Trunc(DaySpan(ANow, AThen));
|
|
end;
|
|
|
|
function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer): TDateTime;
|
|
var
|
|
Year, Month, Day: Word;
|
|
begin
|
|
DecodeDate(DateTime, Year, Month, Day);
|
|
IncAMonth(Year, Month, Day, NumberOfMonths);
|
|
Result := EncodeDate(Year, Month, Day);
|
|
ReplaceTime(Result, DateTime);
|
|
end;
|
|
|
|
function IncYear(const AValue: TDateTime;
|
|
const ANumberOfYears: Integer): TDateTime;
|
|
begin
|
|
Result := IncMonth(AValue, ANumberOfYears * MonthsPerYear);
|
|
end;
|
|
|
|
function IncWeek(const AValue: TDateTime;
|
|
const ANumberOfWeeks: Integer): TDateTime;
|
|
begin
|
|
Result := AValue + ANumberOfWeeks * DaysPerWeek;
|
|
end;
|
|
|
|
function IncDay(const AValue: TDateTime;
|
|
const ANumberOfDays: Integer): TDateTime;
|
|
begin
|
|
Result := AValue + ANumberOfDays;
|
|
end;
|
|
|
|
function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;
|
|
begin
|
|
Result := ((AValue * HoursPerDay) + ANumberOfHours) / HoursPerDay;
|
|
end;
|
|
|
|
function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;
|
|
begin
|
|
Result := ((AValue * MinsPerDay) + ANumberOfMinutes) / MinsPerDay;
|
|
end;
|
|
|
|
procedure DecodeDateMonthWeek(const AValue: TDateTime;
|
|
out AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word);
|
|
var
|
|
LDay, LDaysInMonth: Word;
|
|
LDayOfMonth: Integer;
|
|
LStart: TDateTime;
|
|
LStartDayOfWeek, LEndOfMonthDayOfWeek: Word;
|
|
begin
|
|
DecodeDateFully(AValue, AYear, AMonth, LDay, ADayOfWeek);
|
|
ADayOfWeek := DayMap[ADayOfWeek];
|
|
LStart := EncodeDate(AYear, AMonth, 1);
|
|
LStartDayOfWeek := DayOfTheWeek(LStart);
|
|
LDayOfMonth := LDay;
|
|
if LStartDayOfWeek in [DayFriday, DaySaturday, DaySunday] then
|
|
Dec(LDayOfMonth, 8 - LStartDayOfWeek)
|
|
else
|
|
Inc(LDayOfMonth, LStartDayOfWeek - 1);
|
|
if LDayOfMonth <= 0 then
|
|
DecodeDateMonthWeek(LStart - 1, AYear, AMonth, AWeekOfMonth, LDay)
|
|
else
|
|
begin
|
|
AWeekOfMonth := LDayOfMonth div 7;
|
|
if LDayOfMonth mod 7 <> 0 then
|
|
Inc(AWeekOfMonth);
|
|
LDaysInMonth := DaysInAMonth(AYear, AMonth);
|
|
LEndOfMonthDayOfWeek := DayOfTheWeek(EncodeDate(AYear, AMonth, LDaysInMonth));
|
|
if (LEndOfMonthDayOfWeek in [DayMonday, DayTuesday, DayWednesday]) and
|
|
(LDaysInMonth - LDay < LEndOfMonthDayOfWeek) then
|
|
begin
|
|
Inc(AMonth);
|
|
if AMonth = 13 then
|
|
begin
|
|
AMonth := 1;
|
|
Inc(AYear);
|
|
end;
|
|
AWeekOfMonth := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function WeekOfTheMonth(const AValue: TDateTime): Word;
|
|
var
|
|
LYear, LMonth, LDayOfWeek: Word;
|
|
begin
|
|
DecodeDateMonthWeek(AValue, LYear, LMonth, Result, LDayOfWeek);
|
|
end;
|
|
|
|
function WeekOf(AValue: TDateTime): Word;
|
|
var
|
|
AYear, ADay: Word;
|
|
begin
|
|
DecodeDateWeek(AValue, AYear, Result, ADay);
|
|
end;
|
|
|
|
function WeekOfTheYear(const AValue: TDateTime): Word;
|
|
var
|
|
AYear, ADayOfWeek: Word;
|
|
begin
|
|
DecodeDateWeek(AValue, AYear, Result, ADayOfWeek);
|
|
end;
|
|
|
|
function DayOfTheYear(AValue: TDateTime): Word;
|
|
begin
|
|
Result := Trunc(AValue - StartOfTheYear(AValue)) + 1;
|
|
end;
|
|
|
|
function EndOfTheYear(AValue: TDateTime): TDateTime;
|
|
begin
|
|
Result := EncodeDateTime(YearOf(AValue), 12, 31, 23, 59, 59, 999)
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function StrToDateDef(const ADateStr: string; ADefDate: TDateTime): TDateTime;
|
|
begin
|
|
try
|
|
Result := StrToDate(ADateStr)
|
|
except
|
|
Result := ADefDate
|
|
end;
|
|
end;
|
|
|
|
function SICompare(List: TStringList; Index1, Index2: Integer): Integer;
|
|
var
|
|
S1, S2: string;
|
|
begin
|
|
S1 := List[Index1];
|
|
S2 := List[Index2];
|
|
if Length(S1) > Length(S2) then
|
|
Result := -1
|
|
else
|
|
if Length(S1) < Length(S2) then
|
|
Result := 1
|
|
else
|
|
Result := -AnsiCompareText(S1, S2);
|
|
end;
|
|
|
|
function SmartTextToDate(const AText: string; var ADate: TDateTime): Boolean;
|
|
|
|
function GetSmartInputKind(const AText: string;
|
|
var Kind: TcxDateEditSmartInput): Boolean;
|
|
var
|
|
I: TcxDateEditSmartInput;
|
|
J: Integer;
|
|
S: string;
|
|
begin
|
|
Result := False;
|
|
with TStringList.Create do
|
|
try
|
|
for I := Low(TcxDateEditSmartInput) to High(TcxDateEditSmartInput) do
|
|
AddObject(scxDateEditSmartInput[I], TObject(I));
|
|
CustomSort(SICompare);
|
|
for J := 0 to Count - 1 do
|
|
begin
|
|
S := Strings[J];
|
|
if AnsiCompareText(S, Copy(AText, 1, Length(S))) = 0 then
|
|
begin
|
|
Kind := TcxDateEditSmartInput(Objects[J]);
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: TcxDateEditSmartInput;
|
|
L, Delta: Integer;
|
|
S: string;
|
|
Y, M, D: Word;
|
|
|
|
begin
|
|
InitSmartInputConsts;
|
|
Result := False;
|
|
S := Trim(AText);
|
|
if GetSmartInputKind(S, I) then
|
|
begin
|
|
case I of
|
|
deiToday:
|
|
ADate := Date;
|
|
deiYesterday:
|
|
ADate := Date - 1;
|
|
deiTomorrow:
|
|
ADate := Date + 1;
|
|
deiSunday, deiMonday, deiTuesday, deiWednesday, deiThursday, deiFriday, deiSaturday:
|
|
begin
|
|
ADate := Date;
|
|
Delta := Integer(I) - Integer(deiSunday) + 1 - DayOfWeek(ADate);
|
|
if Delta >= 0 then
|
|
ADate := ADate + Delta
|
|
else
|
|
ADate := ADate + 7 + Delta;
|
|
end;
|
|
deiFirst..deiSeventh:
|
|
begin
|
|
ADate := Date;
|
|
Delta := DayOfWeekOffset(ADate) - (Integer(I) - Integer(deiFirst));
|
|
ADate := ADate - Delta;
|
|
end;
|
|
deiBOM:
|
|
begin
|
|
DecodeDate(Date, Y, M, D);
|
|
ADate := EncodeDate(Y, M, 1);
|
|
end;
|
|
deiEOM:
|
|
begin
|
|
DecodeDate(Date, Y, M, D);
|
|
ADate := EncodeDate(Y, M, MonthDays[IsLeapYear(Y), M]);
|
|
end;
|
|
deiNow:
|
|
ADate := Now;
|
|
end;
|
|
L := Length(scxDateEditSmartInput[I]);
|
|
S := Trim(Copy(AText, L + 1, Length(AText)));
|
|
if (Length(S) >= 2) and ((S[1] = '+') or (S[1] = '-')) then
|
|
begin
|
|
if S[1] = '+' then L := 1
|
|
else L := -1;
|
|
S := Trim(Copy(S, 2, Length(S)));
|
|
try
|
|
ADate := ADate + L * StrToInt(S);
|
|
except
|
|
on EConvertError do;
|
|
end;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
if not Result and Assigned(SmartTextToDateFunc) then
|
|
Result := SmartTextToDateFunc(AText, ADate);
|
|
end;
|
|
|
|
function TextToDateEx(AText: string; var ADate: TDateTime): Boolean;
|
|
var
|
|
ADay, AMonth, AYear: Word;
|
|
begin
|
|
try
|
|
AText := Trim(AText);
|
|
if AText = '' then
|
|
Result := False
|
|
else
|
|
begin
|
|
// Smart Date
|
|
if not SmartTextToDate(AText, ADate) then
|
|
begin
|
|
CorrectTextForDateTimeConversion(AText,
|
|
not cxFormatController.UseDelphiDateTimeFormats);
|
|
if cxFormatController.UseDelphiDateTimeFormats then
|
|
ADate := StrToDateTime(AText)
|
|
else
|
|
ADate := VarToDateTime(AText);
|
|
end;
|
|
Result := (ADate < MaxInt) and (ADate > -MaxInt - 1);
|
|
if Result then
|
|
begin
|
|
DecodeDate(ADate, AYear, AMonth, ADay);
|
|
Result := (ADay > 0) and (AYear <= MaxYear);
|
|
end;
|
|
end;
|
|
except
|
|
Result := False;
|
|
ADate := NullDate;
|
|
end;
|
|
end;
|
|
|
|
function cxDateTimeToText(ADate: TDateTime; AFourDigitYearNeeded: Boolean = False; AUseDelphiDateTimeFormats: Boolean = False): string;
|
|
|
|
function GetDateTimeFormat: string;
|
|
var
|
|
I: Integer;
|
|
S: string;
|
|
begin
|
|
if AUseDelphiDateTimeFormats then
|
|
begin
|
|
Result := ShortDateFormat;
|
|
if TimeOf(ADate) <> 0 then
|
|
Result := Result + ' ' + LongTimeFormat;
|
|
end
|
|
else
|
|
Result := cxGetLocaleStr(LOCALE_SSHORTDATE);
|
|
if AFourDigitYearNeeded then
|
|
begin
|
|
S := LowerCase(Result);
|
|
if (Pos('yyy', S) = 0) and (Pos('yy', S) > 0) then
|
|
begin
|
|
I := Pos('yy', S);
|
|
Insert(Result[I], Result, I + 2);
|
|
Insert(Result[I], Result, I + 3);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
SystemTime: TSystemTime;
|
|
PS: PChar;
|
|
begin
|
|
if ADate = NullDate then
|
|
Result := ''
|
|
else
|
|
if AUseDelphiDateTimeFormats then
|
|
DateTimeToString(Result, GetDateTimeFormat, ADate)
|
|
else
|
|
begin
|
|
DateTimeToSystemTime(ADate, SystemTime);
|
|
GetMem(PS, 100);
|
|
try
|
|
if GetDateFormat(GetThreadLocale, 0, @SystemTime,
|
|
PAnsiChar(GetDateTimeFormat), PS, 100) <> 0 then
|
|
begin
|
|
Result := PS;
|
|
if TimeOf(ADate) <> 0 then
|
|
begin
|
|
GetTimeFormat(GetThreadLocale, 0, @SystemTime, nil, PS, 100);
|
|
Result := Result + ' ' + PS;
|
|
end;
|
|
end
|
|
else
|
|
try
|
|
Result := VarFromDateTime(ADate);
|
|
except
|
|
on EVariantError do
|
|
Result := '';
|
|
end;
|
|
finally
|
|
FreeMem(PS, 100);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function DateTimeToText(ADate: TDateTime; AFourDigitYearNeeded: Boolean = False): string;
|
|
begin
|
|
Result := cxDateTimeToText(ADate, AFourDigitYearNeeded, cxFormatController.UseDelphiDateTimeFormats);
|
|
end;
|
|
|
|
function DateTimeToTextEx(const ADate: TDateTime; AIsMasked: Boolean;
|
|
AIsDateTimeEdit: Boolean = False; AFourDigitYearNeeded: Boolean = False): string;
|
|
begin
|
|
if ADate = NullDate then
|
|
Result := ''
|
|
else
|
|
begin
|
|
if AIsMasked then
|
|
begin
|
|
if AIsDateTimeEdit then
|
|
Result := FormatDateTime(cxFormatController.MaskedDateTimeEditFormat, ADate)
|
|
else
|
|
Result := FormatDateTime(cxFormatController.MaskedDateEditFormat, DateOf(ADate));
|
|
end
|
|
else
|
|
Result := DateTimeToText(ADate, AFourDigitYearNeeded);
|
|
end;
|
|
end;
|
|
|
|
function cxMinDateTime: Double;
|
|
begin
|
|
Result := EncodeDate(MinYear, 1, 1);
|
|
end;
|
|
|
|
function cxStrToDateTime(S: string; AUseOleDateFormat: Boolean;
|
|
out ADate: TDateTime): Boolean;
|
|
begin
|
|
Result := False;
|
|
ADate := NullDate;
|
|
try
|
|
CorrectTextForDateTimeConversion(S, AUseOleDateFormat);
|
|
if AUseOleDateFormat then
|
|
ADate := VarToDateTime(S)
|
|
else
|
|
ADate := StrToDateTime(S);
|
|
Result := True;
|
|
except
|
|
on Exception(*EConvertError*) do
|
|
ADate := NullDate;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|