How to convert one country time stamp into another country timestamp without using tzset() and handle DST properly in C?

176 views Asked by At

Lets assume my application is running in one country(src : India), My friends who live in European country wants to read some specific data from my application in his country time stamp i.e german timestamp. If my friend's country lends in DST(Day light saving), my application shall handle that as well.

Below are steps I've followed.

  • Step-1 : converted system time(IST) to UTC time, sine application is running in India.
  • Step-2 : Added UTC+01:00 offset to UTC time derived in step-1 to get the German local time.
  • Step-3 : Here I've got the German local time, but my application timezone is still IST not CET. How to change it to CET so that I can check tm_isdst flag whether DST is in place or not and adjust the time back or forth by 1 hour. Note that I'm not allowed to use tzset() or any timezone environment variable.

Sample code :

/* step-1 : get the system time */
time_t now = time(NULL);
struct tm *systemTime = localtime(&now);
printf("step-1 system time [%s] timezone[%s]\n", asctime(systemTime), (char*)systemTime->tm_zone);

/* step-2 : get the UTC time */
struct tm *utcTime = gmtime(&now);//return utc
printf("step-2 UTC time [%s] timezone[%s]\n", asctime(utcTime), (char*)utcTime->tm_zone);

/*  step-3 : get the local Berlin/German time from UTC time */
time_t localGermanTime = mktime(utcTime);
struct tm *localGermanTimeTm = localtime(&localGermanTime);
localGermanTimeTm->tm_zone = "CEST"; //Failed : Tried forcefully setting but next mktime() call reset it
localGermanTimeTm->tm_hour += 1; //+01:00 (lets assume german time is UTC+01:00)
localGermanTimeTm->tm_min += 0;
//added mktime to normalize above manipulation 
time_t normalizeTimeRet = mktime(localGermanTimeTm);
struct tm* localGermanTimeTmAdjusted = localtime(&normalizeTimeRet);
if(normalizeTimeRet == -1)
{
    printf("mktime() normalize went in-correct");
}

/*  step-4 : Adjust the DST */
if(localGermanTimeTmAdjusted->tm_isdst) //problem is this localGermanTimeTmAdjusted is having the germany current time but time zone is still IST so this didn't hit
{
    /*  adjust the hours by +1 */
    localGermanTimeTmAdjusted->tm_hour += 1;
    printf("step-4 local german/other time is in DST timezone[%s]\n", (char*)localGermanTimeTmAdjusted->tm_zone);
}
else
{
    printf("local german/other time is not in DST\n");
}
/* step-5 : Normalize above result by calling mktime() */
time_t normalizeTimeDstRet = mktime(localGermanTimeTmAdjusted);
struct tm* localGermanTimeTmDstAdjusted = localtime(&normalizeTimeDstRet);

printf("step-5 german/other time after normalizing DST [%s] timezone [%s]\n", asctime(localGermanTimeTmDstAdjusted), (char*)localGermanTimeTmDstAdjusted->tm_zone);

Above is achievable with tzset() but since one part of application where user tried to read some data, that is happening very frequently hence I can't use the tzset() as this will impact the performance.

Sample code o/p:

[root@achal appAchal]# date && ./a.out
Tue Oct 19 16:25:23 IST 2021
step-1 system time [Tue Oct 19 16:25:23 2021] timezone[IST]
step-2 UTC time [Tue Oct 19 10:55:23 2021] timezone[GMT]
local german/other time is not in DST
step-5 german/other time after normalizing DST [Tue Oct 19 11:55:23 2021] timezone [IST]
0

There are 0 answers