parsing time string, getting timezone

Discussion in 'C Programming' started by Ilja Booij, Sep 8, 2004.

  1. Ilja Booij

    Ilja Booij Guest

    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

    --
    Ilja Booij
    IC&S B.V.
     
    Ilja Booij, Sep 8, 2004
    #1
    1. Advertising

  2. Ilja Booij

    Targeur fou Guest

    Ilja Booij wrote:
    > 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
     
    Targeur fou, Sep 8, 2004
    #2
    1. Advertising

  3. Ilja Booij

    Targeur fou Guest

    Targeur fou wrote:
    >


    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
     
    Targeur fou, Sep 9, 2004
    #3
  4. Ilja Booij

    Ilja Booij Guest

    In article <cho55h$j94$>, Targeur fou wrote:
    >
    >
    > Targeur fou wrote:
    >>

    >


    <snip code>

    >
    > 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
     
    Ilja Booij, Sep 10, 2004
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. asaf
    Replies:
    3
    Views:
    6,207
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Sep 11, 2006
  2. axrock
    Replies:
    8
    Views:
    986
    Roedy Green
    Mar 25, 2009
  3. Paul Brannan

    parsing a time in a specific timezone

    Paul Brannan, Feb 23, 2005, in forum: Ruby
    Replies:
    5
    Views:
    121
    Navindra Umanee
    Feb 23, 2005
  4. David Joseph Bonnici
    Replies:
    1
    Views:
    226
    Gunnar Hjalmarsson
    May 15, 2005
  5. Ami
    Replies:
    5
    Views:
    301
Loading...

Share This Page