實作從 HTTP 伺服器即時獲取格林威治時間 (GMT),並精確轉換為北京時間 (UTC+8) 的完整方案。
uses Winapi.msxml, System.DateUtils;
{ 即時獲取網路時間,預設從 sohu 伺服器(平均 15ms 響應) }
function GetNetTime(aUrl: WideString = 'https://www.sohu.com'): string;
begin
with CoXMLHTTP.Create do
begin
open('Post', aUrl, False, EmptyParam, EmptyParam);
send(EmptyParam);
Result := getResponseHeader('Date'); { 取得 HTTP Date 標頭 }
end;
end;
{ 格林威治時間字串轉北京時間 }
function GMT2BjDateTime(const GMT: string): TDateTime;
var A: TArray<string>;
begin
{ 解析格式: "Wed, 04 Jan 2017 06:00:00 GMT" }
A := GMT.Split([',', ' '], ExcludeEmpty); { XE4 支援 }
with TStringList.Create do
begin
CommaText := 'Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12';
A[2] := Values[A[2]]; { 月份轉數字 }
Free;
end;
{ 組合為 "YYYY/MM/DD HH:NN:SS" 並指定 Locale 2052 (中文) }
Result := StrToDateTime(Format('%s/%s/%s %s', [A[3], A[2], A[1], A[4]]), FormatSettings.Create(2052));
Result := Result + 8/24; { +8 小時轉北京時間 }
end;
function GMT2BjDateTime(const GMT: string): TDateTime;
var
A: TArray<string>;
Y,M,D,H,N,S: Word;
begin
{ 更細緻分割,包含冒號 }
A := GMT.Split([',', ' ', ':'], ExcludeEmpty);
with TStringList.Create do
begin
CommaText := 'Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12';
A[2] := Values[A[2]];
Free;
end;
{ 逐欄位解析並提供預設值,避免格式異常導致例外 }
Y := StrToIntDef(A[3], YearOf(Now));
M := StrToIntDef(A[2], MonthOf(Now));
D := StrToIntDef(A[1], DayOf(Now));
H := StrToIntDef(A[4], HourOf(Now));
N := StrToIntDef(A[5], MinuteOf(Now));
S := StrToIntDef(A[6], SecondOf(Now));
Result := EncodeDateTime(Y, M, D, H, N, S, 0);
Result := Result + 8/24; { 轉北京時間 }
end;
procedure TForm1.Button1Click(Sender: TObject);
var strGMT: string; bjDateTime: TDateTime;
begin
strGMT := GetNetTime();
bjDateTime := GMT2BjDateTime(strGMT);
ShowMessageFmt('%s'#13#10'%s', [strGMT, DateTimeToStr(bjDateTime)]);
end;
+ 8/24 即 + 8/24 天 = +8 小時此方案無需第三方函式庫,純 Delphi 核心單元實現,適合需要網路校時的桌面應用程式。