我使用strptime(3)
来解析代表日期的字符串:
#include <time.h>
#include <stdio.h>
int main () {
struct tm t;
strptime("2015-04-19 12:00:00", "%F %T", &t); /* Sunday */
printf("%d\n", t.tm_wday); /* Should print 0 */
return 0;
}
根据cal -y 2015
的输出,该日期是星期日。但是当我在OSX上编译它时(可能是用clang)它打印6
:
$ gcc timetest.c ; ./a.out
6
而在Debian上它打印(正确)0
:
$ gcc timetest.c ; ./a.out
0
对差异的任何解释?
更新
以下是同一个程序,但t
初始化时间为有效时间,并且我报告了strptime()
的返回值:
#include <time.h>
#include <stdio.h>
int main () {
time_t epoch = 0;
struct tm t;
char *ret;
t = *localtime(&epoch);
ret = strptime("2015-04-19 12:00:00", "%F %T", &t); /* Sunday */
printf("%d\n", t.tm_wday); /* Should print 0 */
printf("strptime() returned %p (%d)\n", ret, *ret);
return 0;
}
这是输出:
$ gcc timetest.c ; ./a.out
6
strptime() returned 0x10c72af83 (0)
以下是我使用的clang
版本:
$ clang -v
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
答案 0 :(得分:1)
我认为原因很简单,就是设计the strptime
function only sets the fields that appear in the format。实质上,strptime(3)
只是使用提供的格式将给定字符串中的字段解析为引用的结构,并且不执行任何其他计算或逻辑。由于您的代码使用的格式为%F %T
,因此只会修改与%Y-%m-%d
和%H:%M:%S
(即tm_{year,mon,mday,hour,min,sec}
)对应的字段。
您可以通过明确地将t.tm_wday
设置为某个已知值来进行试验,该值不应由strptime
设置(例如123)并验证该呼叫未更改它。请注意,您应该在使用之前初始化struct tm
,因为这些字段中的任何一个都可能包含随机值,例如struct tm t; memset((void *) &t, 0, sizeof(t));
。
此外,这个Linux strptime(3)
man page包含以下注释,这使我相信它所描述的特殊行为是非标准的(尽管显然是可取的):
glibc实现不会触及那些未明确指定的字段,除非它重新计算
tm_wday
和tm_yday
字段(如果年,月或日元素中的任何一个更改)。
This answer shows how您可以使用strptime/mktime/localtime
(或gmtime
)三重奏来填充UNIX纪元后日期的tm.tm_wday
字段。
答案 1 :(得分:0)
根据评论中的观察结果,这是一个源自您的代码的程序,该程序说明了即使它没有解释发生了什么:
#include <time.h>
#include <stdio.h>
static void dump_struct_tm(const char *tag, const struct tm *t)
{
printf("%s:\n", tag);
printf(" Time: %.2d:%.2d:%.2d ", t-> tm_hour, t->tm_min, t->tm_sec);
printf(" Date: %.4d-%.2d-%.2d\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
printf(" Wday: %d Yday: %.3d (DST %d Zone [%s] offset %ld)\n",
t->tm_wday, t->tm_yday, t->tm_isdst, t->tm_zone, t-> tm_gmtoff);
}
int main(void)
{
time_t epoch = 0;
struct tm t;
char *ret;
t = *localtime(&epoch);
dump_struct_tm("Epoch", &t);
putchar('\n');
ret = strptime("2015-04-19 12:00:00", "%F %T", &t);
dump_struct_tm("strptime()", &t);
time_t rt = mktime(&t);
dump_struct_tm("mktime()", &t);
printf("Weekday: %d\n", t.tm_wday);
printf("strptime() returned %p (%d)\n", ret, *ret);
printf("Unix time: %lld\n\n", (long long)rt);
t.tm_isdst = -1;
ret = strptime("2015-04-19 12:00:00", "%F %T", &t);
dump_struct_tm("strptime()", &t);
rt = mktime(&t);
dump_struct_tm("mktime()", &t);
printf("Weekday: %d\n", t.tm_wday);
printf("strptime() returned %p (%d)\n", ret, *ret);
printf("Unix time: %lld\n\n", (long long)rt);
return 0;
}
在不同点分析struct tm
(由macOS Sierra上的手册页定义)。请注意tm_isdst
的设置如何改变行为。
Epoch:
Time: 16:00:00 Date: 1969-12-31
Wday: 3 Yday: 364 (DST 0 Zone [PST] offset -28800)
strptime():
Time: 12:00:00 Date: 2015-04-19
Wday: 6 Yday: 108 (DST 0 Zone [(null)] offset -28800)
mktime():
Time: 13:00:00 Date: 2015-04-19
Wday: 0 Yday: 108 (DST 1 Zone [PDT] offset -25200)
Weekday: 0
strptime() returned 0x100c82f0c (0)
Unix time: 1429473600
strptime():
Time: 12:00:00 Date: 2015-04-19
Wday: 6 Yday: 108 (DST -1 Zone [(null)] offset -25200)
mktime():
Time: 12:00:00 Date: 2015-04-19
Wday: 0 Yday: 108 (DST 1 Zone [PDT] offset -25200)
Weekday: 0
strptime() returned 0x100c82f0c (0)
Unix time: 1429470000
我仍然不清楚为什么strptime()
错误填充tm_wday
字段,特别是因为它似乎使tm_yday
字段正确。 4月19日是1月1日第0天的第108天。