如何在Delphi XE2中将本地时间转换为UTC时间?以及如何将它从UTC转换回当地时间?

Dre*_*r64 12 delphi time datetime utc delphi-xe2

我正在使用Delphi xe2,我正在尝试使用UTC datetime在我的数据库中存储记录,然后在客户端在本地日期时间读取它时将其恢复?任何想法如何做到这回来转换?

Dav*_*nan 19

这是我用来将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;
Run Code Online (Sandbox Code Playgroud)

如您所见,该函数转换UTC日期时间如下:

  • 日期时间 - >系统时间
  • 系统时间 - >文件时间
  • 文件时间 - >本地文件时间(这是从UTC到本地的转换)
  • 本地文件时间 - >系统时间
  • 系统时间 - >日期时间

应该明白如何扭转这种局面.


注意,此转换对待夏令因为它是现在,而不是因为它是/是在当时被转换.DateUtils.TTimeZone在XE中引入的类型试图做到这一点.代码变成:

LocalDateTime := TTimeZone.Local.ToLocalTime(UniversalDateTime);
Run Code Online (Sandbox Code Playgroud)

在另一个方向使用ToUniversalTime.

此类似乎(松散地)在.net TimeZone类上建模.

一句警告.不要指望尝试将转换时的夏令时计算为100%准确.实现这一目标根本不可能.至少没有时间机器.这只是考虑未来的时间.过去甚至很复杂.Raymond Chen在这里讨论了这个问题:为什么夏令时不直观.

  • 在具有夏令时区域的区域中将历史数据转换为本地数据需要特殊处理 (5认同)
  • @DavidHeffernan好的,也许我对这个函数应该做什么有不同的期望.但除此之外,你在帖子中暗示你的函数`LocalDateTimeFromUTCDateTime`是`TTimeZone.Local.ToLocalTime`的复杂变体.这不是真的,因为`DateUtils.Local.ToLocalTime`给出的结果与你的代码不同,如果它应用于历史值.你应该在帖子中明确指出两种解决方案都有不同的行为.一个不是另一个的"简化"变体. (3认同)
  • 您的代码不正确.当UTC unix时间是567302400时,我的时钟是1:00,因为我们有标准时间.但是你的功能输出2:00(截至本文撰写时,我们目前有DST).Raymond Chen建议使用`SystemTimeToTzSpecificLocalTimeEx`而不是`FileTimeToLocalFileTime`,例如因为它尊重给定时间戳的DST而不是使用当前的DST,这对于将历史时间戳转换为人类可读时间非常重要.(参见http://goo.gl/t94UNi)但是,使用`TTimeZone.Local.ToLocalTime`的解决方案是正确的. (2认同)

bum*_*mmi 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;
Run Code Online (Sandbox Code Playgroud)


Whi*_*ler 10

当您使用XE2时,您可以使用System.DateUtils.TTimeZone.

您可以查看这篇好文章,解释方法及其工作原理和示例:http: //alex.ciobanu.org/?p = 373


Dre*_*r64 9

如果有人在 2020 年需要答案:

确保包括

Uses 
System.DateUtils;
Run Code Online (Sandbox Code Playgroud)

那么对于UTC

function GetUTC(dt: TDateTime): TDateTime;
begin
  result := TTimeZone.Local.ToUniversalTime(dt);
end;
Run Code Online (Sandbox Code Playgroud)

和当地时间

function GetLocalTime(dt: TDateTime):TDateTime;
begin
  result := TTimeZone.Local.ToLocalTime(dt);
end;
Run Code Online (Sandbox Code Playgroud)