📄 iddatetimestamp.pas
字号:
end else
begin
result := '+' + IntToStr(i); {Do not Localize}
end;
end;
i := GetTimeZoneMinutes;
if i <= 9 then
begin
result := result + '0'; {Do not Localize}
end;
result := result + IntToStr(i);
end;
function TIdDateTimeStamp.GetTimeZoneHour: Integer;
begin
result := FTimeZone div 60;
end;
function TIdDateTimeStamp.GetTimeZoneMinutes: Integer;
begin
result := Abs(FTimeZone) mod 60;
end;
function TIdDateTimeStamp.GetWeekOfYear;
var
w : Integer;
DT : TIdDateTimeStamp;
begin
DT := TIdDateTimeStamp.Create(Self);
try
DT.SetYear(Year);
w := DT.DayOfWeek; // Get the first day of this year & hence number of
// days of the first week that are in the previous year
w := w + Day - 2; // Get complete weeks
w := w div 7;
result := w + 1;
finally
DT.Free;
end;
end;
procedure TIdDateTimeStamp.SetFromDOSDateTime(ADate, ATime: Word);
begin
Zero;
SetYear(1980);
AddYears(ADate shr 9);
AddMonths(((ADate and $1E0) shr 5) - 1);
AddDays((ADate and $1F) - 1);
AddHours(ATime shr 11);
AddMinutes((ATime and $7E0) shr 5);
AddSeconds((ATime and $1F) - 1);
end;
procedure TIdDateTimeStamp.SetDateFromISO8601(AString: String);
var
i, week : Integer;
s : String;
begin
// AString should be in one of three formats:
// Calender - YYYY-MM-DD
// Ordinal - YYYY-XXX where XXX is the day of the year
// Week - YYYY-WXX-D where W is a literal and XX is the week of the year.
i := IndyPos('-', AString); {Do not Localize}
if i > 0 then
begin
s := Trim(Copy(AString, 1, i - 1));
AString := Trim(Copy(AString, i + 1, length(AString)));
i := FindFirstNotOf('0123456789', s); {Do not Localize}
if i = 0 then
begin
SetYear(StrToInt(s));
if length(AString) > 0 then begin
i := IndyPos('-', AString); {Do not Localize}
if (AString[1] = 'W') or (AString[1] = 'w') then {Do not Localize}
begin
// Week format
s := Trim(Copy(AString, 2, i - 2));
AString := Trim(Copy(AString, i + 1, length(AString)));
week := -1;
i := -1;
if (length(AString) > 0)
and (FindFirstNotOf(DIGITS, AString) = 0) then
begin
i := StrToInt(AString);
end;
if (Length(s) > 0)
and (FindFirstNotOf(DIGITS, AString) = 0) then
begin
week := StrToInt(s);
end;
if (week > 0) and (i >= 0) then
begin
Dec(week);
FDay := 1 + (IdDaysInWeek * week);
// Now have the correct week of the year
if i < GetDayOfWeek then begin
SubtractDays(GetDayOfWeek - i);
end else begin
AddDays(i - GetDayOfWeek);
end;
end;
end else if i > 0 then
begin
// Calender format
s := Trim(Copy(AString, 1, i - 1));
AString := Trim(Copy(AString, i + 1, length(AString)));
// Set the day first due to internal format.
if (length(AString) > 0)
and (FindFirstNotOf(DIGITS, s) = 0) then
begin
SetDay(StrToInt(AString));
end;
// Add the months.
if (length(s) > 0) and (FindFirstNotOf(DIGITS, s) = 0) then
begin
AddMonths(StrToInt(s) - 1);
end;
end else
begin
// Ordinal format
i := FindFirstNotOf(DIGITS, AString);
if i = 0 then begin
SetDay(StrToInt(AString));
end;
end;
end;
end;
end;
end;
procedure TIdDateTimeStamp.SetTimeFromISO8601(AString: String);
var
i : Integer;
Hour, Minute : String;
begin
// AString should be in the format of HH:MM:SS where : is a literal.
i := IndyPos(':', AString); {Do not Localize}
Hour := Trim(Copy(AString, 1, i - 1));
AString := Trim(Copy(AString, i + 1, length(AString)));
i := IndyPos(':', AString); {Do not Localize}
Minute := Trim(Copy(AString, 1, i - 1));
AString := Trim(Copy(AString, i + 1, Length(Astring)));
// Set seconds first due to internal format.
if (length(AString) > 0)
and (FindFirstNotOf(DIGITS, AString) = 0) then
begin
SetSecond(StrToInt(AString));
end;
if (length(Minute) > 0)
and (FindFirstNotOf(DIGITS, Minute) = 0) then
begin
AddMinutes(StrToInt(Minute));
end;
if (length(Hour) > 0)
and (FindFirstNotOf(DIGITS, Hour) = 0) then
begin
AddHours(StrToInt(Hour));
end;
end;
procedure TIdDateTimeStamp.SetFromISO8601(AString: String);
var
i : Integer;
begin
Zero;
i := IndyPos('T', AString); {Do not Localize}
if i > 0 then
begin
SetDateFromISO8601(Trim(Copy(AString, 1, i - 1)));
SetTimeFromISO8601(Trim(Copy(AString, i + 1, length(AString))));
end else
begin
SetDateFromISO8601(AString);
SetTimeFromISO8601(AString);
end;
end;
procedure TIdDateTimeStamp.SetFromRFC822(AString: String);
begin
SetFromTDateTime(StrInternetToDateTime(AString))
end;
procedure TIdDateTimeStamp.SetFromTDateTime;
begin
SetFromTTimeStamp(DateTimeToTimeStamp(ADateTime));
end;
procedure TIdDateTimeStamp.SetFromTTimeStamp;
begin
SetYear(1);
SetDay(1);
SetSecond(0);
SetMillisecond(ATimeStamp.Time);
SetDay(ATimeStamp.Date);
end;
procedure TIdDateTimeStamp.SetDay;
begin
if ANumber > 0 then begin
FDay := 0;
AddDays(ANumber);
end else begin
FDay := 1;
end;
end;
procedure TIdDateTimeStamp.SetMillisecond;
begin
FMillisecond := 0;
AddMilliseconds(ANumber);
end;
procedure TIdDateTimeStamp.SetSecond;
begin
FSecond := 0;
AddSeconds(ANumber);
end;
procedure TIdDateTimeStamp.SetTimeZone(const Value: Integer);
begin
FTimeZone := Value;
end;
procedure TIdDateTimeStamp.SetYear;
begin
If ANumber = 0 then begin
FYear := 1;
end else begin
FYear := ANumber;
end;
CheckLeapYear;
end;
procedure TIdDateTimeStamp.SubtractDays;
var
i : Integer;
begin
if ANumber = 0 then exit;
// First remove the number of days in this year. As with AddDays this
// is both an optimisation and a fix for calculations that begin in leap years.
if ANumber >= Cardinal(FDay - 1) then begin
ANumber := ANumber - Cardinal(FDay - 1);
FDay := 1;
end else begin
FDay := FDay - Integer(ANumber);
end;
// Subtract the number of whole leap year cycles = 400 years
if ANumber >= IdDaysInLeapYearCycle then begin
i := ANumber div IdDaysInLeapYearCycle;
SubtractYears(i * IdYearsInLeapYearCycle);
ANumber := ANumber - Cardinal(i * IdDaysInLeapYearCycle);
end;
// Next subtract the centuries, checking for the century that is passed through
if ANumber >= IdDaysInLeapCentury then begin
while ANumber >= IdDaysInLeapCentury do begin
i := FYear div 100;
if i mod 4 = 0 then begin
// Going back through a 'leap' century {Do not Localize}
SubtractYears(IdYearsInCentury);
ANumber := ANumber - Cardinal(IdDaysInLeapCentury);
end else begin
SubtractYears(IdYearsInCentury);
ANumber := ANumber - Cardinal(IdDaysInCentury);
end;
end;
end;
// Subtract multiples of 4 ("Short" Leap year cycle)
if ANumber >= IdDaysInShortLeapYearCycle then begin
while ANumber >= IdDaysInShortLeapYearCycle do begin
// Round off current year to nearest four.
i := (FYear shr 2) shl 2;
if SysUtils.IsLeapYear(i) then begin
// Normal
SubtractYears(IdYearsInShortLeapYearCycle);
ANumber := ANumber - Cardinal(IdDaysInShortLeapYearCycle);
end else begin
// Subtraction crosses a 100-year (but not 400-year) boundary. Add the
// same number of years, but one less day.
SubtractYears(IdYearsInShortLeapYearCycle);
ANumber := ANumber - Cardinal(IdDaysInShortNonLeapYearCycle);
end;
end;
end;
// Now the individual years
while ANumber > Cardinal(DaysInYear) do begin
SubtractYears(1);
Dec(ANumber, DaysInYear);
if Self.IsLeapYear then begin
// Correct the assumption of a non-leap year
AddDays(1);
end;
end;
// and finally the remainders
if ANumber >= Cardinal(FDay) then begin
SubtractYears(1);
ANumber := ANumber - Cardinal(FDay);
Day := DaysInYear - Integer(ANumber);
end else begin
Dec(FDay, ANumber);
end;
end;
procedure TIdDateTimeStamp.SubtractHours;
var
i : Cardinal;
begin
i := ANumber div IdHoursInDay;
SubtractDays(i);
Dec(ANumber, i * IdHoursInDay);
SubtractSeconds(ANumber * IdSecondsInHour);
end;
procedure TIdDateTimeStamp.SubtractMilliseconds;
var
i : Cardinal;
begin
if ANumber = 0 then exit;
i := ANumber div IdMillisecondsInDay;
SubtractDays(i);
Dec(ANumber, i * IdMillisecondsInDay);
i := ANumber div IdMillisecondsInSecond;
SubtractSeconds(i);
Dec(ANumber, i * IdMillisecondsInSecond);
Dec(FMillisecond, ANumber);
while FMillisecond <= 0 do begin
SubtractSeconds(1);
// FMillisecond is already negative, so add it.
FMillisecond := IdMillisecondsInSecond + FMillisecond;
end;
end;
procedure TIdDateTimeStamp.SubtractMinutes(ANumber : Cardinal);
begin
// Down size to seconds
while ANumber > MaxMinutesAdd do begin
SubtractSeconds(MaxMinutesAdd * IdSecondsInMinute);
Dec(ANumber, MaxMinutesAdd);
end;
SubtractSeconds(ANumber * IdSecondsInMinute);
end;
procedure TIdDateTimeStamp.SubtractMonths;
var
i : Integer;
begin
i := ANumber div IdMonthsInYear;
SubtractYears(i);
Dec(ANumber, i * IdMonthsInYear);
while ANumber > 0 do begin
i := MonthOfYear;
if i = 1 then begin
i := 13;
end;
if (i = 3) and (IsLeapYear) then begin
SubtractDays(IdDaysInMonth[2] + 1);
end else begin
SubtractDays(IdDaysInMonth[i - 1]);
end;
Dec(ANumber);
end;
end;
procedure TIdDateTimeStamp.SubtractSeconds(ANumber : Cardinal);
var
i : Cardinal;
begin
if ANumber = 0 then exit;
i := ANumber div IdSecondsInDay;
SubtractDays(i);
Dec(ANumber, i * IdSecondsInDay);
Dec(FSecond, ANumber);
If FSecond < 0 then begin
SubtractDays(1);
FSecond := IdSecondsInDay + FSecond;
end;
end;
procedure TIdDateTimeStamp.SubtractTDateTime;
begin
SubtractTTimeStamp(DateTimeToTimeStamp(ADateTime));
end;
procedure TIdDateTimeStamp.SubtractTIdDateTimeStamp;
begin
{ TODO : Check for accuracy }
SubtractYears(AIdDateTime.Year);
SubtractDays(AIdDateTime.Day);
SubtractSeconds(AIdDateTime.Second);
SubtractMilliseconds(AIdDateTime.Millisecond);
end;
procedure TIdDateTimeStamp.SubtractTTimeStamp;
var
TId : TIdDateTimeStamp;
begin
TId := TIdDateTimeStamp.Create(Self);
try
TId.SetFromTTimeStamp(ATimeStamp);
Self.SubtractTIdDateTimeStamp(TId);
finally
TId.Free;
end;
end;
procedure TIdDateTimeStamp.SubtractWeeks(ANumber : Cardinal);
begin
if ANumber = 0 then exit;
// Down size to subtracting Days
while ANumber > MaxWeekAdd do begin
SubtractDays(MaxWeekAdd * IdDaysInWeek);
Dec(ANumber, MaxWeekAdd * IdDaysInWeek);
end;
SubtractDays(ANumber * IdDaysInWeek);
end;
procedure TIdDateTimeStamp.SubtractYears;
begin
if (FYear > 0) and (ANumber >= Cardinal(FYear)) then begin
Inc(ANumber);
end;
FYear := FYear - Integer(ANumber);
CheckLeapYear;
end;
procedure TIdDateTimeStamp.Zero;
begin
ZeroDate;
ZeroTime;
FTimeZone := 0;
end;
procedure TIdDateTimeStamp.ZeroDate;
begin
SetYear(1);
SetDay(1);
end;
procedure TIdDateTimeStamp.ZeroTime;
begin
SetSecond(0);
SetMillisecond(0);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -