問題描述
Delphi ‑ Tải TTimeZone cho múi giờ không thuộc địa phương và chuyển đổi giữa các múi giờ (Delphi ‑ Get TTimeZone for non‑local timezone and convert between timezones)
My subject is probably terribly worded, but here's what I have.
I have a web service that reports timestamps in its local time and the timestamps reflect daylight time if the server is in an affected area. The web service also has a second call to retrieve the server time in UTC so a server in Pacific Daylight Time (PDT) reports its UTC offset as ‑08:00 even though it's effectively ‑07:00 because of PDT.
Here is the result of my call to return the server's timezone info.
Pacific Standard Time;‑480;(UTC‑08:00) Pacific Time (US & Canada);Pacific Standard Time;Pacific Daylight Time;[01:01:0001;12:31:2006;60;[0;02:00:00;4;1;0;];[0;02:00:00;10;5;0;];][01:01:2007;12:31:9999;60;[0;02:00:00;3;2;0;];[0;02:00:00;11;1;0;];];
So, if a timestamp returned from the web service is 3/12/2013 12:00am and the UTC offset is ‑08:00 and I live in a daylight time exempt area of Arizona where my UTC offset is ‑07:00 how can I convert from the returned timestamp to my local time?
The killer here is the web service using local time in timestamps. If they would just stick to a universal format my life would be easy. My current thinking is if I can get the server's information in a TTimeZone or equivalent structure then I can use the TTimeZone.IsDaylightTime(Timestamp) function to know if I need to subtract an hour from the timestamp before then using the ‑08:00 server offset and ‑07:00 local offset to get my correct local time.
參考解法
方法 1:
You can use delphi‑tzdb. Pseudo‑code:
uses
..., TZDB;
procedure Main;
var
ServerTZID: string;
TZ: TTimeZone;
Stamp1, Stamp2: TDateTime;
begin
// 1. retrieve server timezone info
ServerTZID := ... // MyServer.GetTimezoneInfo; e.g. 'Pacific Standard Time';
// look up the retrieved timezone
TZ := TBundledTimeZone.GetTimeZone(ServerTZID); // nil if not found
// 2. retrieve server timestamp
Stamp1 := ... // MyServer.RetrieveTimestamp;
// 3. convert to UTC and back to local timezone
Stamp2 := TZ.Local.ToLocalTime(TZ.ToUniversalTime(Stamp1));
Writeln(Format('%s %s ‑> %s %s', [FormatDateTime('yyyy‑mm‑dd hh:nn:ss.zzz', Stamp1),
TZ.DisplayName, FormatDateTime('yyyy‑mm‑dd hh:nn:ss.zzz', Stamp2),
TZ.Local.DisplayName]));
end;
(by Michael S.、Ondrej Kelle)