کد:
unit UFarsiDate;
{-----------------------------------------}
{ * * * * *Farsi functions unit * * * * * }
{ * * *Use this unit for persian date * * }
{ * * * * * * * * * * * * * * * * * * * * }
{ * * *Written by: Salar Khalilzadeh * * *}
{ * * * * * *Copyright © 2006 * * * * * * }
{ * * * * * * SalarSoftwares * * * * * * *}
{ * * * * * * * * * * * * * * * * * * * * }
{----Website: www.salarsoft.somee.com-----}
{----E-mail: SalarSoftwares@gmail.com-----}
{ * * * *Last update: 2006/05/08 * * * * *}
{-----------------------------------------}
{-----------------------------------------
Updates:
1-Persian date to Milady date conversion supported.
2-Support persian dates and strings
3-Support time included in TDateTime
4-Support Old version of Delphi
-----------------------------------------}
{IMPORTANT: TfarDateTime = TDateTime}
{Important note:
You never need to create TFarDate class.
Only add TFarDate string before functions.
Always use first: (FarEncodeDate or MiladyToShamsi or
* * * * * * * * *MiladyToShamsiInt or MiladyToShamsiStr or
* * * * * * * * *farStrToDate or farStrToDateDef )
after them use other functions.
}
interface
uses windows,sysutils,SysConst,math,DateUtils;
{$IFDEF VER140}
*{$DEFINE OldDelphi}
{$ENDIF}
{$IFDEF VER130}
*{$DEFINE OldDelphi}
{$ENDIF}
{$IFDEF VER120}
*{$DEFINE OldDelphi}
{$ENDIF}
const
*FarMonthDays: array [Boolean] of TDayTable =
* *((31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29),
* * (31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30));
const
*EngMonthDays: array [Boolean] of TDayTable =
* *((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
* * (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
const
*farEngToFarDays:array[1..7] of word=(7,1,2,3,4,5,6) * *;
*farShortMonths:array [1..12] of string=
* *("فروردين","ارديبهشت","خرداد","تير","مرداد","شهريور","مهر","آبان",
* * *"آذر","دي","بهمن","اسفند");
*farLongMonths:array [1..12] of string=
* *("فروردين","ارديبهشت","خرداد","تير","مرداد","شهريور","مهر","آبان",
* * *"آذر","دي","بهمن","اسفند");
*farShortDays:array [1..7] of string=
* *("جمعه","شنبه","يكشنبه","دو شنبه","سه شنبه","چهار شنبه","پنج شنبه");
*farLongDays:array [1..7] of string=
* *("جمعه","شنبه","يكشنبه","دو شنبه","سه شنبه","چهار شنبه","پنج شنبه");
const
*DaysPerWeek = 7;
*WeeksPerFortnight = 2;
*MonthsPerYear = 12;
*YearsPerDecade = 10;
*YearsPerCentury = 100;
*YearsPerMillennium = 1000;
*DayMonday = 1;
*DayTuesday = 2;
*DayWednesday = 3;
*DayThursday = 4;
*DayFriday = 5;
*DaySaturday = 6;
*DaySunday = 7;
var
*farShortMonthNames: array[1..12] of string;
*farLongMonthNames: array[1..12] of string;
*farShortDayNames: array[1..7] of string;
*farLongDayNames: array[1..7] of string;
type
*TDateOrder = (doMDY, doDMY, doYMD);
*TfarDateTime=TDateTime;
type
*TDateKind = (dkSolar, dkGregorian);
*
{$IfDef OldDelphi}
type
*TFormatSettings = record
* *CurrencyFormat: Byte;
* *NegCurrFormat: Byte;
* *ThousandSeparator: Char;
* *DecimalSeparator: Char;
* *CurrencyDecimals: Byte;
* *DateSeparator: Char;
* *TimeSeparator: Char;
* *ListSeparator: Char;
* *CurrencyString: string;
* *ShortDateFormat: string;
* *LongDateFormat: string;
* *TimeAMString: string;
* *TimePMString: string;
* *ShortTimeFormat: string;
* *LongTimeFormat: string;
* *ShortMonthNames: array[1..12] of string;
* *LongMonthNames: array[1..12] of string;
* *ShortDayNames: array[1..7] of string;
* *LongDayNames: array[1..7] of string;
* *TwoDigitYearCenturyWindow: Word;
*end;
Const
*{ Units of time }
*HoursPerDay * = 24;
*MinsPerHour * = 60;
*SecsPerMin * *= 60;
*MSecsPerSec * = 1000;
*MinsPerDay * *= HoursPerDay * MinsPerHour;
*SecsPerDay * *= MinsPerDay * SecsPerMin;
*MSecsPerDay * = SecsPerDay * MSecsPerSec;
{$EndIf}
type
*TFarDate=class
*Private
* *class function farIsLeapYear(Year: Word): Boolean;
* *//class procedure farDivMod(Dividend: Integer; Divisor: Word;
* *// *var Result, Remainder: Word);
* *class function FarDecodeDateFully(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean;
* *class function farGetDateOrder(const DateFormat: string): TDateOrder;
* *class function farGetEraYearOffset(const Name: string): Integer;
* *class procedure farScanBlanks(const S: string; var Pos: Integer);
* *class function farScanChar(const S: string; var Pos: Integer; Ch: Char): Boolean;
* *class function farScanDate(const S: string; var Pos: Integer;
* * *var Date: TDateTime): Boolean; overload;
* *class function farScanDate(const S: string; var Pos: Integer; var Date: TDateTime;
* * *const FormatSettings: TFormatSettings): Boolean; overload;
* *class function farScanNumber(const S: string; var Pos: Integer;
* * *var Number: Word; var CharCount: Byte): Boolean;
* *class procedure farScanToNumber(const S: string; var Pos: Integer);
* *class function farTryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;
* *class function farTryStrToDate(const S: string; out Value: TDateTime): Boolean;overload;
* *class function farTryStrToDate(const S: string; out Value: TDateTime;
* * *const FormatSettings: TFormatSettings): Boolean;overload;
* *class procedure farDateTimeToString(var Result: string; const Format: string;
* * *DateTime: TDateTime);overload;
* *class procedure farDateTimeToString(var Result: string; const Format: string;
* * *DateTime: TDateTime; const FormatSettings: TFormatSettings);overload;
* *//class procedure farDateTimeToStringFarsi(var Result: string;
* *// *const Format: string; DateTime: TDateTime);
* *class function farTryEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
* * *AMilliSecond: Word; out AValue: TDateTime): Boolean;
* *class procedure farDivMod(Dividend: Integer; Divisor: Word;
* * *var Result, Remainder: Word);
* *class function farTryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime): Boolean;
* *class function farDateOfDay(DateKind: TDateKind; Days, Year: Word;
* * *var Month, Day: Word): Boolean;
* *class function farDaysOfMonth(DateKind: TDateKind; Year,
* * *Month: Word): Word;
* *class function farDaysToDate(DateKind: TDateKind; Year, Month,
* * *Day: Word): Word;
* *class function farIsDateValid(DateKind: TDateKind; Year, Month,
* * *Day: Word): Boolean;
* *class function SolarIsLeapYear(DateKind: TDateKind;
* * *Year: Word): Boolean;
*public
* *class function farEncodeDate(const Year, Month, Day: Word): TfarDateTime;
* *class procedure farDecodeDate(const DateTime: TfarDateTime; var Year, Month, Day: Word);
* *class procedure farDecodeDateTime(const AValue: TfarDateTime; out AYear, AMonth, ADay,
* * * * * *AHour, AMinute, ASecond, AMilliSecond: Word);
* *class function farEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
* * *AMilliSecond: Word): TfarDateTime;
* *class Function MiladyToShamsi(const DTime:tdateTime):TfarDateTime;
* *class Function MiladyToShamsistr(const DTime:tdateTime):String;
* *class Function MiladyToShamsiInt( const DTime:tdateTime;var Year,Month,Day:word):TfarDateTime;
* *class Function ShamsiToMilady(const DateTime: TfarDateTime): TDateTime;
* *class function farDateToStr(dateTime:TfarDateTime):string;overload;
* *class function farDateToStr(const DateTime: TfarDateTime;
* * *const FormatSettings: TFormatSettings): string;overload;
* *class function farDateTimeToStr(const DateTime: TfarDateTime): string;overload;
* *class function farDateTimeToStr(const DateTime: TfarDateTime;
* * *const FormatSettings: TFormatSettings): string;overload;
* *class function farFormatDateTime(const Format: string; DateTime: TfarDateTime): string;overload;
* *class function farFormatDateTime(const Format: string; DateTime: TfarDateTime;
* * *const FormatSettings: TFormatSettings): string;overload;
* *class function farStrToDateDef(const S: string; const Default: TfarDateTime): TfarDateTime;overload;
* *class function farStrToDateDef(const S: string; const Default: TfarDateTime;
* * *const FormatSettings: TFormatSettings): TfarDateTime;overload;
* *class function farStrToDate(const S: string): TfarDateTime;overload;
* *class function farStrToDate(const S: string;
* * *const FormatSettings: TFormatSettings): TfarDateTime;overload;
* *class function farYearOf(const AValue: TfarDateTime): Word;
* *class function farMonthOf(const AValue: TfarDateTime): Word;
* *class function farWeekOf(const AValue: TfarDateTime): Word; * * * * * * * * * * * {ISO 8601}
* *class function farDayOf(const AValue: TfarDateTime): Word;
* *class function farDayOfTheWeek(const AValue: TfarDateTime): Word;
* *class function farDayString(const AValue: TfarDateTime): string;
* *class function farMonthString(const AValue: TfarDateTime): string;
* *{-------------------------}
* *class function farWeekOfTheYear(const AValue: TfarDateTime): Word; overload; * * *{ISO 8601}
* *class function farWeekOfTheYear(const AValue: TfarDateTime; * * * * * * * * * * * {ISO 8601}
* * *var AYear: Word): Word; overload;
* *{ Encode/decode functions that work with week of year and day of week }
* *class procedure farDecodeDateWeek(const AValue: TfarDateTime; out AYear, * * * * *{ISO 8601}
* * *AWeekOfYear, ADayOfWeek: Word);
*end;
{ Pick-a-field functions }
function AddWeek(const AValue: TDateTime;
*const ANumberOfWeeks: Integer): TDateTime;
function AddDay(const AValue: TDateTime;
*const ANumberOfDays: Integer): TDateTime;
function AddHour(const AValue: TDateTime;
*const ANumberOfHours: Int64): TDateTime;
function AddMinute(const AValue: TDateTime;
*const ANumberOfMinutes: Int64): TDateTime;
function AddSecond(const AValue: TDateTime;
*const ANumberOfSeconds: Int64): TDateTime;
function AddMilliSecond(const AValue: TDateTime;
*const ANumberOfMilliSeconds: Int64): TDateTime;
implementation
function AddWeek(const AValue: TDateTime;
*const ANumberOfWeeks: Integer): TDateTime;
begin
*Result := AValue + ANumberOfWeeks * DaysPerWeek;
end;
function AddDay(const AValue: TDateTime;
*const ANumberOfDays: Integer): TDateTime;
begin
*Result := AValue + ANumberOfDays;
end;
function AddHour(const AValue: TDateTime;
*const ANumberOfHours: Int64): TDateTime;
begin
*Result := ((AValue * HoursPerDay) + ANumberOfHours) / HoursPerDay;
end;
function AddMinute(const AValue: TDateTime;
*const ANumberOfMinutes: Int64): TDateTime;
begin
*Result := ((AValue * MinsPerDay) + ANumberOfMinutes) / MinsPerDay;
end;
function AddSecond(const AValue: TDateTime;
*const ANumberOfSeconds: Int64): TDateTime;
begin
*Result := ((AValue * SecsPerDay) + ANumberOfSeconds) / SecsPerDay;
end;
function AddMilliSecond(const AValue: TDateTime;
*const ANumberOfMilliSeconds: Int64): TDateTime;
begin
*Result := ((AValue * MSecsPerDay) + ANumberOfMilliSeconds) / MSecsPerDay;
end;
class function TFarDate.farIsLeapYear(Year: Word): Boolean;
begin
*Result := (Year mod 4 = 0) and ((Year mod 100 *0) or (Year mod 400 = 0));
end;
{procedure farDivMod(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;}
class procedure TFarDate.farDivMod(Dividend: Integer; Divisor: Word;
*var Result, Remainder: Word);
begin
Result:= *Dividend div *Divisor;
Remainder:=Dividend-(Result * Divisor);
end;
class function TFarDate.farTryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;
var
*I: Integer;
*DayTable: PDayTable;
begin
*Result := False;
*DayTable := @farMonthDays[farIsLeapYear(Year)];
*if (Year >= 1) and (Year = 1) and (Month = 1) and (Day *LeapMonth[DateKind]) and SolarIsLeapYear(DateKind, Year) then
* * *LeapDay := 1;
* *if Days =Counter do begin /////////////////////////
*If thisYear=counter then begin
* *AddOneDay:=true;
* *break;
*end;
*If counter=TestRange2 then break;
*counter:=counter+4
end;//while
If AddOneDay then
*addtodays:=1
Else
*AddTodays:=0;
//Rem---------------------------------/////////////////
If (((ThisMonth = 3) and (thisday4))) then
*CurYear:=yearEqual[2,1]+YearDif1
else begin
*CurYear:=YearEqual[2,1]+YearDif2;
*Counter:=FarsiRange1;
*while counter>FarsiRange2 do begin /////////////////////////
* *If CurYear=Counter then begin
* * *AddFarDay:=true;
* * *break;
* *end;
*If FarsiRange2>=Counter then break;
*counter:=counter+4
*end;//while
*If AddFarDay then
* *FarDay:=1 *else * Farday:=0;
*If (((thismonth=3) and (thisday>20-(addToDays)+FarDay)) or *(thismonth>3) ) then
* *CurYear:=CurYear+1;
end; //First If
If AddtoDays=1 then FarDay:=0;
//Rem---------------------------------
Case thismonth of
*1:Begin
* * *If thisday 2 then Count := 2;
* * * * * * *AppendNumber(Min, Count);
* * * * * *end;
* * * * *"S":
* * * * * *begin
* * * * * * *GetCount;
* * * * * * *GetTime;
* * * * * * *if Count > 2 then Count := 2;
* * * * * * *AppendNumber(Sec, Count);
* * * * * *end;
* * * * *"T":
* * * * * *begin
* * * * * * *GetCount;
* * * * * * *if Count = 1 then
* * * * * * * *AppendFormat(Pointer(FormatSettings.ShortTimeFormat)) else
* * * * * * * *AppendFormat(Pointer(FormatSettings.LongTimeFormat));
* * * * * *end;
* * * * *"Z":
* * * * * *begin
* * * * * * *GetCount;
* * * * * * *GetTime;
* * * * * * *if Count > 3 then Count := 3;
* * * * * * *AppendNumber(MSec, Count);
* * * * * *end;
* * * * *"A":
* * * * * *begin
* * * * * * *GetTime;
* * * * * * *P := Format - 1;
* * * * * * *if StrLIComp(P, "AM/PM", 5) = 0 then
* * * * * * *begin
* * * * * * * *if Hour >= 12 then Inc(P, 3);
* * * * * * * *AppendChars(P, 2);
* * * * * * * *Inc(Format, 4);
* * * * * * * *Use12HourClock := TRUE;
* * * * * * *end else
* * * * * * *if StrLIComp(P, "A/P", 3) = 0 then
* * * * * * *begin
* * * * * * * *if Hour >= 12 then Inc(P, 2);
* * * * * * * *AppendChars(P, 1);
* * * * * * * *Inc(Format, 2);
* * * * * * * *Use12HourClock := TRUE;
* * * * * * *end else
* * * * * * *if StrLIComp(P, "AMPM", 4) = 0 then
* * * * * * *begin
* * * * * * * *if Hour < 12 then
* * * * * * * * *AppendString(FormatSettings.TimeAMString) else
* * * * * * * * *AppendString(FormatSettings.TimePMString);
* * * * * * * *Inc(Format, 3);
* * * * * * * *Use12HourClock := TRUE;
* * * * * * *end else
* * * * * * *if StrLIComp(P, "AAAA", 4) = 0 then
* * * * * * *begin
* * * * * * * *GetDate;
* * * * * * * *AppendString(FormatSettings.LongDayNames[farDayOfTheWeek(DateTime)]);
* * * * * * * *Inc(Format, 3);
* * * * * * *end else
* * * * * * *if StrLIComp(P, "AAA", 3) = 0 then
* * * * * * *begin
* * * * * * * *GetDate;
* * * * * * * *AppendString(FormatSettings.ShortDayNames[farDayOfTheWeek(DateTime)]);
* * * * * * * *Inc(Format, 2);
* * * * * * *end else
* * * * * * *AppendChars(@Starter, 1);
* * * * * *end;
* * * * *"C":
* * * * * *begin
* * * * * * *GetCount;
* * * * * * *AppendFormat(Pointer(FormatSettings.ShortDateFormat));
* * * * * * *GetTime;
* * * * * * *if (Hour *0) or (Min *0) or (Sec *0) then
* * * * * * *begin
* * * * * * * *AppendChars(" ", 1);
* * * * * * * *AppendFormat(Pointer(FormatSettings.LongTimeFormat));
* * * * * * *end;
* * * * * *end;
* * * * *"/":
* * * * * *if DateSeparator *#0 then
* * * * * * *AppendChars(@FormatSettings.DateSeparator, 1);
* * * * *":":
* * * * * *if TimeSeparator *#0 then
* * * * * * *AppendChars(@FormatSettings.TimeSeparator, 1);
* * * * *"""", """:
* * * * * *begin
* * * * * * *P := Format;
* * * * * * *while (Format^ *#0) and (Format^ *Starter) do
* * * * * * *begin
* * * * * * * *if Format^ in LeadBytes then
* * * * * * * * *Format := StrNextChar(Format)
* * * * * * * *else
* * * * * * * * *Inc(Format);
* * * * * * *end;
* * * * * * *AppendChars(P, Format - P);
* * * * * * *if Format^ *#0 then Inc(Format);
* * * * * *end;
* * * *else
* * * * *AppendChars(@Starter, 1);
* * * *end;
* * *end;
* * *Dec(AppendLevel);
* *end;
*end;
begin
*BufPos := 0;
*AppendLevel := 0;
*if Format *"" then AppendFormat(Pointer(Format)) else AppendFormat("C");
*SetString(Result, Buffer, BufPos);
end;
class function TFarDate.farDateToStr(dateTime:TfarDateTime):string;
begin
farDateTimeToString(Result, ShortDateFormat, DateTime);
end;
class function TFarDate.farDateToStr(const DateTime: TfarDateTime;
*const FormatSettings: TFormatSettings): string;
begin
*farDateTimeToString(Result, FormatSettings.ShortDateFormat, DateTime,
* *FormatSettings);
end;
class function TFarDate.farFormatDateTime(const Format: string; DateTime: TfarDateTime): string;
begin
*farDateTimeToString(Result, Format, DateTime);
end;
class function TFarDate.farFormatDateTime(const Format: string; DateTime: TfarDateTime;
*const FormatSettings: TFormatSettings): string;
begin
*farDateTimeToString(Result, Format, DateTime, FormatSettings);
end;
class function TFarDate.farDateTimeToStr(const DateTime: TfarDateTime): string;
begin
*farDateTimeToString(Result, "", DateTime);
end;
class function TFarDate.farDateTimeToStr(const DateTime: TfarDateTime;
*const FormatSettings: TFormatSettings): string;
begin
*farDateTimeToString(Result, "", DateTime, FormatSettings);
end;
class function TFarDate.farGetDateOrder(const DateFormat: string): TDateOrder;
var
*I: Integer;
begin
*Result := doMDY;
*I := 1;
*while I *0 then
* * *Y := EraToYear(Y)
* *else
* *if (YearLen *0) and (Y < CenturyBase) then
* * * *Inc(Y, 100);
* *end;
*end else
*begin
* *Y := CurrentYear;
* *if DateOrder = doDMY then
* *begin
* * *D := N1; M := N2;
* *end else
* *begin
* * *M := N1; D := N2;
* *end;
*end;
*farScanChar(S, Pos, DateSeparator);
*farScanBlanks(S, Pos);
*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
* * *farScanToNumber(S, Pos)
* *else *// stop at time prefix
* * *repeat
* * * *while (Pos *Length(S)) or
* * * *(AnsiCompareText(TimeAMString, Copy(S, Pos, Length(TimeAMString))) = 0) or
* * * *(AnsiCompareText(TimePMString, Copy(S, Pos, Length(TimePMString))) = 0);
*end;
*Result := farTryEncodeDate(Y, M, D, Date);
end;
class function TFarDate.farTryStrToDate(const S: string; out Value: TDateTime): Boolean;
var
*Pos: Integer;
begin
*Pos := 1;
*Result := farScanDate(S, Pos, Value) and (Pos > Length(S));
end;
class function TFarDate.farTryStrToDate(const S: string; out Value: TDateTime;
*const FormatSettings: TFormatSettings): Boolean;
var
*Pos: Integer;
begin
*Pos := 1;
*Result := farScanDate(S, Pos, Value, FormatSettings) and (Pos > Length(S));
end;
class function TFarDate.farStrToDate(const S: string): TfarDateTime;
begin
*if not farTryStrToDate(S, Result) then
* *raise EConvertError.Createfmt(SInvalidDate,[S]);
end;
class function TFarDate.farStrToDate(const S: string;
*const FormatSettings: TFormatSettings): TfarDateTime;
begin
*if not farTryStrToDate(S, Result, FormatSettings) then
* *raise EConvertError.Createfmt(SInvalidDate,[S]);
end;
class function TFarDate.farStrToDateDef(const S: string; const Default: TfarDateTime): TfarDateTime;
begin
*if not farTryStrToDate(S, Result) then
* *Result := Default;
end;
class function TFarDate.farStrToDateDef(const S: string; const Default: TfarDateTime;
*const FormatSettings: TFormatSettings): TfarDateTime;
begin
*if not farTryStrToDate(S, Result, FormatSettings) then
* *Result := Default;
end;
{----AValue is Shamsi date-----}
class function TFarDate.farYearOf(const AValue: TDateTime): Word;
var
*LMonth, LDay: Word;
begin
*TFarDate.FarDecodeDate(AValue, Result, LMonth, LDay);
end;
{----AValue is Shamsi date-----}
class function TFarDate.farMonthOf(const AValue: TDateTime): Word;
var
*LYear, LDay: Word;
begin
*TFarDate.FarDecodeDate(AValue, LYear, Result, LDay);
end;
{----AValue is Shamsi date-----}
class function TFarDate.farWeekOf(const AValue: TDateTime): Word; * * * * * * * * * * * {ISO 8601}
begin
*Result := farWeekOfTheYear(AValue);
end;
{----AValue is Shamsi date-----}
class function TFarDate.farDayOf(const AValue: TfarDateTime): Word;
var
*LYear, LMonth: Word;
begin
*TFarDate.FarDecodeDate(AValue, LYear, LMonth, Result);
end;
class function TFarDate.farWeekOfTheYear(const AValue: TfarDateTime): Word;
var
*LYear, LDOW: Word;
begin
*farDecodeDateWeek(AValue, LYear, Result, LDOW);
end;
class function TFarDate.farWeekOfTheYear(const AValue: TfarDateTime; var AYear: Word): Word;
var
*LDOW: Word;
begin
*farDecodeDateWeek(AValue, AYear, Result, LDOW);
end;
علاقه مندي ها (Bookmarks)