Timezone problem


M

mimmo

I have a problem while calculating timezone (from Europe/Rome to
Brazil/East).
Can someone help me ??
Thank you,
Mimmo.

On this site
http://www.timezoneconverter.com/cgi-bin/tzc.tzc

I have for this date 2003/01/01 00:00:00:
00:00:00 Wed Jan 01 2003 in Europe/Rome converts to
21:00:00 Tue Dec 31 2002 in Brazil/East

DST* is not in effect on this date/time in Europe/Rome
DST* is in effect on this date/time in Brazil/East
*Daylight Saving Time

On Unix:
tmpbuf:2003/01/01 00:00:00 <-------------date
t_time.tm_isdst:0 <------------Daylight Saving Time flag
Time in seconds: 1041375600 <------------julian date
Local time: Tue Dec 31 21:00:00 2002 <-----------local time in
Brazil/East
t_time.tm_isdst:1 <-----------Daylight Saving Time flag
tmpbuf:2002/12/31 21:00:00
**************************************
Result seems OK
**************************************

Instead for date 2003/08/08 13:48:23 I have:
13:48:23 Fri Aug 08 2003 in Europe/Rome converts to
08:48:23 Fri Aug 08 2003 in Brazil/East

DST* is in effect on this date/time in Europe/Rome
DST* is not in effect on this date/time in Brazil/East
*Daylight Saving Time

but on Unix there's a difference of one hour:
tmpbuf:2003/08/13 13:48:19
t_time.tm_isdst:1
Time in seconds: 1060778899
Local time: Wed Aug 13 09:48:19 2003 (!!!!!!!!!!)
localt.tm_isdst:0
tmpbuf:2003/08/13 09:48:19 (!!!!!!!!!!)
**************************************
Result is not right!!!!!!!
**************************************

This is my code for testing it:
#include <time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <string.h>


int timezoneconverter(char *local_tz, char *tz, char *string_date,
char *format_date, char **result_date)
{
char buf[256];
struct tm t_time;
struct tm *pt_time, *localt;
time_t julian_date = -1;
int ret = -1;

tzset();
memset(&buf, 0, sizeof(buf) );
memset(&t_time, 0, sizeof(struct tm) );
t_time.tm_isdst = -1;

string_date = strptime(string_date, format_date, &t_time);
if (NULL == string_date) {
printf("string_date null\n");
return (-1);
}

julian_date = mktime(&t_time);
if(-1 == julian_date) {
return (-1);
}

printf("t_time.tm_isdst:%d\n", t_time.tm_isdst);

strcpy(buf, "TZ=");
strcat(buf, tz);
putenv(buf);

printf( "Time in seconds:\t%ld\n", julian_date );
localt = (struct tm *) localtime(&julian_date);
if (NULL == (struct tm *) localt) {
return (-1);
}
printf( "Local time:\t\t%s", asctime(localt));

printf("localt.tm_isdst:%d\n", localt->tm_isdst);

memset(&buf, 0, sizeof(buf) );
ret = strftime(buf, sizeof(buf), format_date, localt);
if (0 == ret) {
printf("strftime error\n");
return (-1);
}

*result_date = strdup(buf);

/* Setting old TZ value */
memset(&buf, 0, sizeof(buf) );
strcpy(buf, "TZ=");
strcat(buf, local_tz);
putenv(buf);

return (0);
}

int main()
{
char tmpbuf[128], ampm[] = "AM";
char *tmp = NULL;

printf("----->Europe/Rome to Brazil/East<-----\n");
strcpy(tmpbuf, "2003/01/01 00:00:00");
printf("tmpbuf:%s\n", tmpbuf);
timezoneconverter("Europe/Rome", "Brazil/East", tmpbuf, "%Y/%m/%d
%H:%M:%S", &tmp);
strcpy(tmpbuf, tmp);
printf("tmpbuf:%s\n", tmpbuf);

printf("----->Europe/Rome to Brazil/East<-----\n");
strcpy(tmpbuf, "2003/08/13 13:48:19");
printf("tmpbuf:%s\n", tmpbuf);
timezoneconverter("Europe/Rome", "Brazil/East", tmpbuf, "%Y/%m/%d
%H:%M:%S", &tmp);
strcpy(tmpbuf, tmp);
printf("tmpbuf:%s\n", tmpbuf);

return(0);

}
 
Ad

Advertisements

D

Dave Thompson

I have a problem while calculating timezone (from Europe/Rome to
Brazil/East). <snip>
On this site
http://www.timezoneconverter.com/cgi-bin/tzc.tzc <snip>
On Unix: <snip>
Result seems OK
**************************************

Instead for date 2003/08/08 13:48:23 I have: <snip>

BTW- "Instead" is not really right here, since this isn't intended to
be the same as the first case. Better "In contrast".
but on Unix there's a difference of one hour: <snip>
tmpbuf:2003/08/13 13:48:19
t_time.tm_isdst:1
Time in seconds: 1060778899
Local time: Wed Aug 13 09:48:19 2003 (!!!!!!!!!!)
localt.tm_isdst:0
tmpbuf:2003/08/13 09:48:19 (!!!!!!!!!!)
**************************************
Result is not right!!!!!!!

Your mktime appears to have gone wrong; the POSIX-time_t value
1060778899 is 12:48:19 UTC, but it should be 1 hour less for
Europe/Rome during DST, i.e. +2 instead of +1. Given that (wrong)
time_t value the conversion to Brazil/East local struct tm is correct.
<picky> OK, theoretically POSIX-time_t is adjusted-TAI not UTC, but in
practice that doesn't matter. </>

Since your zone settings suggest your system is using or based on the
Olson time library, you might try zdump -v Europe/Rome and make sure
it is correct. If it isn't, you might try a group or forum for your
OS, which you didn't specify; or (e-mail address removed), preferably
after subscribing at tz-request, and specifying your system.
**************************************

This is my code for testing it:

and some comments (mostly nitpicks) thereon.
#include <time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <string.h>
You're not actually using anything from types.h or timeb.h, and if you
were they would be off-topic for clc.
int timezoneconverter(char *local_tz, char *tz, char *string_date,
char *format_date, char **result_date)

You could use const on the input parameters.
{
char buf[256];
struct tm t_time;
struct tm *pt_time, *localt;
time_t julian_date = -1;
int ret = -1;

tzset();

tzset, and strptime and putenv and strdup below, are not standard C
but are POSIX, and hence considered off-topic in clc but on-topic in
comp.unix.programmer (or a group for a specific OS).
memset(&buf, 0, sizeof(buf) );
memset(&t_time, 0, sizeof(struct tm) );

It is possible, simpler, and preferred by clc to instead initialize in
the declaration: struct tm t_time = {0}; This also handles the very
theoretical possibility that some fields in the struct have a type for
which all-bits-zero is a trap representation.

Similarly for buf, except for the trap-rep issue (all-bits-zero must
be zero for all char types), but in fact you don't need to initialize
buf at all since you proceed to ignore its initial value.
t_time.tm_isdst = -1;

string_date = strptime(string_date, format_date, &t_time);
if (NULL == string_date) {
printf("string_date null\n");
return (-1);
}
While it is true that string_date is null in that branch, it would be
more useful to explain what led to it: "strptime failed" or even
something like "input string did not parse correctly".
julian_date = mktime(&t_time);
if(-1 == julian_date) {
return (-1);
}
This variable name is confusing; the time_t value here is not a Julian
date by either of the definitions of that word.
printf("t_time.tm_isdst:%d\n", t_time.tm_isdst);

strcpy(buf, "TZ=");
strcat(buf, tz);
putenv(buf);
Even in POSIX, I don't believe it is guaranteed that putenv of TZ
controls subsequent time-related library calls unless you do tzset
again. This would be on topic in comp.unix.programmer. It seems
unlikely to me this would cause exactly your symptoms, but you might
try it just in case.
printf( "Time in seconds:\t%ld\n", julian_date );

time_t is not actually guaranteed to be (signed) long, or in seconds,
though it is on most systems obviously including yours.
localt = (struct tm *) localtime(&julian_date);
if (NULL == (struct tm *) localt) {
return (-1);
}
printf( "Local time:\t\t%s", asctime(localt));

printf("localt.tm_isdst:%d\n", localt->tm_isdst);

memset(&buf, 0, sizeof(buf) );

Again you don't need to (re)initialize buf before strftime'ing to it.
ret = strftime(buf, sizeof(buf), format_date, localt);
if (0 == ret) {
printf("strftime error\n");
return (-1);
}

*result_date = strdup(buf);
Your test driver, snipped, never free's these strings, leaving a leak.
It might be preferable to write directly into a/the caller's buffer
rather than using dynamic memory. Then again it might not.
/* Setting old TZ value */
memset(&buf, 0, sizeof(buf) );

And again before strcpy.


- David.Thompson1 at worldnet.att.net
 

Top