Reliable Way To Convert DateTime Values from UTC to CST and Back

B

Bruce

Is there a reliable way in Dot Net 2.0 to convert Date Time values between
UTC and CST when the local computer is set to other than CST?

It must work on operating systems for W2K and up.

I found some sample code on CodeProject.com

http://www.codeproject.com/KB/cs/timezoneconversions.aspx

It is the best that I have found so far, but it isn't completely reliable.
For example it uses TzSpecificLocalTimeToSystemTime() to convert dates from
a specific time zone to UTC, which requires Windows XP and higher. It also
uses the time zone's "index" registry value which isn't present in Vista. In
order to find the CST entry I have to resort to string compares on Vista
which makes the code much more fragile.

It also seems to have issues determining the current time zone. If I set the
zone to Arizona for example, it doesn't find the zone properly.

What we have is a SQL database located on a server in CST and a Access
Database copy of that SQL database on the user's computer. The user can
access the data through a web interface or the local desktop application.
The dates in both cases need to match otherwise we get off by a day issues
and things like that. When you store dates, they are stored with a time
value set to midnight. If the date gets adjusted for time zone, it may
display the date as the previous day instead of the date that was entered.

Thanks,
Bruce
 
J

Jeroen Mostert

Bruce said:
Is there a reliable way in Dot Net 2.0 to convert Date Time values
between UTC and CST when the local computer is set to other than CST?
No. .NET 2.0 has no (managed) way of accessing time zone data other than
that of the current one. This oversight was rectified in .NET 3.5.
It must work on operating systems for W2K and up.
Good luck with that. AFAIK there are no nonlocal time zone APIs for W2K at
all. Registry groveling is your only hope.
I found some sample code on CodeProject.com

http://www.codeproject.com/KB/cs/timezoneconversions.aspx

It is the best that I have found so far, but it isn't completely
reliable. For example it uses TzSpecificLocalTimeToSystemTime() to
convert dates from a specific time zone to UTC, which requires Windows
XP and higher.

I have no idea how you'd achieve this pre-XP, other than manually parsing
the DST rules in the registry (and that needs a version check so you really
only do it pre-XP, because it'll stop working in Vista at least).

In this case it's probably wiser to just work out the algorithm yourself.
You presumably know the DST transitions and the difference between the time
zones; if the zones don't cross countries (so they are the same in both
zones) you can determine for yourself what the offset to UTC was at any
given point, and from there you can convert to another time. This is not a
general solution, but a general solution needs a complete DST database and
the one in the registry isn't too convenient.
It also uses the time zone's "index" registry value which isn't present
in Vista. In order to find the CST entry I have to resort to string
compares on Vista which makes the code much more fragile.
The registry keys are documented in the MSDN
(http://msdn.microsoft.com/library/ms725481); "index" isn't part of those
keys, so it shouldn't be used. String compares should not be fragile; the
key names should be the standard time zone names and they should not vary
across operating systems. Display names, of course, are another matter.
It also seems to have issues determining the current time zone. If I set
the zone to Arizona for example, it doesn't find the zone properly.
For determining the current time zone, no registry groveling is required;
GetTimeZoneInformation() is supported on all platforms, and you don't even
need to call that, as TimeZone.CurrentTimeZone will return it too
(.StandardName should correspond to the registry key). Arizona should be "US
Mountain Standard Time", exactly like that.
What we have is a SQL database located on a server in CST and a Access
Database copy of that SQL database on the user's computer. The user can
access the data through a web interface or the local desktop
application. The dates in both cases need to match otherwise we get off
by a day issues and things like that. When you store dates, they are
stored with a time value set to midnight. If the date gets adjusted for
time zone, it may display the date as the previous day instead of the
date that was entered.
This is why you should always, always store times in UTC if you possibly
can, with an explicit time zone offset if you do need to record the time
zone the entry was made in. Storing local times is a bad idea, storing local
times without an offset is inviting disaster. Of course, it's cheap to say
that after the fact, but it's just how it is.
 
B

Bruce

Storing everything in UTC still would not solve my probems. It isn't a
viable option because we have to maintain backward compatability with
previous versions of the application.

The real issue is that dates should be stored as dates, not as date time,
unless there is a specific need for both such as in a time stamp.

When a date is entered as 10/16/2008 it needs to be displayed as that
regardless of the time zone.
 
J

Jeroen Mostert

Bruce said:
Storing everything in UTC still would not solve my probems. It isn't a
viable option because we have to maintain backward compatability with
previous versions of the application.
Sure, hence my "easy to say after the fact" remark. Once you've got it
wrong, you're usually stuck with it.
The real issue is that dates should be stored as dates, not as date
time, unless there is a specific need for both such as in a time stamp.
But if that's the only problem, isn't it trivial for you to just ignore the
time part?
When a date is entered as 10/16/2008 it needs to be displayed as that
regardless of the time zone.
Per above, what's stopping you from doing that? All you need to do is force
the .Kind of the DateTime to UTC after reading it from the DB (it should be
Unknown initialy). It isn't UTC, but that doesn't matter -- what matters is
that no time zone offsets are applied.

You will not be able to reliably tell what the date was in any other time
zone (that's just not possible without the time), but a date is a date.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top