Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting between timezones in C

Tags:

c

timezone

I need to convert time between timezones in C (on linux, so anything specific would do too).

I know my current time, local and UTC, I have the offset of the target time. I am trying to use mktime, gmtime, localtime and similar set of functions but still can't figure it out.

Thanks in advance.

like image 642
verma Avatar asked Jul 23 '09 18:07

verma


2 Answers

As comments do not allow posting the code, posting as a separate answer.. If you know "local" time and "UTC" time, you can calculate the offset of the "other" time from your "local" time. Then you convert the struct tm into calendar time, add the desired number of seconds (being the offset of the target time), and convert it back to struct tm:

(edited to account for another scenario to use mktime's normalization)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char *argv) {
  struct timeval tv_utc;
  struct tm *local_tm, *other_tm;

  /* 'synthetic' time_t to convert to struct tm for the other time */
  time_t other_t_synt;
  /* Other time is 1 hour ahead of local time */
  int other_local_delta = 1*3600; 


  /* the below two lines are just to set local_tm to something */
  gettimeofday(&tv_utc, NULL);
  local_tm = localtime(&tv_utc.tv_sec);

  printf("Local time: %s", asctime(local_tm));

  #ifdef DO_NOT_WRITE_TO_LOCAL_TM
  other_t_synt = mktime(local_tm) + other_local_delta;
  #else
  local_tm->tm_sec += other_local_delta;
  /* mktime will normalize the seconds to a correct calendar date */
  other_t_synt = mktime(local_tm);
  #endif

  other_tm = localtime(&other_t_synt);

  printf("Other time: %s", asctime(other_tm));

  exit(0);
}
like image 169
Andrew Y Avatar answered Sep 30 '22 05:09

Andrew Y


You can use gmtime() and the tm structure to directly set this, provided you know the offsets.

If you know your local time and UTC, you know your local offset. Provided you also know the target offset, it's just a matter of setting tm_hour appropriate (and potentially flipping the day, too, if you go <0 or >23).

For some sample code, see this gmtime reference page. It shows offsetting based off time zone offsets.


Edit:

In response to the comments - you can also let mktime handle the shifting for you, which allows you to simplify this by converting back to a time_t. You can use something like:

time_t currentTime;
tm * ptm;
time ( &currentTime );
ptm = gmtime ( &rawtime );
ptm->tm_hour += hours_to_shift;
ptm->tm_minutes += minutes_to_shift; // Handle .5 hr timezones this way

time_t shiftedTime = mktime( ptm );
// If you want to go back to a tm structure:

tm * pShiftedTm = gmtime( &shiftedTime );
like image 45
Reed Copsey Avatar answered Sep 30 '22 05:09

Reed Copsey