使用sscanf()
或strptime()
來提取大部分字段。時區字符和DST字符需要自行解碼。由於您僅使用2位數年份,因此您需要定義範圍。下面的例子使用1970-2069。使用提取的時區字符來形成通常的時區名稱。在致電mktime()
之前,請將TZ設置爲時區名稱。然後,手中有time_t
,轉換爲當地時間。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
extern time_t mktime_TZ(struct tm *tm, const char *tz);
extern time_t DecodeTimeString_time_t(const char *time_string);
void DecodeTimeString_Local(const char *time_string, struct tm *local) {
// Various error handling not shown
time_t t;
t = DecodeTimeString_time_t(time_string);
*local = *localtime(&t);
}
time_t DecodeTimeString_time_t(const char *time_string /* YYMMDDHHMMCY */) {
struct tm tm;
char Zone, DST;
int result = sscanf(time_string, "%2d%2d%2d%2d%2d%[CEMP]%[NY]",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &Zone, &DST);
if (result != 7) {
; // handle error
}
// Your need to decide how to handle 2 digits years
// Assume 70-99 is 1970-1999 and 0 to 69 is 2000-2069
if (tm.tm_year < 70) tm.tm_year += 2000-1900;
tm.tm_mon--; // Assume DateString used "01" for January, etc.
tm.tm_sec = 0;
tm.tm_isdst = Zone == 'Y';
const char *TZ;
switch (Zone) {
case 'P': TZ = "PST8PDT"; break; // Pacific
case 'M': TZ = "MST7MDT"; break; // mountain
case 'C': TZ = "CST6CDT"; break; // central
case 'E': TZ = "EST5EDT"; break; // eastern
}
time_t t = mktime_TZ(&tm, TZ);
return t;
}
// Form time_t from struct tm given a TZ
time_t mktime_TZ(struct tm *tm, const char *tz) {
time_t t;
const char *old_tz = getenv("TZ");
if (setenv("TZ", tz, 1 /* overwrite */)) {
return -1; // handle error
}
tzset();
t = mktime(tm);
if (old_tz) {
if (setenv("TZ", old_tz, 1 /* overwrite */)) {
return -1; // handle error
}
}
else {
if (unsetenv("TZ")) {
return -1; // handle error
}
}
tzset();
return t;
}
將環境變量TZ重新設置回舊變量後,應該調用tzset();再次。 – Jimm
@Jimm發佈的代碼準備好在'return t'之前調用'tzset()'。它不會在錯誤處理中調用'tzset()',因爲該代碼區域需要根據OP進行擴展(現在我注意到了你)。 – chux