Click here to Skip to main content
Licence CPOL
First Posted 2 Jan 2006
Views 53,605
Downloads 1,112
Bookmarked 26 times

Universal Time Converter

By Ramesh Ketha | 2 Jan 2006
Illustrates converting time from universal time to local time and vice versa in C++
1 vote, 9.1%
1
1 vote, 9.1%
2
1 vote, 9.1%
3
2 votes, 18.2%
4
6 votes, 54.5%
5
4.29/5 - 11 votes
1 removed
μ 3.76, σa 2.47 [?]
Sample Image - TimeZoneConverter/TimeZoneConverter.jpg

Introduction

Recently we had a requirement which demands knowledge of all the time zones and doing conversions from universal time to local time and vice versa. I searched for the code which would do this, but most of them happened to be in C#, article by Mike Dimmick is quite good but this was also in C# and there was very limited information available for doing this in C++. So I thought of putting together C++ code which does this on CodeProject. The different steps involved in writing this code are explained in the following sections. (I am not an English expert, but I tried my best to make the intention as clear as possible).

Enumerating TimeZones

There are no direct API's in Windows to enumerate time zones. We need to do get all the time zone information from the registry. The following key in the registry contains a list of time zones in alphabetical order in the form of sub keys:

"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"

Each subkey under the above subkey will give information about individual timezone. This individual subkey will have the following value names.

For eg: subkey ALASKAN STANDARD TIME will have information like this:

Display : (GMT - 9:00) Alaska
Dlt : Alaskan DayLight Time
Index : 0x00000003 (3)
MapID : 30,31
Std : Alaskan Standard Time
TZI : TimeZone Information in Binary Form

Of all these values, TZI happens to be critical information, which needs to be retrieved.
This value has the following data:

long Bias
long StandardBias
long DaylightBias
SYSTEMTIME StandardDate
SYSTEMTIME DaylightDate

We need to retrieve this information, first by enumerating all sub keys under "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones", then by querying values under each of the sub keys.

CTimeZoneInfoManager::EnumerateTimeZones() will have related code which would read all sub keys information of "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones".

int CTimeZoneInfoManager::GetFullTimeZoneInfoFromRegistry() will have code which will fill the necessary time zone information structures, which are required for conversion.

Finally all the time zone information is collected in the template based class CArray<CRegTimeZoneInfo*, CRegTimeZoneInfo*> in alphabetical order.

Sorting TimeZones

Now we have time zone information in alphabetical form, but we need to have this information sorted on the offset from GMT time (bias). There are several ways to do this, but I have selected qsort() function. We need to supply the starting address of the array and a callback comparison function which will get called when sorting the CArray.

We need to pass the address of the first element of CArray and a comparison function to qsort(). The comparison function will decide the criteria on which we will sort the code. We need to sort time zones based on the offset from GMT or standard bias.

int CTimeZoneInfoManager::SortTimeZoneList()
TimeZoneComparer(const void *i_TZ1, const void *i_TZ2)

will have the related code.

FINALLY...THE TIME CONVERSION

The following APIs do the necessary conversion from local time in given TimeZone to universal time.

  • TzSpecificLocalTimeToSystemTime()
  • SystemTimeToTzSpecificLocalTime()

The SystemTimeToTzSpecificLocalTime() API takes TIME_ZONE_INFORMATION, Universal time as input and returns localtime which corresponds to supplied TIME_ZONE_INFORMATION. We will fill this TIME_ZONE_INFORMATION structure from the information we retrieved from the registry. One particular thing we need to be careful here is that the information we collected from registry for "StandardName" and "DayLightName" is in ANSI form, but TIME_ZONE_INFORMATION requires these values to be in widechar or Unicode format, so we need to use MultiByteToWideChar() and WideCharToMultiByte() functions to do the necessary conversions wherever necessary.

The TzSpecificLocalTimeToSystemTime() API does exactly the reverse of the above API, that is, it takes TIME_ZONE_INFORMATION and the corresponding local time as input and converts to universal time. But unfortunately, this is available only on XP and later OS versions!(to compile the code under XP, please uncomment "//#define _XP_OR_LATER" in TimeZoneInfoManager.cpp)

For the OS versions below XP, we can convert local time of currenttimezone to universal time using code like this:

int CTimeZoneInfoManager::SpecificLocalTimeToSystemTime
	(SYSTEMTIME* i_stLocal, SYSTEMTIME* o_stUniversal)
{

    FILETIME ft, ft_utc;

    if (!(SystemTimeToFileTime(i_stLocal, &ft) && 
          LocalFileTimeToFileTime(&ft, &ft_utc) &&
          FileTimeToSystemTime(&ft_utc,o_stUniversal)))
         {
            return 0;
         }

        return 1;
}

But SpecificLocalTimeToSystemTime() has other limitations too. It always considers daylight bias to be -60 and there may be a difference in behaviour of TzSpecificLocalTimeToSystemTime() and SpecificLocalTimeToSystemTime() in case of daylight savings.

The following functions have related code:

  • int CTimeZoneInfoManager::ConvertFromLocalToUTC()
  • int CTimeZoneInfoManager::ConvertFromUTClToLocal()

Sample Application

The application has very basic GUI. I have used simple datetimepicker control for I/O purposes of date and time. We can choose the option of converting UTCtoLocal or LocalToUTC from the provided radio buttons. Based on the selection, datepicker used for I/P gets enabled and datepicker used for O/P gets disabled. Whenever there is a change in the I/P, output changes automatically. We can select the required timezone from the combobox.

Conclusion

I hope this would help atleast some programmers who are looking for information related to timezones and timezone conversions.

History

  • 2nd January, 2006: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ramesh Ketha



United States United States

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralRegarding Local Time to UTC conversion Pinmemberdhdfghdfhdfhg2:49 9 Sep '08  
AnswerRe: Regarding Local Time to UTC conversion Pinmemberprantlf3:14 4 Sep '09  
QuestionHow to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmembertrysunil17:24 13 Apr '08  
AnswerRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmembertrysunil19:54 13 Apr '08  
GeneralRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP PinmemberAnatoly Ivasyuk11:56 29 Aug '08  
GeneralRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP PinmemberHugh Jizak11:17 16 Dec '08  
GeneralRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmemberehsiung14:17 4 Jan '09  
GeneralRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmembertrysunil14:33 4 Jan '09  
QuestionRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP PinmemberZhi Chen7:06 9 Feb '09  
AnswerRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmembertrysunil15:13 9 Feb '09  
QuestionRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP PinmemberZhi Chen11:24 13 Feb '09  
AnswerRe: How to make the TzSpecificLocalTimeToSystemTime work for Os < Win XP Pinmemberehsiung8:11 12 Jun '09  
GeneralInvalid Property Value Pinmemberwhoisthis8:40 4 Jan '06  
GeneralRe: Invalid Property Value PinmemberBrian (BH)0:15 11 Jan '06  
The problem lies in the function CTimeZoneInfoManager::ConvertFromLocalToUTC(). The if/else statement that decides which conversion function to use depending on the current operating system is at fault. The "else" clause only gets compiled if you define the _XP_OR_LATER macro, so if you run this on XP after compiling without this flag no conversion actually takes place!
 
In any case, if you compile this for XP it won't run on an earlier version of windows (the exe won't be able to load) so the whole "if" statement is redundant and should be replaced with the code below.
 
#if _WIN32_WINNT >= 0x0501
//available only on XP and Later
TzSpecificLocalTimeToSystemTime(&tzi,&localTime,&universalTime);
#else
// always available
SpecificLocalTimeToSystemTime(&localTime, &universalTime);
#endif
 
This will allow the programmer to use the newer function when compiling for XP and above, or the more generic function if he want's to support earlier versions of windows.
 
Having said all that, the function SpecificLocalTimeToSystemTime() doesn't seem to work anyway! I think it only converts the time between the current locale for the system and UTC, instead of using the selected locale! Maybe it should change the current locale to the selected one temporarily, do the conversion and then change back.

GeneralRe: Invalid Property Value Pinmembershadow7921:25 19 Jul '06  
GeneralRe: Invalid Property Value PinmembermacALEX20:02 28 Sep '06  
GeneralRe: Invalid Property Value Pinmemberp4abit1:49 24 Apr '07  
GeneralRe: Invalid Property Value PinmemberArunKumar Yalamarthy21:23 22 May '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120210.1 | Last Updated 3 Jan 2006
Article Copyright 2006 by Ramesh Ketha
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid