Thread: strptime and gmtime

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    9

    strptime and gmtime

    Is it possible to first build a time (populate the tm structure) using strptime and then get the gmtime() of that time. I have a function that receives a time in the format 'YYYY-MM-DD HH:MMD' and a timezone 'EST5EDT' and I need to get the GMT time for the passed time based on the timezone. I'm trying to use strptime for the time passed to load the tm struct and then get the gmtime of that using gmtime(). Is this possible? Keep running into road bloacks
    int function (const char* time, const char* timezone)struct tm tm;
    time_t t;

    if (strptime("2013-10-11 12:33:45", "%Y %M %D %H:%M:%S", &tm) == NULL)
    /* Handle error */;

    now I want to get the gmtime. Is this possible? Is there another way?

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Welcome to the forum, wjblack!

    You're telling me what you're currently trying to use in the C toolbox, that isn't working. I don't need to know that.

    Give me an example: This is what I have - XXXXXXXX and this is what I need - XXXXXXXXX.

    That is all.

  3. #3
    Registered User
    Join Date
    Oct 2013
    Posts
    9
    I need to build a function that will translate an incoming time stamp (param 1) and time zone (param 2) to a passed time zones GMT/UTC time. The time stamp can be in a few different formats so this is why I was trying to use strptime().

    Ex) function (const char* time,
    const char* timezone) or function ("2013-10-10 15:36:01", "EST5EDT")

    would yield '
    2013-10-10 15:36:01'

    In addition to this I need to build a separate function that will take the original time stamp and time zone and return just the offet (Ex. UTC + 5)

    function2 (const char* time, const char* timezone)
    would yield '5'


    Here is what I tried so far:

    struct tm parsed_time;
    strcpy(timestring,"2013-10-10 15:36:01");
    strptime(timestring, "%Y-%m-%d %H:%M:%S", &parsed_time);//this builds the tm struct


    putenv("TZ=EST5EDT");
    tzset();

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Here is what I tried so far:
    1) I don't care what you've tried so far.

    2) You want a GMT time from this format of a time stamp:
    2013-10-10 15:36:01

    Do you want the GMT time to be in this same format, or a different format, or does it matter?


    3) And the local offset of that system.

    4) Please post with plain text ONLY. All the font and colors adds up to a pile of horse........, in the forum, when someone wants to quote you.

  5. #5
    Registered User
    Join Date
    Oct 2013
    Posts
    9
    1) I don't care what you've tried so far.
    OK, didn't realize extra was a problem

    2) You want a GMT time from this format of a time stamp:
    2013-10-10 15:36:01

    Yes

    Do you want the GMT time to be in this same format, or a different format, or does it matter?
    Yes, same format

    3) And the local offset of that system.
    local offset depending on the timezone passed

    4) Please post with plain text ONLY. All the font and colors adds up to a pile of horse........, in the forum, when someone wants to quote you.
    Not sure what colors your seeing as it's all in black and white on my side.

    Thanks for your assistance.

  6. #6
    Registered User
    Join Date
    Oct 2013
    Posts
    9
    Quote Originally Posted by wjblack View Post
    1) I don't care what you've tried so far.
    OK, didn't realize extra was a problem

    2) You want a GMT time from this format of a time stamp:
    2013-10-10 15:36:01

    Yes

    Do you want the GMT time to be in this same format, or a different format, or does it matter?
    Yes, same format

    3) And the local offset of that system.
    local offset depending on the timezone passed

    4) Please post with plain text ONLY. All the font and colors adds up to a pile of horse........, in the forum, when someone wants to quote you.
    Not sure what colors your seeing as it's all in black and white on my side.

    Thanks for your assistance.
    To add to the above post, I also have to factor in DST (Daylight Savings Time) depending on the time zone passed. gmtime seems like a potential candidate. Please advise.

  7. #7
    .
    Join Date
    Nov 2003
    Posts
    307
    We seem to be talking past each other.

    You should call tzset() with the timezone of the input data. Then call strptime() with the time/date string only, no TZ string.
    As a matter of procedure call tzset() for each call to strptime(). It is safer that way.

    Now you have a struct tm. What do you want - GMT time and date? In other words convert from any input TZ to GMT?
    You do not have to mess with DST, gmtime (or localtime) correct for that. If your tzset() call was made beforehand.

    Beyond that I do not understand this thread very well.

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    tzset() will set his local time zone, to the the timezone abbreviation string he has been sent, is what you're saying, Jim?

    Then after using strptime() with the proper string, and no TZ string, his local system will show that info so gmtime and localtime can correct for it.

    Afterward, he doesn't need to reset tzset() with his own local time zone, because it was never changed in his environment.

    That would be by far the easiest way to do this.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This will set the environment, on POSIX (Linux, UNIX, etc.) compilers. I have found the equivalent for Windows, but it's not standard C, so your compiler may not support it.

    Code:
    //For POSIX compilers, only
    /* CELEBT17
    
       This example set time conversion information for
       Eastern Standard and Eastern Daylight Savings Time in the
       United States.
    
     */
    #define _POSIX_SOURCE
    #include <env.h>
    #include <time.h>
    
    int main(void)
    {
    
       setenv("TZ", "EST5EDT", 1);
       tzset();
    }
    Are you using a POSIX compliant compiler, wj?

    This is a large example which includes what you want, btw. From Microsoft for Windows 7, etc.
    From:
    http://msdn.microsoft.com/en-us/library/1f4c8f33.aspx
    Code:
    time, _time32, _time64
    Visual Studio 2012
    Other Versions
    1 out of 1 rated this helpful
    
    Get the system time.
    
    time_t time(
       time_t *timer 
    );
    __time32_t _time32(
       __time32_t *timer 
    );
    __time64_t _time64(
       __time64_t *timer 
    );
    
    Parameters
    
    timer
    
        Pointer to the storage location for time.
    
    Return Value
    
    Return the time as seconds elapsed since midnight, January 1, 1970, or -1 in the case of an error.
    Remarks
    
    The time function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970, Coordinated Universal Time (UTC), according to the system clock. The return value is stored in the location given by timer. This parameter may be NULL, in which case the return value is not stored.
    
    time is a wrapper for _time64 and time_t is, by default, equivalent to __time64_t. If you need to force the compiler to interpret time_t as the old 32-bit time_t, you can define _USE_32BIT_TIME_T. This is not recommended because your application may fail after January 18, 2038; the use of this macro is not allowed on 64-bit platforms.
    Requirements
    
    Routine
    	
    
    Required header
    
    time
    	
    
    <time.h>
    
    _time32 , _time64
    	
    
    <time.h>
    
    For additional compatibility information, see Compatibility in the Introduction.
    Example
    
    // crt_times.c
    // compile with: /W3
    // This program demonstrates these time and date functions:
    //      time         _ftime    ctime_s     asctime_s
    //      _localtime64_s    _gmtime64_s    mktime    _tzset
    //      _strtime_s     _strdate_s  strftime
    //
    // Also the global variable:
    //      _tzname
    //
    
    #include <time.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/timeb.h>
    #include <string.h>
    
    int main()
    {
        char tmpbuf[128], timebuf[26], ampm[] = "AM";
        time_t ltime;
        struct _timeb tstruct;
        struct tm today, gmt, xmas = { 0, 0, 12, 25, 11, 93 };
        errno_t err;
    
        // Set time zone from TZ environment variable. If TZ is not set,
        // the operating system is queried to obtain the default value 
        // for the variable. 
        //
        _tzset();
    
        // Display operating system-style date and time. 
        _strtime_s( tmpbuf, 128 );
        printf( "OS time:\t\t\t\t%s\n", tmpbuf );
        _strdate_s( tmpbuf, 128 );
        printf( "OS date:\t\t\t\t%s\n", tmpbuf );
    
        // Get UNIX-style time and display as number and string. 
        time( &ltime );
        printf( "Time in seconds since UTC 1/1/70:\t%ld\n", ltime );
        err = ctime_s(timebuf, 26, &ltime);
        if (err)
        {
           printf("ctime_s failed due to an invalid argument.");
           exit(1);
        }
        printf( "UNIX time and date:\t\t\t%s", timebuf );
    
        // Display UTC. 
        err = _gmtime64_s( &gmt, &ltime );
        if (err)
        {
           printf("_gmtime64_s failed due to an invalid argument.");
        }
        err = asctime_s(timebuf, 26, &gmt);
        if (err)
        {
           printf("asctime_s failed due to an invalid argument.");
           exit(1);
        }
        printf( "Coordinated universal time:\t\t%s", timebuf );
    
        // Convert to time structure and adjust for PM if necessary. 
        err = _localtime64_s( &today, &ltime );
        if (err)
        {
           printf("_localtime64_s failed due to an invalid argument.");
           exit(1);
        }
        if( today.tm_hour >= 12 )
        {
       strcpy_s( ampm, sizeof(ampm), "PM" );
       today.tm_hour -= 12;
        }
        if( today.tm_hour == 0 )  // Adjust if midnight hour.
       today.tm_hour = 12;
    
        // Convert today into an ASCII string 
        err = asctime_s(timebuf, 26, &today);
        if (err)
        {
           printf("asctime_s failed due to an invalid argument.");
           exit(1);
        }
    
        // Note how pointer addition is used to skip the first 11 
        // characters and printf is used to trim off terminating 
        // characters.
        //
        printf( "12-hour time:\t\t\t\t%.8s %s\n",
           timebuf + 11, ampm );
    
        // Print additional time information. 
        _ftime( &tstruct ); // C4996
        // Note: _ftime is deprecated; consider using _ftime_s instead
        printf( "Plus milliseconds:\t\t\t%u\n", tstruct.millitm );
        printf( "Zone difference in hours from UTC:\t%u\n", 
                 tstruct.timezone/60 );
        printf( "Time zone name:\t\t\t\t%s\n", _tzname[0] ); //C4996
        // Note: _tzname is deprecated; consider using _get_tzname
        printf( "Daylight savings:\t\t\t%s\n", 
                 tstruct.dstflag ? "YES" : "NO" );
    
        // Make time for noon on Christmas, 1993. 
        if( mktime( &xmas ) != (time_t)-1 )
        {
           err = asctime_s(timebuf, 26, &xmas);
           if (err)
           {
              printf("asctime_s failed due to an invalid argument.");
              exit(1);
           }
           printf( "Christmas\t\t\t\t%s\n", timebuf );
        }
    
        // Use time structure to build a customized time string. 
        err = _localtime64_s( &today, &ltime );
        if (err)
        {
            printf(" _localtime64_s failed due to invalid arguments.");
            exit(1);
        }
    
        // Use strftime to build a customized time string. 
        strftime( tmpbuf, 128,
             "Today is %A, day %d of %B in the year %Y.\n", &today );
        printf( tmpbuf );
    }
    OS time: 13:51:23
    OS date: 04/25/03
    Time in seconds since UTC 1/1/70: 1051303883
    UNIX time and date: Fri Apr 25 13:51:23 2003
    Coordinated universal time: Fri Apr 25 20:51:23 2003
    12-hour time: 01:51:23 PM
    Plus milliseconds: 552
    Zone difference in hours from UTC: 8
    Time zone name: Pacific Standard Time
    Daylight savings: YES
    Christmas Sat Dec 25 12:00:00 1993

    Today is Friday, day 25 of April in the year 2003.
    Last edited by Adak; 10-11-2013 at 08:01 PM.

  10. #10
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    Why not just use sscanf() it can do almost a good of a job as strptime() and in the case of yours (not reading text month or day) its nearly just as easy.

    Look here:
    Code:
    #include <time.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        struct tm date, * gm; 
        time_t nt; 
        int r;
    
        r = sscanf(
                "2013-10-11 12:33:45", "%d-%d-%d %d:%d:%d",
                &date.tm_year, &date.tm_mon, &date.tm_mday,
                &date.tm_hour, &date.tm_min, &date.tm_sec
        );  
    
        /* check return of sscanf != 6 etc.. */
    
        date.tm_year -= 1900; /* years since 1900 */
        date.tm_mon -= 1;     /* 0 - 11 range */
        date.tm_isdst = -1;   /* automatically determine DST */
    
        nt = mktime(&date);
        gm = gmtime(&nt);
    
        fprintf(stderr, "gmtime: %s hour: %d\n", asctime(gm), date.tm_hour);
    
        return 0;
    }

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    If it was being done just on his local system, that would be fine. What he wants though is to have it also include the difference to GMT, based on the received timezone info that he receives, as well.

    And can it be done using the C standard library?

    On POSIX enabled systems, yes - but on non POSIX systems, it requires non-standard functions, as far as I can tell.

  12. #12
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    I was just going by what the op said, he said he wanted to use gmtime() on the struct tm object. A struct tm object has no timezone information in it. gmtime() is going to be using the system timezone information clearly...however if you have a known timezone you can use simple math to calculate the GMT offset, without the need for non-standard functions.

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by nonpuz View Post
    I was just going by what the op said, he said he wanted to use gmtime() on the struct tm object. A struct tm object has no timezone information in it. gmtime() is going to be using the system timezone information clearly...however if you have a known timezone you can use simple math to calculate the GMT offset, without the need for non-standard functions.
    That's what he wants. The timezone abbreviation will be arriving at his system, along with the time itself. That timezone is not his local timezone, in all cases.

    I looked up the timezone abbreviations of the world, and there are a boatload! If he only needs a few of them, then that's the ez way to go, but he has to handle daylight savings time, still.

    I was thinking if the abbreviation was put into the local copy of the environment, and then read back by the C time functions, it could be handled automatically.

  14. #14
    Registered User
    Join Date
    Oct 2013
    Posts
    9
    Quote Originally Posted by Adak View Post
    That's what he wants. The timezone abbreviation will be arriving at his system, along with the time itself. That timezone is not his local timezone, in all cases.

    I looked up the timezone abbreviations of the world, and there are a boatload! If he only needs a few of them, then that's the ez way to go, but he has to handle daylight savings time, still.

    I was thinking if the abbreviation was put into the local copy of the environment, and then read back by the C time functions, it could be handled automatically.
    Yes, Adak is correct that the timezone will be arriving at the system along with the time itself. As far as the boatload of timezone abbreviations, it's like Adak is reading my mind, I wanted to build a local copy that could be sourced. Does anyone know of a reputable location where a list of timezones 'EST5EDT, EST5, PST8PDT, PST8, etc' can be acquired?

    Something Like...

    Code:
    int main(void)
    {
       setenv("TZ", "EST5EDT", 1);
       tzset();
       strptime("%Y-%M-%D HH:MM:SS", .....)
     mktime(...);
     gmtime(...);
     etc....
    
    }

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The full list is here:
    Time zone abbreviations

    The way I'd do this is to prototype a struct above main():
    Code:
    typedef struct TimeZone {
       char zone[12];
       int offset;
    }tz;
    Then load all those time zone abbrev. into a file, and read them one time into an array of this struct you declare in main(). After that, it's just a matter of searching them to find the tz.zone string that matches, and then reading the tz.offset.
    Last edited by Adak; 10-13-2013 at 11:56 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strptime Warning
    By TheSquid in forum C Programming
    Replies: 9
    Last Post: 10-06-2009, 08:24 AM
  2. FYI: asctime(gmtime(&mytime)) = crash!
    By anonytmouse in forum C Programming
    Replies: 2
    Last Post: 09-29-2003, 02:24 AM