Converting string containing localtime into UTC in C

前端 未结 3 1885
长发绾君心
长发绾君心 2021-01-13 09:12

I have a string containing a local date/time and I need to convert it to a time_t value (in UTC) - I\'ve been trying this:

char* date = \"2009/09/01/00\";
st         


        
相关标签:
3条回答
  • 2021-01-13 09:49

    I think I've cracked it now, thanks to Andomar - this code does what I need and appears to work regardless of the current DST status (I changed the clock on my PC to check this):

    #include <time.h>
    #include <assert.h>
    
    time_t parseLocalDate(char* date){
        struct tm cal = {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, NULL};
        strptime(date, "%Y/%m/%d/%H", &cal);
        return mktime(&cal);
    }
    
    int main(int argc, char *argv[]){
     // DST is effect, Local Time = GMT+1
        assert(1251759600 == parseLocalDate("2009/09/01/00")); // Mon, 31 Aug 2009 23:00:00 GMT
        assert(1254351600 == parseLocalDate("2009/10/01/00")); // Wed, 30 Sep 2009 23:00:00 GMT
     // DST not in effect, Local Time = GMT
        assert(1257033600 == parseLocalDate("2009/11/01/00")); // Sun, 01 Nov 2009 00:00:00 GMT
    }
    
    0 讨论(0)
  • 2021-01-13 09:55

    Here's my version, using tm_gmtoff. Hopefully, the library takes care of daylight savings time ...

    #define _BSD_SOURCE
    #define _XOPEN_SOURCE
    #include <stdio.h>
    #include <time.h>
    
    int gmtoffset(void) {
      struct tm *dummy;
      time_t t = 0;
      dummy = localtime(&t);
      return dummy->tm_gmtoff; /* _BSD_SOURCE */
    }
    
    int main(void) {
      int off;
      const char *date = "2009/09/01/00";
      struct tm cal = {0};
      time_t t;
    
      off = gmtoffset();
    
      strptime(date, "%Y/%m/%d/%H", &cal); /* _XOPEN_SOURCE */
      t = mktime(&cal);
      printf("t     --> %s", ctime(&t)); /* ctime includes a final '\n' */
      t -= off;
      printf("t-off --> %s", ctime(&t));
      return 0;
    }
    
    $ /usr/bin/gcc ptime.c
    
    $ ./a.out
    t     --> Tue Sep  1 01:00:00 2009
    t-off --> Tue Sep  1 00:00:00 2009
    
    0 讨论(0)
  • 2021-01-13 09:58

    You can use mktime to interpret a struct tm in the local timezone. When you do so, be careful to set the tm_isdst flag. It's 0 for summertime, 1 for wintertime, and to -1 to have mktime figure it out. Here's some example code:

    void main()
    {
        char* date = "2009/09/01/00";
        struct tm cal = {};
        // Read string into struct tm
        strptime(date, "%Y/%m/%d/%H", &cal);
        // Tell mktime to figure out the daylight saving time
        cal.tm_isdst = -1;
        printf("%20s: %s", "Before mktime", asctime(&cal));
        // Convert struct tm to time_t
        time_t t = mktime(&cal);
        // Convert time_t to localtime
        struct tm localcal = *localtime(&t);
        printf("%20s: %s", "Local time", asctime(&localcal));
        printf("%20s: %i\n", "Local DST", localcal.tm_isdst);
        // Convert time_t to GMT
        struct tm gmcal = *gmtime(&t);
        printf("%20s: %s", "GM time", asctime(&gmcal));
        printf("%20s: %i\n", "GM DST", gmcal.tm_isdst);
    }
    

    This prints (I live in GMT+1, and it's wintertime now):

       Before mktime: Tue Sep  1 00:00:00 2009
          Local time: Tue Sep  1 00:00:00 2009
           Local DST: 1
             GM time: Mon Aug 31 22:00:00 2009
              GM DST: 0
    

    It looks like mktime converts a date in September based on the current daylight savings time. It's November now, so it's actually one hour off. I haven't found a way to correct that.

    0 讨论(0)
提交回复
热议问题