Solved

UTC time getting different result during daylight savings time

Posted on 2014-11-03
7
265 Views
Last Modified: 2014-11-10
I have written two functions to convert to and from UTC time (see below). The problem is that events created when we were in daylight savings time have shifted by an hour now that we are not in daylight time. e.g. an event was saved on Friday for 8:00 on Monday is now showing at 7:00, presumably because the offset is different. (I'm presuming I'll have the opposite problem when events saved during a non-daylight time are shown during daylight time.) I'm puzzled as to why this isn't handling automatically since EST should have a different offset from UTC than EDT. Appreciate you help in understanding what's going on here so my "fix" doesn't break something else in the spring.

Did the functions that I wrote do something incorrect, or am I supposed to know to add/subtract an hour when in/not in daylight time.  Also, if I have to figure out if I'm in daylight time or not, is there a standard Delphi (2010) call to the system to figure this out.

Here's the code I'm currently using:
function UTCToLocal(var dtUTC: TDateTime): TDateTime;
var
  LocalSystemTime, UTCSystemTime: TSystemTime;
  LocalFileTime, UTCFileTime: TFileTime;
begin
  DateTimeToSystemTime(dtUTC, UTCSystemTime);
  SystemTimeToFileTime(UTCSystemTime, UTCFileTime);
  if FileTimeToLocalFileTime(UTCFileTime, LocalFileTime)
  and FileTimeToSystemTime(LocalFileTime, LocalSystemTime) then begin
    Result := SystemTimeToDateTime(LocalSystemTime);
  end
  else begin
    Result := dtUTC;  // Use time originally passed if conversion fails.
  end;
end;

function LocalToUTC(var dtLocal: TDateTime): TDateTime;
var
  LocalSystemTime, UTCSystemTime: TSystemTime;
  LocalFileTime, UTCFileTime: TFileTime;
begin
  DateTimeToSystemTime(dtLocal, LocalSystemTime);
  SystemTimeToFileTime(LocalSystemTime, LocalFileTime);
  if LocalFileTimeToFileTime(LocalFileTime, UTCFileTime)
  and FileTimeToSystemTime(UTCFileTime, UTCSystemTime) then begin
    Result := SystemTimeToDateTime(UTCSystemTime);
  end
  else begin
    Result := dtLocal; // Use time originally passed if conversion fails.
  end;
end;

Open in new window

0
Comment
Question by:EricTaylor
  • 3
  • 3
7 Comments
 
LVL 25

Expert Comment

by:Sinisa Vuk
Comment Utility
0
 
LVL 19

Expert Comment

by:Thommy
Comment Utility
Your conversion treats daylight saving time as it is now and not as it was at the time being converted!!!

You should use System.DateUtils.TTimeZone to account for daylight saving times...
How to convert Local time to UTC time in Delphi XE2? and how to convert it back from UTC to local time?
0
 

Author Comment

by:EricTaylor
Comment Utility
Sinisa, the info you posted seems helpful, but when I try to do this,TzSpecificLocalTimeToSystemTime is an undeclared identifier. What am I missing?  Thanks.

function LocalToUTC(var dtLocal: TDateTime): TDateTime;
var
  LocalSystemTime, UTCSystemTime: TSystemTime;
  TZInfo: TTimeZoneInformation;
begin
  GetTimeZoneInformation(TZInfo);
  DateTimeToSystemTime(dtLocal, LocalSystemTime);
  TzSpecificLocalTimeToSystemTime (@TZInfo, LocalSystemTime, UTCSystemTime);
  Result := SystemTimeToDateTime(UTCSystemTime);
end;

Open in new window

0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 25

Expert Comment

by:Sinisa Vuk
Comment Utility
add declaration for win api function:

function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation;
  var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall; external kernel32 name 'TzSpecificLocalTimeToSystemTime';

Open in new window

0
 

Author Comment

by:EricTaylor
Comment Utility
The Win api is not something I've generally had to deal with; could you point me to something that will give guidance on how to use it for something like this. Sorry for the ignorance... but that's where I'm at on this one.  Thanks
0
 
LVL 25

Accepted Solution

by:
Sinisa Vuk earned 500 total points
Comment Utility
this is my project if it helps:
unit Unit30;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation;
  var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall; external kernel32 name 'TzSpecificLocalTimeToSystemTime';


implementation

{$R *.dfm}

function UTCToLocalTime(AValue: TDateTime): TDateTime;
var
  LocalSystemTime, UTCSystemTime: TSystemTime;
  TZInfo: TTimeZoneInformation;
begin
  GetTimeZoneInformation(TZInfo);
  DateTimeToSystemTime(AValue, UTCSystemTime);
  SystemTimeToTzSpecificLocalTime(@TZInfo, UTCSystemTime, LocalSystemTime);
  Result := SystemTimeToDateTime(LocalSystemTime);
end;

function LocalTimeToUTC(dtLocal: TDateTime): TDateTime;
var
  LocalSystemTime, UTCSystemTime: TSystemTime;
  TZInfo: TTimeZoneInformation;
begin
  GetTimeZoneInformation(TZInfo);
  DateTimeToSystemTime(dtLocal, LocalSystemTime);
  TzSpecificLocalTimeToSystemTime(@TZInfo, LocalSystemTime, UTCSystemTime);

  Result := SystemTimeToDateTime(UTCSystemTime);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption := DateTimeToStr(LocalTimeToUTC(now));
end;

end.

Open in new window

0
 

Author Closing Comment

by:EricTaylor
Comment Utility
Thanks Sinisa. That appears to do the trick.

Thommy, thanks to you for your input as well...
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now