git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@12 7f62d464-2af8-f54e-996c-e91b33f51cbe
764 lines
18 KiB
ObjectPascal
764 lines
18 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvDateUtil.PAS, released on 2002-07-04.
|
|
|
|
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 2001,2002 SGB Software
|
|
All Rights Reserved.
|
|
|
|
Last Modified: 2002-07-04
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
|
|
{$I JVCL.INC}
|
|
|
|
unit JvDateUtil;
|
|
|
|
interface
|
|
|
|
{$IFDEF COMPILER6}
|
|
uses
|
|
RTLConsts;
|
|
{$ELSE
|
|
{$IFDEF COMPILER7_UP}
|
|
uses
|
|
SysConst;
|
|
{$ENDIF}
|
|
|
|
function CurrentYear: Word;
|
|
function IsLeapYear(AYear: Integer): Boolean;
|
|
function DaysPerMonth(AYear, AMonth: Integer): Integer;
|
|
function FirstDayOfPrevMonth: TDateTime;
|
|
function LastDayOfPrevMonth: TDateTime;
|
|
function FirstDayOfNextMonth: TDateTime;
|
|
function ExtractDay(ADate: TDateTime): Word;
|
|
function ExtractMonth(ADate: TDateTime): Word;
|
|
function ExtractYear(ADate: TDateTime): Word;
|
|
function IncDate(ADate: TDateTime; Days, Months, Years: Integer): TDateTime;
|
|
function IncDay(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
function IncMonth(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
function IncYear(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
function ValidDate(ADate: TDateTime): Boolean;
|
|
procedure DateDiff(Date1, Date2: TDateTime; var Days, Months, Years: Word);
|
|
function MonthsBetween(Date1, Date2: TDateTime): Double;
|
|
function DaysInPeriod(Date1, Date2: TDateTime): Longint;
|
|
{ Count days between Date1 and Date2 + 1, so if Date1 = Date2 result = 1 }
|
|
function DaysBetween(Date1, Date2: TDateTime): Longint;
|
|
{ The same as previous but if Date2 < Date1 result = 0 }
|
|
function IncTime(ATime: TDateTime; Hours, Minutes, Seconds, MSecs: Integer): TDateTime;
|
|
function IncHour(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
function IncMinute(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
function IncSecond(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
function IncMSec(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
function CutTime(ADate: TDateTime): TDateTime; { Set time to 00:00:00:00 }
|
|
|
|
type
|
|
TDateOrder = (doMDY, doDMY, doYMD);
|
|
TDayOfWeekName = (Sun, Mon, Tue, Wed, Thu, Fri, Sat);
|
|
TDaysOfWeek = set of TDayOfWeekName;
|
|
|
|
{ String to date conversions }
|
|
function GetDateOrder(const DateFormat: string): TDateOrder;
|
|
function MonthFromName(const S: string; MaxLen: Byte): Byte;
|
|
function StrToDateDef(const S: string; Default: TDateTime): TDateTime;
|
|
function StrToDateFmt(const DateFormat, S: string): TDateTime;
|
|
function StrToDateFmtDef(const DateFormat, S: string; Default: TDateTime): TDateTime;
|
|
function DefDateFormat(FourDigitYear: Boolean): string;
|
|
function DefDateMask(BlanksChar: Char; FourDigitYear: Boolean): string;
|
|
|
|
{$IFDEF WIN32}
|
|
function FormatLongDate(Value: TDateTime): string;
|
|
function FormatLongDateTime(Value: TDateTime): string;
|
|
{$ENDIF}
|
|
|
|
const
|
|
DefaultDateOrder = doDMY;
|
|
|
|
{$IFDEF USE_FOUR_DIGIT_YEAR}
|
|
var
|
|
FourDigitYear: Boolean;
|
|
{$ELSE}
|
|
function FourDigitYear: Boolean;
|
|
{$ENDIF USE_FOUR_DIGIT_YEAR}
|
|
|
|
const
|
|
CenturyOffset: Byte = 60;
|
|
{$IFDEF WIN32}
|
|
NullDate: TDateTime = {-693594} 0;
|
|
{$ELSE}
|
|
NullDate: TDateTime = 0;
|
|
{$ENDIF}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF WIN32}
|
|
Windows,
|
|
{$ENDIF}
|
|
SysUtils, Consts,
|
|
JvStrUtils;
|
|
|
|
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
|
|
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 FirstDayOfNextMonth: TDateTime;
|
|
var
|
|
Year, Month, Day: Word;
|
|
begin
|
|
DecodeDate(Date, Year, Month, Day);
|
|
Day := 1;
|
|
if Month < 12 then
|
|
Inc(Month)
|
|
else
|
|
begin
|
|
Inc(Year);
|
|
Month := 1;
|
|
end;
|
|
Result := EncodeDate(Year, Month, Day);
|
|
end;
|
|
|
|
function FirstDayOfPrevMonth: TDateTime;
|
|
var
|
|
Year, Month, Day: Word;
|
|
begin
|
|
DecodeDate(Date, Year, Month, Day);
|
|
Day := 1;
|
|
if Month > 1 then
|
|
Dec(Month)
|
|
else
|
|
begin
|
|
Dec(Year);
|
|
Month := 12;
|
|
end;
|
|
Result := EncodeDate(Year, Month, Day);
|
|
end;
|
|
|
|
function LastDayOfPrevMonth: TDateTime;
|
|
var
|
|
D: TDateTime;
|
|
Year, Month, Day: Word;
|
|
begin
|
|
D := FirstDayOfPrevMonth;
|
|
DecodeDate(D, Year, Month, Day);
|
|
Day := DaysPerMonth(Year, Month);
|
|
Result := EncodeDate(Year, Month, Day);
|
|
end;
|
|
|
|
function ExtractDay(ADate: TDateTime): Word;
|
|
var
|
|
M, Y: Word;
|
|
begin
|
|
DecodeDate(ADate, Y, M, Result);
|
|
end;
|
|
|
|
function ExtractMonth(ADate: TDateTime): Word;
|
|
var
|
|
D, Y: Word;
|
|
begin
|
|
DecodeDate(ADate, Y, Result, D);
|
|
end;
|
|
|
|
function ExtractYear(ADate: TDateTime): Word;
|
|
var
|
|
D, M: Word;
|
|
begin
|
|
DecodeDate(ADate, Result, M, D);
|
|
end;
|
|
|
|
function IncDate(ADate: TDateTime; Days, Months, Years: Integer): TDateTime;
|
|
var
|
|
D, M, Y: Word;
|
|
Day, Month, Year: Longint;
|
|
begin
|
|
DecodeDate(ADate, Y, M, D);
|
|
Year := Y;
|
|
Month := M;
|
|
Day := D;
|
|
Inc(Year, Years);
|
|
Inc(Year, Months div 12);
|
|
Inc(Month, Months mod 12);
|
|
if Month < 1 then
|
|
begin
|
|
Inc(Month, 12);
|
|
Dec(Year);
|
|
end
|
|
else if Month > 12 then
|
|
begin
|
|
Dec(Month, 12);
|
|
Inc(Year);
|
|
end;
|
|
if Day > DaysPerMonth(Year, Month) then
|
|
Day := DaysPerMonth(Year, Month);
|
|
Result := EncodeDate(Year, Month, Day) + Days + Frac(ADate);
|
|
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 IncDay(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := ADate + Delta;
|
|
end;
|
|
|
|
function IncMonth(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncDate(ADate, 0, Delta, 0);
|
|
end;
|
|
|
|
function IncYear(ADate: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncDate(ADate, 0, 0, Delta);
|
|
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;
|
|
|
|
function IsValidDate(Y, M, D: Word): Boolean;
|
|
begin
|
|
Result := (Y >= 1) and (Y <= 9999) and (M >= 1) and (M <= 12) and
|
|
(D >= 1) and (D <= DaysPerMonth(Y, M));
|
|
end;
|
|
|
|
function ValidDate(ADate: TDateTime): Boolean;
|
|
var
|
|
Year, Month, Day: Word;
|
|
begin
|
|
try
|
|
DecodeDate(ADate, Year, Month, Day);
|
|
Result := IsValidDate(Year, Month, Day);
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function DaysInPeriod(Date1, Date2: TDateTime): Longint;
|
|
begin
|
|
if ValidDate(Date1) and ValidDate(Date2) then
|
|
Result := Abs(Trunc(Date2) - Trunc(Date1)) + 1
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function DaysBetween(Date1, Date2: TDateTime): Longint;
|
|
begin
|
|
Result := Trunc(Date2) - Trunc(Date1) + 1;
|
|
if Result < 0 then
|
|
Result := 0;
|
|
end;
|
|
|
|
function IncTime(ATime: TDateTime; Hours, Minutes, Seconds,
|
|
MSecs: Integer): TDateTime;
|
|
begin
|
|
Result := ATime + (Hours div 24) + (((Hours mod 24) * 3600000 +
|
|
Minutes * 60000 + Seconds * 1000 + MSecs) / MSecsPerDay);
|
|
if Result < 0 then
|
|
Result := Result + 1;
|
|
end;
|
|
|
|
function IncHour(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncTime(ATime, Delta, 0, 0, 0);
|
|
end;
|
|
|
|
function IncMinute(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncTime(ATime, 0, Delta, 0, 0);
|
|
end;
|
|
|
|
function IncSecond(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncTime(ATime, 0, 0, Delta, 0);
|
|
end;
|
|
|
|
function IncMSec(ATime: TDateTime; Delta: Integer): TDateTime;
|
|
begin
|
|
Result := IncTime(ATime, 0, 0, 0, Delta);
|
|
end;
|
|
|
|
function CutTime(ADate: TDateTime): TDateTime;
|
|
begin
|
|
Result := Trunc(ADate);
|
|
end;
|
|
|
|
function CurrentYear: Word;
|
|
var
|
|
SystemTime: TSystemTime;
|
|
begin
|
|
GetLocalTime(SystemTime);
|
|
Result := SystemTime.wYear;
|
|
end;
|
|
|
|
{ String to date conversions. Copied from SYSUTILS.PAS unit. }
|
|
|
|
procedure ScanBlanks(const S: string; var Pos: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := Pos;
|
|
while (I <= Length(S)) and (S[I] = ' ') do
|
|
Inc(I);
|
|
Pos := I;
|
|
end;
|
|
|
|
function ScanNumber(const S: string; MaxLength: Integer; var Pos: Integer;
|
|
var Number: Longint): Boolean;
|
|
var
|
|
I: Integer;
|
|
N: Word;
|
|
begin
|
|
Result := False;
|
|
ScanBlanks(S, Pos);
|
|
I := Pos;
|
|
N := 0;
|
|
while (I <= Length(S)) and (Longint(I - Pos) < MaxLength) and
|
|
(S[I] in ['0'..'9']) and (N < 1000) do
|
|
begin
|
|
N := N * 10 + (Ord(S[I]) - Ord('0'));
|
|
Inc(I);
|
|
end;
|
|
if I > Pos then
|
|
begin
|
|
Pos := I;
|
|
Number := N;
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
function ScanChar(const S: string; var Pos: Integer; Ch: Char): Boolean;
|
|
begin
|
|
Result := False;
|
|
ScanBlanks(S, Pos);
|
|
if (Pos <= Length(S)) and (S[Pos] = Ch) then
|
|
begin
|
|
Inc(Pos);
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF COMPILER3_UP}
|
|
|
|
procedure ScanToNumber(const S: string; var Pos: Integer);
|
|
begin
|
|
while (Pos <= Length(S)) and not (S[Pos] in ['0'..'9']) do
|
|
begin
|
|
if S[Pos] in LeadBytes then
|
|
Inc(Pos);
|
|
Inc(Pos);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function GetDateOrder(const DateFormat: string): TDateOrder;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := DefaultDateOrder;
|
|
I := 1;
|
|
while I <= Length(DateFormat) do
|
|
begin
|
|
case Chr(Ord(DateFormat[I]) and $DF) of
|
|
{$IFDEF COMPILER3_UP}
|
|
'E':
|
|
Result := doYMD;
|
|
{$ENDIF}
|
|
'Y':
|
|
Result := doYMD;
|
|
'M':
|
|
Result := doMDY;
|
|
'D':
|
|
Result := doDMY;
|
|
else
|
|
Inc(I);
|
|
Continue;
|
|
end;
|
|
Exit;
|
|
end;
|
|
Result := DefaultDateOrder; { default }
|
|
end;
|
|
|
|
function CurrentMonth: Word;
|
|
var
|
|
SystemTime: TSystemTime;
|
|
begin
|
|
GetLocalTime(SystemTime);
|
|
Result := SystemTime.wMonth;
|
|
end;
|
|
|
|
{Modified}
|
|
|
|
function ExpandYear(Year: Integer): Integer;
|
|
var
|
|
N: Longint;
|
|
begin
|
|
if Year = -1 then
|
|
Result := CurrentYear
|
|
else
|
|
begin
|
|
Result := Year;
|
|
if Result < 100 then
|
|
begin
|
|
N := CurrentYear - CenturyOffset;
|
|
Inc(Result, N div 100 * 100);
|
|
if (CenturyOffset > 0) and (Result < N) then
|
|
Inc(Result, 100);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function ScanDate(const S, DateFormat: string; var Pos: Integer;
|
|
var Y, M, D: Integer): Boolean;
|
|
var
|
|
DateOrder: TDateOrder;
|
|
N1, N2, N3: Longint;
|
|
begin
|
|
Result := False;
|
|
Y := 0;
|
|
M := 0;
|
|
D := 0;
|
|
DateOrder := GetDateOrder(DateFormat);
|
|
{$IFDEF COMPILER3_UP}
|
|
if ShortDateFormat[1] = 'g' then { skip over prefix text }
|
|
ScanToNumber(S, Pos);
|
|
{$ENDIF COMPILER3_UP}
|
|
if not (ScanNumber(S, MaxInt, Pos, N1) and ScanChar(S, Pos, DateSeparator) and
|
|
ScanNumber(S, MaxInt, Pos, N2)) then
|
|
Exit;
|
|
if ScanChar(S, Pos, DateSeparator) then
|
|
begin
|
|
if not ScanNumber(S, MaxInt, Pos, N3) then
|
|
Exit;
|
|
case DateOrder of
|
|
doMDY:
|
|
begin
|
|
Y := N3;
|
|
M := N1;
|
|
D := N2;
|
|
end;
|
|
doDMY:
|
|
begin
|
|
Y := N3;
|
|
M := N2;
|
|
D := N1;
|
|
end;
|
|
doYMD:
|
|
begin
|
|
Y := N1;
|
|
M := N2;
|
|
D := N3;
|
|
end;
|
|
end;
|
|
Y := ExpandYear(Y);
|
|
end
|
|
else
|
|
begin
|
|
Y := CurrentYear;
|
|
if DateOrder = doDMY then
|
|
begin
|
|
D := N1;
|
|
M := N2;
|
|
end
|
|
else
|
|
begin
|
|
M := N1;
|
|
D := N2;
|
|
end;
|
|
end;
|
|
ScanChar(S, Pos, DateSeparator);
|
|
ScanBlanks(S, Pos);
|
|
{$IFDEF COMPILER3_UP}
|
|
if SysLocale.FarEast and (System.Pos('ddd', ShortDateFormat) <> 0) then
|
|
begin { ignore trailing text }
|
|
if ShortTimeFormat[1] in ['0'..'9'] then { stop at time digit }
|
|
ScanToNumber(S, Pos)
|
|
else { stop at time prefix }
|
|
repeat
|
|
while (Pos <= Length(S)) and (S[Pos] <> ' ') do
|
|
Inc(Pos);
|
|
ScanBlanks(S, Pos);
|
|
until (Pos > Length(S)) or
|
|
(AnsiCompareText(TimeAMString, Copy(S, Pos, Length(TimeAMString))) = 0) or
|
|
(AnsiCompareText(TimePMString, Copy(S, Pos, Length(TimePMString))) = 0);
|
|
end;
|
|
{$ENDIF COMPILER3_UP}
|
|
Result := IsValidDate(Y, M, D) and (Pos > Length(S));
|
|
end;
|
|
|
|
function MonthFromName(const S: string; MaxLen: Byte): Byte;
|
|
begin
|
|
if Length(S) > 0 then
|
|
for Result := 1 to 12 do
|
|
begin
|
|
if (Length(LongMonthNames[Result]) > 0) and
|
|
(AnsiCompareText(Copy(S, 1, MaxLen),
|
|
Copy(LongMonthNames[Result], 1, MaxLen)) = 0) then
|
|
Exit;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure ExtractMask(const Format, S: string; Ch: Char; Cnt: Integer;
|
|
var I: Integer; Blank, Default: Integer);
|
|
var
|
|
Tmp: string[20];
|
|
J, L: Integer;
|
|
begin
|
|
I := Default;
|
|
Ch := UpCase(Ch);
|
|
L := Length(Format);
|
|
if Length(S) < L then
|
|
L := Length(S)
|
|
else if Length(S) > L then
|
|
Exit;
|
|
J := Pos(MakeStr(Ch, Cnt), AnsiUpperCase(Format));
|
|
if J <= 0 then
|
|
Exit;
|
|
Tmp := '';
|
|
while (UpCase(Format[J]) = Ch) and (J <= L) do
|
|
begin
|
|
if S[J] <> ' ' then
|
|
Tmp := Tmp + S[J];
|
|
Inc(J);
|
|
end;
|
|
if Tmp = '' then
|
|
I := Blank
|
|
else if Cnt > 1 then
|
|
begin
|
|
I := MonthFromName(Tmp, Length(Tmp));
|
|
if I = 0 then
|
|
I := -1;
|
|
end
|
|
else
|
|
I := StrToIntDef(Tmp, -1);
|
|
end;
|
|
|
|
function ScanDateStr(const Format, S: string; var D, M, Y: Integer): Boolean;
|
|
var
|
|
Pos: Integer;
|
|
begin
|
|
ExtractMask(Format, S, 'm', 3, M, -1, 0); { short month name? }
|
|
if M = 0 then ExtractMask(Format, S, 'm', 1, M, -1, 0);
|
|
ExtractMask(Format, S, 'd', 1, D, -1, 1);
|
|
ExtractMask(Format, S, 'y', 1, Y, -1, CurrentYear);
|
|
if M = -1 then
|
|
M := CurrentMonth;
|
|
Y := ExpandYear(Y);
|
|
Result := IsValidDate(Y, M, D);
|
|
if not Result then
|
|
begin
|
|
Pos := 1;
|
|
Result := ScanDate(S, Format, Pos, Y, M, D);
|
|
end;
|
|
end;
|
|
|
|
function InternalStrToDate(const DateFormat, S: string;
|
|
var Date: TDateTime): Boolean;
|
|
var
|
|
D, M, Y: Integer;
|
|
begin
|
|
if S = '' then
|
|
begin
|
|
Date := NullDate;
|
|
Result := True;
|
|
end
|
|
else
|
|
begin
|
|
Result := ScanDateStr(DateFormat, S, D, M, Y);
|
|
if Result then
|
|
try
|
|
Date := EncodeDate(Y, M, D);
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function StrToDateFmt(const DateFormat, S: string): TDateTime;
|
|
begin
|
|
if not InternalStrToDate(DateFormat, S, Result) then
|
|
{$IFDEF COMPILER3_UP}
|
|
raise EConvertError.CreateFmt(SInvalidDate, [S]);
|
|
{$ELSE}
|
|
raise EConvertError.CreateFmt(LoadStr(SInvalidDate), [S]);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function StrToDateDef(const S: string; Default: TDateTime): TDateTime;
|
|
begin
|
|
if not InternalStrToDate(ShortDateFormat, S, Result) then
|
|
Result := Trunc(Default);
|
|
end;
|
|
|
|
function StrToDateFmtDef(const DateFormat, S: string; Default: TDateTime): TDateTime;
|
|
begin
|
|
if not InternalStrToDate(DateFormat, S, Result) then
|
|
Result := Trunc(Default);
|
|
end;
|
|
|
|
function DefDateFormat(FourDigitYear: Boolean): string;
|
|
begin
|
|
if FourDigitYear then
|
|
begin
|
|
case GetDateOrder(ShortDateFormat) of
|
|
doMDY:
|
|
Result := 'MM/DD/YYYY';
|
|
doDMY:
|
|
Result := 'DD/MM/YYYY';
|
|
doYMD:
|
|
Result := 'YYYY/MM/DD';
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
case GetDateOrder(ShortDateFormat) of
|
|
doMDY:
|
|
Result := 'MM/DD/YY';
|
|
doDMY:
|
|
Result := 'DD/MM/YY';
|
|
doYMD:
|
|
Result := 'YY/MM/DD';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function DefDateMask(BlanksChar: Char; FourDigitYear: Boolean): string;
|
|
begin
|
|
if FourDigitYear then
|
|
begin
|
|
case GetDateOrder(ShortDateFormat) of
|
|
doMDY, doDMY:
|
|
Result := '!99/99/9999;1;';
|
|
doYMD:
|
|
Result := '!9999/99/99;1;';
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
case GetDateOrder(ShortDateFormat) of
|
|
doMDY, doDMY:
|
|
Result := '!99/99/99;1;';
|
|
doYMD:
|
|
Result := '!99/99/99;1;';
|
|
end;
|
|
end;
|
|
if Result <> '' then
|
|
Result := Result + BlanksChar;
|
|
end;
|
|
|
|
{$IFDEF WIN32}
|
|
|
|
function FormatLongDate(Value: TDateTime): string;
|
|
var
|
|
Buffer: array[0..1023] of Char;
|
|
SystemTime: TSystemTime;
|
|
begin
|
|
{$IFDEF COMPILER3_UP}
|
|
DateTimeToSystemTime(Value, SystemTime);
|
|
{$ELSE}
|
|
with SystemTime do
|
|
begin
|
|
DecodeDate(Value, wYear, wMonth, wDay);
|
|
DecodeTime(Value, wHour, wMinute, wSecond, wMilliseconds);
|
|
end;
|
|
{$ENDIF}
|
|
SetString(Result, Buffer, GetDateFormat(GetThreadLocale, DATE_LONGDATE,
|
|
@SystemTime, nil, Buffer, SizeOf(Buffer) - 1));
|
|
Result := TrimRight(Result);
|
|
end;
|
|
|
|
function FormatLongDateTime(Value: TDateTime): string;
|
|
begin
|
|
if Value <> NullDate then
|
|
Result := FormatLongDate(Value) + FormatDateTime(' tt', Value)
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
{$ENDIF WIN32}
|
|
|
|
{$IFNDEF USE_FOUR_DIGIT_YEAR}
|
|
|
|
function FourDigitYear: Boolean;
|
|
begin
|
|
Result := Pos('YYYY', AnsiUpperCase(ShortDateFormat)) > 0;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{$IFDEF USE_FOUR_DIGIT_YEAR}
|
|
initialization
|
|
FourDigitYear := Pos('YYYY', AnsiUpperCase(ShortDateFormat)) > 0;
|
|
{$ENDIF}
|
|
end.
|
|
|