printf epochtime 显示错误的值

printf epochtime shows wrong values

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

而 link 表示该值应为 1034985600。我尝试了多个 printf 格式说明符,因为我在这里找到了关于如何打印 time_t 变量的多个答案,但其中 none 似乎对我有用。有什么想法吗?

printf epochtime shows wrong values

time_t 没有指定的匹配 打印说明符。除了 printf("%ju\n", (uintmax_t)epochdate); 之外的所有 printf() 都可能导致 未定义的行为 (UB)。

... multiple answers here on how to print time-t variables, but none of them seems to work for me. Any ideas why?

time_t是一种能够表示时间的类型。

The range and precision of times representable in clock_t and time_t are implementation-defined. C17dr § 7.27.1 4


使用铸件打印。由于 time_t 非常 通常是有符号整数类型,转换为宽 有符号 类型:

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); 由于转换错误而返回 -1 的结果,可能是由于 epochtime.tm_year = 2002; 的范围错误。 .tm_year 1900 年以来的年份。

最好先将 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

我假设您要表示日期:2002 年 10 月 19 日 00:00:00,它对应于您期望的纪元时间戳:1034985600。

在这种情况下,你做错了。阅读 the manual:

Broken-down time is stored in the structure tm, which is defined in <time.h> as follows:

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 = 一月开始)。

正确的代码是:

#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 无法正确表示您提供的“错误”日期和 returns -1,然后您将其打印为未签名并成为一个巨大的无意义数字。