我使用以下方法从文本文件解析日期时间:
#define DATETIME_FORMAT "%Y-%m-%d %H:%M:%S"
Run Code Online (Sandbox Code Playgroud)
if (!strptime(datetimestr, DATETIME_FORMAT, &record->datetime)) {
return 0;
} else {
record->message_size = strlen(messagestr) - 1;
messagestr[record->message_size] = '\0';
strcpy(record->message, messagestr);
printf("parsed '%s' '%s' %ld\n", messagestr, datetimestr, mktime(&record->datetime));
return 1;
}
Run Code Online (Sandbox Code Playgroud)
我得到了这些印刷品
parsed 'ETC' '2023-04-03 09:00:19' 1680508819
parsed 'StandUp' '2023-04-03 09:00:47' 1680508847
parsed 'Stop' '2023-04-03 09:11:55' 1680505915
Run Code Online (Sandbox Code Playgroud)
但是当我将它们粘贴到在线纪元转换器时,我得到:
那么为什么第三次约会strptime和mktime改造第三次约会完全不同呢?
为什么 strptime 和 mktime 对第三个日期的转换完全不同?
mktime()struct tm未完全分配时存在不一致行为的风险。
strptime(datetimestr, DATETIME_FORMAT, &record->datetime)填充了一些成员。 tm 应在调用之前初始化。struct tmrecord->datetime
mktime()使用由 分配的成员strptime(..., %Y-%m-%d %H:%M:%S", ...加上其他成员(包括 ).tm_isdst,这会减少一小时。
之前,将整个strptime()零填充*1struct tm并设置.tm_isdst为-1 (让我们mktime()确定 DST 设置)。@dalfaB
// Add
memset(&record->datetime, 0, sizeof record->datetime);
record->datetime.tm_isdst = -1;
if (!strptime(datetimestr, DATETIME_FORMAT, &record->datetime)) {
...
printf("parsed '%s' '%s' %lld\n",
messagestr, datetimestr, (long long) mktime(&record->datetime));
Run Code Online (Sandbox Code Playgroud)
旁白:使用匹配的打印说明符。 "%ld"可能不匹配time_t。建议转换为宽类型。
请注意,mktime()将 读取struct tm为当地时间,而不一定是 GMT 或UTC。
*1详细信息:至少struct tm有9 名成员。2 ( , )在确定返回时被忽略。由于各种实现可能具有超过 9 个标准成员,因此我们希望初始化/分配所有成员以获得一致的结果。.tm_yday.tm_wdaygmtime()time_t
struct tm tm = { 0 };或者memset(&tm, 0, sizeof tm);有两种方法可以做到这一点。
strptime(datetimestr, %Y-%m-%d %H:%M:%S", &record->datetime)设置 6 个预期成员(和.tm_yday、.tm_wday),但不设置.tm_isdst,也不可能设置其他tm成员。
代码可以进行零初始化和设置.tm_isdst:
struct tm tm = { .tm_isdst = -1 };
Run Code Online (Sandbox Code Playgroud)
代码可以使用复合文字.tm_isdst对其他成员进行赋值和清零。
record->datetime = (struct tm){ .tm_isdst = -1 };
Run Code Online (Sandbox Code Playgroud)