timeutils.pas

来自「用DELPHI实现的 PGP 加密算法」· PAS 代码 · 共 648 行 · 第 1/2 页

PAS
648
字号
	 else Result := 28;
      4, 6, 9, 11: Result := 30;
      else Result := 31;
    end;
  end; { DaysInMonth }

  function ThisYear: Word;
  begin
    Result := Date2Year(Date);
  end; { ThisYear }

  function ThisMonth: Word;
  begin
    Result := Date2Month(Date);
  end; { ThisMonth }

  function ThisDay: Word;
  begin
    Result := Date2Day(Date);
  end; { ThisDay }

  function ThisHr: Word;
  begin
    Result := Time2Hr(Time);
  end; { ThisHr }

  function ThisMin: Word;
  begin
    Result := Time2Min(Time);
  end; { ThisMin }

  function ThisSec: Word;
  begin
    Result := Time2Sec(Time);
  end; { ThisSec }

  function ThisMSec: Word;
  begin
    Result := Time2MSec(Time);
  end; { ThisYear }

  function DayOfMonth2Date(year,month,weekInMonth,dayInWeek: word): TDateTime;
  var
    days: integer;
    day : integer;
  begin
    if (weekInMonth >= 1) and (weekInMonth <= 4) then begin
      day := DayOfWeek(EncodeDate(year,month,1));		// get first day in month
      day := 1 + dayInWeek-day;					// get first dayInWeek in month
      if day <= 0 then
	Inc(day,7);
      day := day + 7*(weekInMonth-1);				// get weekInMonth-th dayInWeek in month
      Result := EncodeDate(year,month,day);
    end
    else if weekInMonth = 5 then begin				// last week, calculate from end of month
      days := DaysInMonth(EncodeDate(year,month,1));
      day  := DayOfWeek(EncodeDate(year,month,days));		// get last day in month
      day  := days + (dayInWeek-day);
      if day > days then
	Dec(day,7);						// get last dayInWeek in month
      Result := EncodeDate(year,month,day);
    end
    else
      Result := 0;
  end; { DayOfMonth2Date }

  function DSTDate2Date(const dstDate: TSystemTime; year: word): TDateTime;
  begin
    if dstDate.wMonth = 0 then
      Result := 0						// invalid month => no DST info
    else if dstDate.wYear = 0 then begin			// day-of-month notation
      Result :=
	DayOfMonth2Date(year,dstDate.wMonth,dstDate.wDay,dstDate.wDayOfWeek+1{convert to Delphi Style}) +
	EncodeTime(dstDate.wHour,dstDate.wMinute,dstDate.wSecond,dstDate.wMilliseconds);
    end
    else if dstDate.wYear = year then				// absolute format - valid only for specified year
      Result := SystemTimeToDateTime(dstDate)
    else
      Result := 0;
  end; { DSTDate2Date }

  function GetTZDaylightSavingInfoForYear(
    const TZ: TTimeZoneInformation; year: word;
    var DaylightDate, StandardDate: TDateTime;
    var DaylightBias, StandardBias: longint): boolean;
  begin
    Result := false;
    if (TZ.DaylightDate.wMonth <> 0) and
       (TZ.StandardDate.wMonth <> 0) then
    begin
      DaylightDate := DSTDate2Date(TZ.DaylightDate,year);
      StandardDate := DSTDate2Date(TZ.StandardDate,year);
      DaylightBias := TZ.Bias+TZ.DaylightBias;
      StandardBias := TZ.Bias+TZ.StandardBias;
      Result := (DaylightDate <> 0) and (StandardDate <> 0);
    end;
  end; { GetTZDaylightSavingInfoForYear }

  function GetTZDaylightSavingInfo(
    const TZ: TTimeZoneInformation;
    var DaylightDate, StandardDate: TDateTime;
    var DaylightBias, StandardBias: longint): boolean;
  begin
    Result := GetTZDaylightSavingInfoForYear(TZ,ThisYear,DaylightDate,StandardDate,DaylightBias,StandardBias);
  end; { GetTZDaylightSavingInfo }

  function GetDaylightSavingInfoForYear(
    year: word;
    var DaylightDate, StandardDate: TDateTime;
    var DaylightBias, StandardBias: longint): boolean;
  var
    TZ: TTimeZoneInformation;
  begin
    GetTimeZoneInformation(TZ);
    Result := GetTZDaylightSavingInfoForYear(TZ,year,DaylightDate,StandardDate,StandardBias,DaylightBias);
  end; { GetDaylightSavingInfoForYear }

  function GetDaylightSavingInfo(
    var DaylightDate, StandardDate: TDateTime;
    var DaylightBias, StandardBias: longint): boolean;
  var
    TZ: TTimeZoneInformation;
  begin
    GetTimeZoneInformation(TZ);
    Result := GetTZDaylightSavingInfo(TZ,DaylightDate,StandardDate,StandardBias,DaylightBias);
  end; { GetDaylightSavingInfo }

  function TZLocalTimeToUTC(
    const TZ: TTimeZoneInformation;
    const loctime: TDateTime;
    preferDST: boolean): TDateTime;

    function Convert(const startDate, endDate, startOverl, endOverl: TDateTime;
      const startInval, endInval: TDateTime; inBias, outBias, overlBias: longint): TDateTime;
    begin
      if ((locTime > startOverl) or DateEQ(locTime,startOverl)) and (locTime < endOverl) then
	Result := loctime + overlBias/MINUTES_PER_DAY
      else if ((locTime > startInval) or DateEQ(locTime,startInval)) and (locTime < endInval) then
	Result := 0
      else if ((locTime > startDate) or DateEQ(locTime,startDate)) and (locTime < endDate) then
	Result := loctime + inBias/MINUTES_PER_DAY
      else
	Result := loctime + outBias/MINUTES_PER_DAY;
    end; { Convert }

  var
    dltBias : real;
    overBias: longint;
    stdBias : longint;
    dayBias : longint;
    stdDate : TDateTime;
    dayDate : TDateTime;
  begin { TZLocalTimeToUTC }
    if GetTZDaylightSavingInfoForYear(TZ, Date2Year(loctime), dayDate, stdDate, dayBias, stdBias) then begin
      if preferDST then
        overBias := dayBias
      else
        overBias := stdBias;
      dltBias := (stdBias-dayBias)/MINUTES_PER_DAY;
      if dayDate < stdDate then begin				// northern hemisphere
	if dayBias < stdBias then				// overlap at stdDate
	  Result := Convert(dayDate, stdDate, stdDate-dltBias, stdDate,
	    dayDate, dayDate+dltBias, dayBias, stdBias, overBias)
	else 							// overlap at dayDate - that actually never happens
	  Result := Convert(dayDate, stdDate, dayDate+dltBias, dayDate,
	    stdDate, stdDate-dltBias, dayBias, stdBias, overBias);
      end
      else begin						// southern hemisphere
	if dayBias < stdBias then				// overlap at stdDate
	  Result := Convert(stdDate, dayDate, stdDate-dltBias, stdDate,
	    dayDate, dayDate+dltBias, stdBias, dayBias, overBias)
	else							// overlap at dayDate - that actually never happens
	  Result := Convert(stdDate, dayDate, dayDate+dltBias, dayDate,
	    stdDate, stdDate-dltBias, stdBias, dayBias, overBias);
      end;
    end
    else
      Result := loctime + TZ.bias/MINUTES_PER_DAY;		// TZ does not use DST
  end; { TZLocalTimeToUTC }

  function UTCToTZLocalTime(
    const TZ: TTimeZoneInformation;
    const utctime: TDateTime): TDateTime;

    function Convert(const startDate, endDate: TDateTime; inBias, outBias: longint): TDateTime;
    begin
      if ((utctime > startDate) or DateEQ(utctime,startDate)) and (utctime < endDate) then
	Result := utctime - inBias/MINUTES_PER_DAY
      else
	Result := utctime - outBias/MINUTES_PER_DAY;
    end; { Convert }

  var
    stdUTC : TDateTime;
    dayUTC : TDateTime;
    stdBias: longint;
    dayBias: longint;
    stdDate: TDateTime;
    dayDate: TDateTime;

  begin { UTCToTZLocalTime }
    if GetTZDaylightSavingInfoForYear(TZ, Date2Year(utctime), dayDate, stdDate, dayBias, stdBias) then begin
      dayUTC := dayDate + stdBias/MINUTES_PER_DAY;
      stdUTC := stdDate + dayBias/MINUTES_PER_DAY;
      if dayUTC < stdUTC then
	Result := Convert(dayUTC,stdUTC,dayBias,stdBias)	// northern hem.
      else
	Result := Convert(stdUTC,dayUTC,stdBias,dayBias);	// southern hem.
    end
    else
      Result := utctime - TZ.bias/MINUTES_PER_DAY;		// TZ does not use DST
  end; { UTCToTZLocalTime }

  function LocalTimeToUTC(const loctime: TDateTime; preferDST: boolean): TDateTime;
  var
    TZ: TTimeZoneInformation;
  begin
    GetTimeZoneInformation(TZ);
    Result := TZLocalTimeToUTC(TZ,loctime,preferDST);
  end; { LocalTimeToUTC }

  function UTCToLocalTime(const utctime: TDateTime): TDateTime;
  var
    TZ: TTimeZoneInformation;
  begin
    GetTimeZoneInformation(TZ);
    Result := UTCToTZLocalTime(TZ,utctime);
  end; { UTCToLocalTime }

  function CompareSysTime(st1, st2: TSystemTime): integer;
  begin
    if st1.wYear < st2.wYear then
      Result := -1
    else if st1.wYear > st2.wYear then
      Result := 1
    else if st1.wMonth < st2.wMonth then
      Result := -1
    else if st1.wMonth > st2.wMonth then
      Result := 1
    else if st1.wDayOfWeek < st2.wDayOfWeek then
      Result := -1
    else if st1.wDayOfWeek > st2.wDayOfWeek then
      Result := 1
    else if st1.wDay < st2.wDay then
      Result := -1
    else if st1.wDay > st2.wDay then
      Result := 1
    else if st1.wHour < st2.wHour then
      Result := -1
    else if st1.wHour > st2.wHour then
      Result := 1
    else if st1.wMinute < st2.wMinute then
      Result := -1
    else if st1.wMinute > st2.wMinute then
      Result := 1
    else if st1.wSecond < st2.wSecond then
      Result := -1
    else if st1.wSecond > st2.wSecond then
      Result := 1
    else if st1.wMilliseconds < st2.wMilliseconds then
      Result := -1
    else if st1.wMilliseconds > st2.wMilliseconds then
      Result := 1
    else
      Result := 0;
  end; { CompareSysTime }

  function IsEqualTZ(tz1, tz2: TTimeZoneInformation): boolean;
  begin
    Result :=
      (tz1.Bias         = tz2.Bias)         and
      (tz1.StandardBias = tz2.StandardBias) and
      (tz1.DaylightBias = tz2.DaylightBias) and
      (CompareSysTime(tz1.StandardDate,tz2.StandardDate) = 0) and
      (CompareSysTime(tz1.DaylightDate,tz2.DaylightDate) = 0) and
      (WideCharToString(tz1.StandardName) = WideCharToString(tz2.StandardName)) and
      (WideCharToString(tz1.DaylightName) = WideCharToString(tz2.DaylightName));
  end; { IsEqualTZ }

  function NowUTC: TDateTime;
  var
    sysnow: TSystemTime;
  begin
    GetSystemTime(sysnow);
    Result := SystemTimeToDateTime(sysnow);
  end; { NowUTC }

  function TimeUTC: TDateTime;
  begin
    Result := Frac(NowUTC);
  end; { TimeUTC }

  function DateUTC: TDateTime;
  begin
    Result := Int(NowUTC);
  end; { DateUTC }

  // added by idw =========================================================== //

  function SystemTimeToDateTime(const ST: TSystemTime): TDateTime;
  begin
    with ST do Result:=EncodeDate(wYear, wMonth, wDay) + EncodeTime(wHour, wMinute, wSecond, wMilliseconds);
  end;

  function SystemTimeToUnixTime(const ST: TSystemTime): longint;
  var
    UTC: TDateTime;
  begin
    UTC:=SystemTimeToDateTime(ST);
    Result:=Round((UTC - EncodeDate(1970, 1, 1)) * SECONDS_PER_DAY);
  end;

  function UnixTimeToLocalTime(unixtime: longint): TDateTime;
  var
    TZ: TTimeZoneInformation;
  begin
    Result:=EncodeDate(1970, 1, 1) + unixtime/SECONDS_PER_DAY;
    GetTimeZoneInformation(TZ);
    Result:=UTCToTZLocalTime(TZ, Result);
  end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?