我正在使用Delphi xe2,我正在尝试使用UTC datetime在我的数据库中存储记录,然后在客户端在本地日期时间读取它时将其恢复?任何想法如何做到这一点反向转换?
答案 0 :(得分:18)
这是我用来将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日期时间:
如何扭转这种情况应该是显而易见的。
请注意,此转化会将夏令时视为现在,而不是在转换时 。 XE中引入的DateUtils.TTimeZone
类型试图做到这一点。代码变为:
LocalDateTime := TTimeZone.Local.ToLocalTime(UniversalDateTime);
在另一个方向使用ToUniversalTime
。
此类似乎(松散地)在.net TimeZone
类上建模。
一句警告。不要指望尝试在转换为100%准确时考虑夏令时。实现这一目标根本不可能。至少没有时间机器。这只是考虑未来的时间。过去甚至很复杂。 Raymond Chen在这里讨论了这个问题:Why Daylight Savings Time is nonintuitive。
答案 1 :(得分:11)
你可以使用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;
答案 2 :(得分:10)
在使用XE2时,您可以使用System.DateUtils.TTimeZone
。
您可以查看good post解释方法及其工作原理和示例: http://alex.ciobanu.org/?p=373
答案 3 :(得分:2)
万一有人需要在2020年回答问题:
确保包含
Uses
System.DateUtils;
然后选择UTC
function GetUTC(dt: TDateTime): TDateTime;
begin
result := TTimeZone.Local.ToUniversalTime(dt);
end;
和本地时间
function GetLocalTime(dt: TDateTime):TDateTime;
begin
result := TTimeZone.Local.ToLocalTime(dt);
end;
答案 4 :(得分:1)
如果您的客户使用本地Delphi应用程序,可以使用系统日期函数来完成。
但是,如果您处于客户端/服务器环境中(例如,Delphi应用程序是Web服务器,而客户端只接收HTML页面),则需要以不同方式转换为用户的本地时间。服务器需要知道用户的时区,并进行适当的转换。
如果应用程序需要转换历史数据,夏令时也会引起头痛 - 您需要知道是否有对用户所在地区有效的DST。
在这些用例中,Time Zone Database for Delphi可能会有所帮助。
TZDB提供了一个简单的数据库和一个专门的时区类 允许访问时区数据库支持的所有时区 项目
我不知道有SystemTimeToTzSpecificLocalTime但是只读了Jon Skeet prefers TZDB进行时区处理。
答案 5 :(得分:1)
function NowUTC: TDateTime;
Var UTC: TSystemTime;
begin
GetSystemTime(UTC);
Result := SystemTimeToDateTime(UTC);
end;
function UTCToLocal(UTC: TDateTime): TDateTime;
begin
Result := IncMinute(UTC, UTCToLocalTimeOffsetMinutes);
end;
function UTCToLocalTimeOffsetMinutes: Int16;
Var UTC: TSystemTime;
UTC2: TSystemTime;
t : TDateTime;
t2 : TDateTime;
begin
GetSystemTime(UTC);
GetLocalTime(UTC2);
t := SystemTimeToDateTime(UTC);
t2 := SystemTimeToDateTime(UTC2);
Result := System.DateUtils.MinutesBetween(t,t2);
end;