printf epochtime显示错误的值

问题描述

我正在试验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_ttime_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