parsing time string, getting timezone

I

Ilja Booij

Hi all,

I have some trouble with the following:

I'm getting a time string, in YYYY-MM-DD HH:mm:ss format, which I
need to translate into a string with DD-Mon-YYYY HH:mm:ss +HHMM,
where the last part is the timezone offset.

I've tried to do it with the following function. This works for me,
I get +0200 for the timezone part, which makes sense, because we're
on daylight savings time at the moment here in the Netherlands.
However, another user of the same code is located in Australia, he
gets +1100 as timezone offset. It's winter out there now, and at the
moment he's really at +1000. All his other software does it in the
right way. So... what am I doing wrong?

char *date_sql2imap(const char *sqldate)
{
char *last_char;
struct tm tm_localtime, tm_sqldate;
time_t td;

/* we need to get the localtime to get the current timezone */
if (time(&td) == -1) {
trace(TRACE_ERROR, "%s,%s: error getting time()",
__FILE__, __func__);
return IMAP_STANDARD_DATE;
}
tm_localtime = *localtime(&td);
/* parse sqldate */
last_char = strptime(sqldate, "%Y-%m-%d %T", &tm_sqldate);
if (*last_char != '\0') {
trace(TRACE_DEBUG, "%s,%s, error parsing date [%s]",
__FILE__, __func__, sqldate);
strcpy(_imapdate, IMAP_STANDARD_DATE);
return _imapdate;
}
tm_sqldate.tm_gmtoff = tm_localtime.tm_gmtoff;
(void) strftime(_imapdate, IMAP_INTERNALDATE_LEN,
"%d-%b-%Y %T %z", &tm_sqldate);
return _imapdate;
}

Thanks for your time,
Ilja Booij
 
T

Targeur fou

Ilja said:
Hi all,
Hi,


I have some trouble with the following:

I'm getting a time string, in YYYY-MM-DD HH:mm:ss format, which I
need to translate into a string with DD-Mon-YYYY HH:mm:ss +HHMM,
where the last part is the timezone offset.

I've tried to do it with the following function. This works for me,
I get +0200 for the timezone part, which makes sense, because we're
on daylight savings time at the moment here in the Netherlands.
However, another user of the same code is located in Australia, he
gets +1100 as timezone offset. It's winter out there now, and at the
moment he's really at +1000. All his other software does it in the
right way. So... what am I doing wrong?

char *date_sql2imap(const char *sqldate)
{
char *last_char;
struct tm tm_localtime, tm_sqldate;

Since most of time functions ask for pointers to struct tm, I would have
used struct tm * variables instead.
time_t td;

/* we need to get the localtime to get the current timezone */
if (time(&td) == -1) {
trace(TRACE_ERROR, "%s,%s: error getting time()",
__FILE__, __func__);
return IMAP_STANDARD_DATE;
}
tm_localtime = *localtime(&td);

IMHO, what I said above could have led in perhaps more readable code
with tm_localtime = localtime(&td); /* assuming struct tm* tm_localtime */
/* parse sqldate */
last_char = strptime(sqldate, "%Y-%m-%d %T", &tm_sqldate);

strptime is not part of C standard functions, it's a POSIX/Unix one.
According to the documentation I found on the Internet (
http://www.opengroup.org/onlinepubs/009695399/functions/strptime.html ),
strptime returns a null pointer in case of failure. It would have been
more readable to test with NULL below.
if (*last_char != '\0') {
if (last_char == NULL) {
trace(TRACE_DEBUG, "%s,%s, error parsing date [%s]",
__FILE__, __func__, sqldate);
strcpy(_imapdate, IMAP_STANDARD_DATE);
return _imapdate;
}
tm_sqldate.tm_gmtoff = tm_localtime.tm_gmtoff;

I didn't see a such member (tm_gmtoff) in a tm structure (C or POSIX).
What I know is that there is a required flag for daylight, a tm member
named tm_isdst. tm_isdst (int)is positive if daylight is used, zero if
daylight is'nt used or negative if this information isn't available. My
advice would be to use tm_isdst (and check its value) instead of
tm_gmtoff, knowing that tm_isdst isn't modified by strptime. Time and
date handling is very implementation dependent thus my last advice is to
keep your code compliant with the C Standard as much as possible.
Personally, in your date_sql2imap function, the only non C standard
stuff that I would have used is strptime.
(void) strftime(_imapdate, IMAP_INTERNALDATE_LEN,
"%d-%b-%Y %T %z", &tm_sqldate);
return _imapdate;
}

Finally, here is the code of a little program that you can share with
your australian collegue to compare values:

___________________________________

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(void)
{
time_t time_Calendar;
struct tm * time_Local;
char bufferLocalTime[100];
size_t nbWrittenChars;

if (time(&time_Calendar) == (time_t)-1)
{
fprintf(stderr, "Couldn't retrieve the calendar time\n");
exit(EXIT_FAILURE);
}

time_Local = localtime(&time_Calendar);
if (time_Local == NULL)
{
fprintf(stderr, "Couldn't retrieve the local time\n");
exit(EXIT_FAILURE);
}

memset(bufferLocalTime, 0, sizeof bufferLocalTime);
nbWrittenChars = strftime(bufferLocalTime,
sizeof bufferLocalTime,
"%d-%b-%Y %T",
time_Local);

/* Check the daylight flag */
if (time_Local->tm_isdst > 0)
{
printf("The daylight flag is used, time_Local->tm_isdst = %d\n",
time_Local->tm_isdst);
}
else
{
if (time_Local->tm_isdst == 0)
{
printf("The daylight flag is NOT used, time_Local->tm_isdst=%d\n",
time_Local->tm_isdst);
}
else
{
printf("Daylight information is unavailable,"
"time_Local->tm_isdst=%d\n",
time_Local->tm_isdst);
}
}

if (nbWrittenChars > 0)
{
puts(bufferLocalTime);
}
else
{
fprintf(stderr, "strftime failed to write the local time\n");
exit(EXIT_FAILURE);
}

return EXIT_SUCCESS;

}



Cheers,

Regis
 
T

Targeur fou

Targeur said:
Erratum,


memset(bufferLocalTime, 0, sizeof bufferLocalTime);
nbWrittenChars = strftime(bufferLocalTime,
sizeof bufferLocalTime,
"%d-%b-%Y %T",
time_Local);

[snipped]

nbWrittenChars = strftime(bufferLocalTime,
sizeof bufferLocalTime,
"%d-%b-%Y %T %z",
time_Local);

[snipped]

By the way, have a look to the tzset() POSIX function and its associated
external variables to handle timezone informations in a "quite" portable
manner.
http://www.opengroup.org/onlinepubs/009695399/functions/tzset.html
 
I

Ilja Booij

By the way, have a look to the tzset() POSIX function and its associated
external variables to handle timezone informations in a "quite" portable
manner.
http://www.opengroup.org/onlinepubs/009695399/functions/tzset.html

first of all, thanks for your answer!

tm_gmtoff is a BSD & GNU extension, so definetly not ISO or POSIX
C.

Anyway. I've tried to use your recommendations for changing the function, but
I cannot see how I should do it.

Can you shed some light on how I should change this function to return a string
with the right timezone? Using tm_isdst I can see whether it's daylight savings
time or not, but I wouldn't know how to use that information in the string..

I know, I should be able to figure this out by myself.. I've been ill the last
2 days, and my brain hasn't been fully reconnected yet I guess..

Thanks
Ilja
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top