问题描述
我正在试验time_t
变量,这是有问题的代码:
#include <stdio.h>
#include <time.h>
#include <stdint.h>
struct tm epochtime;
time_t epochdate;
int main()
{
epochtime.tm_mday = 19;
epochtime.tm_mon = 10;
epochtime.tm_year = 2002;
epochtime.tm_hour = 0;
epochtime.tm_min = 0;
epochtime.tm_sec = 0 ;
epochdate = mktime(&epochtime);
printf("%ju\n",epochdate);
printf("%ju\n",(uint32_t)epochdate);
printf("%ju\n",(uint64_t)epochdate);
printf("%ju\n",(uintmax_t)epochdate);
printf("%Lf\n",epochdate);
printf("%Le\n",epochdate);
}
我正在尝试打印给定日期的epochtime
。代码可以编译并且没有错误,但是当我将打印的内容与在this website上计算的内容进行比较时,值并不相同。对于上面示例中的给定值,代码输出为:
210453397503
210453397503
18446744073709551615
18446744073709551615
-1.#QNAN0e+000
-1.#QNAN0e
,而链接显示该值应为1034985600
。我尝试了多个printf
格式说明符,因为在这里我找到了关于如何打印time_t
变量的多个答案,但是似乎没有一个适合我。有什么想法吗?
解决方法
我想您要表示日期:2002年10月19日00:00:00,它对应于您期望的时代时间戳记:1034985600。
在这种情况下,您做错了。阅读the manual:
下降时间存储在
tm
中的结构<time.h>
中,如下所示:struct tm { int tm_sec; /* Seconds (0-60) */ int tm_min; /* Minutes (0-59) */ int tm_hour; /* Hours (0-23) */ int tm_mday; /* Day of the month (1-31) */ int tm_mon; /* Month (0-11) */ int tm_year; /* Year - 1900 */ int tm_wday; /* Day of the week (0-6,Sunday = 0) */ int tm_yday; /* Day in the year (0-365,1 Jan = 0) */ int tm_isdst; /* Daylight saving time */ };
您的年份应该是2002-1900 = 102,您的月份应该是9,而不是10(从0 = 1月开始的月份)。
正确的代码是:
#include <stdio.h>
#include <time.h>
#include <inttypes.h>
int main(void) {
struct tm epochtime = {
.tm_mday = 19,.tm_mon = 9,.tm_year = 102,.tm_hour = 0,.tm_min = 0,.tm_sec = 0,.tm_isdst = -1
};
time_t epochdate = mktime(&epochtime);
if (epochdate == (time_t)(-1)) {
perror("mktime failed");
return 1;
}
printf("%" PRIuMAX "\n",(uintmax_t)epochdate);
return 0;
}
可以正确输出1034985600
。
您的代码有问题的原因很可能是mktime
无法正确表示您提供的“错误”日期并返回-1
,然后您将其打印为未签名并变成一个庞大的荒谬数字
printf epochtime显示错误的值
time_t
没有指定匹配的打印说明符。除了printf()
以外的所有printf("%ju\n",(uintmax_t)epochdate);
都可能导致不确定的行为(UB)。
...关于如何打印time-t变量,这里有多个答案,但它们似乎都不适合我。有什么想法吗?
time_t
是一种能够表示时间的类型。
clock_t
和time_t
中可表示的时间范围和精度是实现定义的。 C17dr§7.27.1 4
使用强制转换进行打印。由于time_t
是非常通常是有符号整数类型,因此将其转换为宽的 signed 类型:
time_t t;
time(&t);
printf("%jd",(intmax_t) t);
// or pre-C99
printf("%ld",(long) t);
或具有广泛的可移植性,而损失某些精度的风险很小,
printf("%f",(double) t);
printf("%ju\n",(uintmax_t)epochdate);
-> 18446744073709551615当然是mktime(&epochtime);
由于转换错误(很可能是由于epochtime.tm_year = 2002;
的范围错误)返回-1的结果。 .tm_year
是 1900年的年份。@pmg
最好先将epochtime
归零以初始化所有成员-可能有9个以上。
struct tm epochtime = {0};
epochtime.tm_mday = 19;
epochtime.tm_mon = 10 - 1; // Months since January
epochtime.tm_year = 2002 - 1900; // Year since 1900
epochtime.tm_isdst = -1; // Let system daylight daylight time for that date
epochdate = mktime(&epochtime); // epochtime is assumed here to be a local time