在C中将包含localtime的字符串转换为UTC

我有一个包含本地日期/时间的字符串,我需要将其转换为time_t值(以UTC为单位) – 我一直在尝试这个:

char* date = "2009/09/01/00"; struct tm cal = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL}; strptime(date, "%Y/%m/%d/%H", &cal); time_t t = mktime(&cal); 

但是我得到的time_t值是如果字符串被解析为UTC而不是本地时间的话我期望的值。 也许我误解了strptime应该做什么,但是在我9月1日的时区(英国),我们正在使用BST(即UTC + 1小时)所以我希望我最终得到的值比UTC提前1小时。

有没有办法将字符串解释为localtime,自动考虑在该日期生效的UTC偏移量? 请注意,我需要time_t值而不是struct tm,在上面的示例中,我希望time_t值对应于2009-09-01 01:00:00 GMT

您可以使用mktime来解释本地时区中的struct tm。 执行此操作时,请小心设置tm_isdst标志。 夏季为0,冬季为1, mktime为-1。 这是一些示例代码:

 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); } 

这打印(我住在GMT + 1,现在是冬天):

  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 

看起来mktime根据当前的夏令时转换9月的日期。 现在是十一月,所以它实际上是一小时。 我还没有办法纠正这个问题。

这是我的版本,使用tm_gmtoff 。 希望图书馆能够照顾夏令时……

 #define _BSD_SOURCE #define _XOPEN_SOURCE #include  #include  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  - > 2009年9月1日星期二01:00:00
 t-off  - > 2009年9月1日00:00:00

我想我现在已经破解了它,感谢Andomar – 这个代码完成了我需要的工作并且无论当前的DST状态如何都可以工作(我更改了PC上的时钟来检查):

 #include  #include  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 }