converting between UTC and localtime (Linux)

Posted on 2008-10-26
Last Modified: 2012-05-05
I'm working with libecal to manage and add events to Evolution. Evolution date/time events are set to UTC timezone. No matter what i do the events in the calendar are always entered according to the UTC,
so, for example, if i have a struct tm and i fill it with the following values:

       timestart.tm_year = 2008 - 1900;
       timestart.tm_mon = 11 - 1;
       timestart.tm_mday = 9;
       timestart.tm_hour = 12;
       timestart.tm_min = 00;
       timestart.tm_sec = 00;
       timestart.tm_isdst = -1;

instead of entering the event (appointment) on 11/09/1008 12:00 PM it will be set at 11/09/2008 10:00 AM because UTC is -2hs

i tried different approaches like

   time_t now = time(NULL);
   struct tm lcl = *localtime(&now);
   struct tm gmt = *gmtime(&now);

and then comparing the two values at lcl.tm_hour and gmt.tm_hour and fixing struct tm accordingly but it gets really messy.

how can i convert UTC timezone to the local timezone and fill the tm struct with the proper values?

(or if anyone know how to do it specifically for the libecal even better...)

Question by:urif
  • 2
  • 2
LVL 23

Accepted Solution

Mysidia earned 100 total points
ID: 22807918
You convert UTC calendar time to a 'struct tm'  in UTC  by calling gmtime().
UTC calendar time is a 'time_t'  integer variable which represents number of second since Jan 1, 1970.

You convert UTC calendar time to a 'struct tm'  representing the time in the LOCAL time zone by calling localtime().

You convert a  'tm'  structure to calendar time by calling the 'mktime()' function and taking its result.

So for example, if you have a timestamp 'now'  that you want to convert into a localtime structure
   struct tm lcl = *localtime(&now);

is correct.

If you want to convert 'lcl'  back to UTC 'calendar time' then you use

   time_t newtimestamp = mktime(lcl);

If you want to  change a tm structure manually IN THE LOCAL TIMEZONE,  I suggest you use localtime()  to fill it with values represented in the local timezone.

Then make your adjustments.
Use mktime()  to convert the structure to a 'time_t'  UTC calendar time value.

Then lastly call  gmtime()   and get its result, which is a 'struct tm' of the time in UTC.

 time_t now = time(0);
 struct tm X = *localtime(&now);
  /* make your changes to X */
 time_t  newtime  = mktime(&X);

 struct tm InUTC = *gmtime(&newtime);


Author Comment

ID: 22810746
ok, let me check and i'll get back to you shortly.

i assume the X.tm_hour has the local timezone hour and InUTC.tm_hour the UTC timezone? is that correct?

Author Comment

ID: 22811199
well, i tried it. it does give me the time in UTC and localtime, the same as the sample i wrote in the question:

 time_t now = time(NULL);
   struct tm lcl = *localtime(&now);
   struct tm gmt = *gmtime(&now);

now, i computer the difference (in my case 2hr) and when i add that difference to the struct tm and convert it to time_t i still get a different date or time or a segfault.

the idea is not to get the "now" time/date but a specific date filled by the user. while this sample works more of less for the "now" it still fails when i have to convert a struct tm that was filled with a specific date
LVL 23

Expert Comment

ID: 22811736
Use  localtime()  to fill in the 'struct tm'  initially.  

Then change values in the 'struct tm'  you  got with localtime()    to what the user input and  THEN proceed with the conversion  to a time_t using  mktime().

All fields must be properly filled in  (including some time zone fields)  in order for mktime()  to work correctly.

It's impossible to tell without seeing what code you are attempting to use, but a most likely reason for a segfault is that  the call to   gmtime()  or localtime()  fails

These functions may fail and return a null pointer if the 'struct tm'   isn't completely populated.

Dereferencing a null pointer causes a segfault.


Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

821 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