Как конвертировать местное время в UTC время в Delphi XE2? и как преобразовать его обратно из UTC в местное время?
Я использую Delphi xe2, и я пытаюсь сохранить записи с помощью UTC datetime в моей базе данных, а затем восстановить его, когда клиент читает его в своем локальном datetime ? есть идеи, как это сделать?
4 ответов
Это функция, которую я использую для преобразования из 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 следующим образом:
- время даты - > системное время
- системное время - > время файла
- время файла - > локальное время файла (это преобразование из UTC в локальный)
- локальное время файла - > системное время
- системное время - > время даты
Это должно быть очевидно, как чтобы обратить это вспять.
обратите внимание, что это преобразование рассматривает летнее время, как это теперь а не как это было в момент преобразования. The DateUtils.TTimeZone
тип, введенный в XE, пытается сделать именно это. Код становится:
LocalDateTime := TTimeZone.Local.ToLocalTime(UniversalDateTime);
в другом направлении использовать ToUniversalTime
.
этот класс, похоже, (свободно) смоделирован на .net TimeZone
класса.
слова предупреждающий. Не ожидайте попытка учитывать летнее время в то время преобразуется, чтобы быть на 100% точным. Этого просто невозможно достичь. По крайней мере без машины времени. И это только учитывая времена в будущем. Даже времена в прошлом сложны. Раймонд Чен обсуждает этот вопрос здесь: почему летнее время неинтуитивно.
Как вы используете XE2, вы можете использовать System.DateUtils.TTimeZone
.
вы можете проверить это хороший пост объясняя методы и как это работает и примеры : http://alex.ciobanu.org/?p=373
вы можете использовать TzSpecificLocalTimeToSystemTime и SystemTimeToTzSpecificLocalTime из kernel32.
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;
Если ваш клиент использует локальное приложение Delphi, это можно сделать с помощью системных функций даты.
однако, если вы находитесь в среде клиент / сервер (например, приложение Delphi является веб-сервером, и клиент получает только HTML-страницы), вам нужно преобразовать в локальное время пользователя по-разному. Сервер должен знать часовой пояс пользователя и преобразовывать его соответствующим образом.
также переход на летнее время может вызвать головную боль, если приложение должно преобразовать исторические данные-вам нужно знать, действовал ли DST для региона пользователя.
в этих случаях использовать тег база данных часовых поясов для Delphi может быть полезным.
TZDB предоставляет простую базу данных и специализированный класс часового пояса, который позволяет получить доступ ко всем часовым поясам, поддерживаемым базой данных часовых поясов проект.
Я не знал, что есть SystemTimeToTzSpecificLocalTime, но просто прочитал это Джон Скит предпочитает TZDB для обработки часового пояса.