Delphi xe2を使用していて、UTC日時を使用してレコードをデータベースに保存し、クライアントがローカル日時に読み取ったときにレコードを復元しようとしていますか?これを逆変換する方法はありますか?
これは、UTCからローカルに変換するために使用する関数です。
function LocalDateTimeFromUTCDateTime(const UTCDateTime: TDateTime): TDateTime;
var
LocalSystemTime: TSystemTime;
UTCSystemTime: TSystemTime;
LocalFileTime: TFileTime;
UTCFileTime: TFileTime;
begin
DateTimeToSystemTime(UTCDateTime, UTCSystemTime);
SystemTimeToFileTime(UTCSystemTime, UTCFileTime);
if FileTimeToLocalFileTime(UTCFileTime, LocalFileTime)
and FileTimeToSystemTime(LocalFileTime, LocalSystemTime) then begin
Result := SystemTimeToDateTime(LocalSystemTime);
end else begin
Result := UTCDateTime; // Default to UTC if any conversion function fails.
end;
end;
ご覧のとおり、この関数はUTC日時を次のように変換します。
これを逆にする方法は明らかです。
この変換では、夏時間がそのまま/以前の変換時ではなく現在として扱われることに注意してください。 DateUtils.TTimeZone
XEで導入されたタイプは、まさにそれを実行しようとします。コードは次のようになります。
LocalDateTime := TTimeZone.Local.ToLocalTime(UniversalDateTime);
他の方向では、ToUniversalTime
を使用します。
このクラスは、.net TimeZone
クラスで(大まかに)モデル化されているようです。
警告の言葉。 attemptが、変換時に100%正確になるように夏時間を考慮することを期待しないでください。それを達成することは単に不可能です。少なくともタイムマシンなしで。そして、それは将来の時代を考慮しているだけです。過去の時代でさえ複雑です。 Raymond Chenがこの問題についてここで説明しています: 夏時間が直感的でない理由 。
kernel32からTzSpecificLocalTimeToSystemTimeおよびSystemTimeToTzSpecificLocalTimeを使用できます。
var
Form1: TForm1;
function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation; var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall;
function SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation: PTimeZoneInformation; var lpUniversalTime,lpLocalTime: TSystemTime): BOOL; stdcall;
implementation
function TzSpecificLocalTimeToSystemTime; external kernel32 name 'TzSpecificLocalTimeToSystemTime';
function SystemTimeToTzSpecificLocalTime; external kernel32 name 'SystemTimeToTzSpecificLocalTime';
{$R *.dfm}
Function DateTime2UnivDateTime(d:TDateTime):TDateTime;
var
TZI:TTimeZoneInformation;
LocalTime, UniversalTime:TSystemTime;
begin
GetTimeZoneInformation(tzi);
DateTimeToSystemTime(d,LocalTime);
TzSpecificLocalTimeToSystemTime(@tzi,LocalTime,UniversalTime);
Result := SystemTimeToDateTime(UniversalTime);
end;
Function UnivDateTime2LocalDateTime(d:TDateTime):TDateTime;
var
TZI:TTimeZoneInformation;
LocalTime, UniversalTime:TSystemTime;
begin
GetTimeZoneInformation(tzi);
DateTimeToSystemTime(d,UniversalTime);
SystemTimeToTzSpecificLocalTime(@tzi,UniversalTime,LocalTime);
Result := SystemTimeToDateTime(LocalTime);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Date,Univdate,DateAgain:TDateTime;
begin
Date := Now;
Univdate := DateTime2UnivDateTime(Date);
DateAgain := UnivDateTime2LocalDateTime(Univdate);
Showmessage(DateTimeToStr(Date) +#13#10 + DateTimeToStr(Univdate)+#13#10 + DateTimeToStr(DateAgain));
end;
XE2を使用しているので、System.DateUtils.TTimeZone
を使用できます。
あなたはこれをチェックすることができます 良い投稿 方法とそれがどのように機能するかと例を説明します: http://alex.ciobanu.org/?p=37
クライアントがローカルのDelphiアプリケーションを使用している場合、これはシステム日付関数を使用して実行できます。
ただし、クライアント/サーバー環境を使用している場合(たとえば、DelphiアプリがWebサーバーであり、クライアントがHTMLページのみを受信する場合)、ユーザーの現地時間に別の方法で変換する必要があります。サーバーはユーザーのタイムゾーンを認識し、適切に変換する必要があります。
また、アプリケーションが履歴データを変換する必要がある場合、夏時間は頭痛の種になる可能性があります。ユーザーの地域でDSTが有効になっているかどうかを知る必要があります。
これらのユースケースでは、 Delphiのタイムゾーンデータベース が役立ちます。
TZDBは、タイムゾーンデータベースプロジェクトでサポートされているすべてのタイムゾーンにアクセスできるようにする、単純なデータベースと特殊なタイムゾーンクラスを提供します。
SystemTimeToTzSpecificLocalTimeがあることを知りませんでしたが、タイムゾーンの処理に Jon SkeetはTZDBを優先します と読みました。