ctime提供不正确的输出

时间:2013-02-08 22:28:15

标签: c linux

ctime()函数应该以字符串格式给出时间,因为传入的秒数是Epoch。这是我的代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(int argc, int **argv)
{
    time_t tmp=86400; // Seconds for one day
    char *s;
    s = ctime(&tmp);
    if(!s) perror("ctime");
    else printf("%s", s);
    return 0;
}

程序在我的Ubuntu 12.04,32位机器上提供正确的输出:

Fri Jan  2 01:00:00 1970

但是相同的代码在我的Scientific Linux,64位机器上输出错误:

Thu Jan  1 16:00:00 1970

显然,根据这台机器Epoch是:

Wed Dec 31 16:00:00 1969

知道为什么Scientific Linux 6输出错误了吗?!

3 个答案:

答案 0 :(得分:4)

time_t值始终为[1]表示自纪元以来的秒数,即1970-01-01 00:00:00 UTC - 加上或减去任何需要确认我们的手续费可能无视闰秒。因此(time_t)86400表示单个时刻,无论您当前的时区如何。

ctime()函数返回指向 local 时间内表示格式错误的[2]字符串的指针。我在UTC以西8小时,所以在我的系统上你的程序输出是:

Thu Jan  1 16:00:00 1970

(纪元加上86400的24小时,我的时区减去8小时。)

系统对当前时区的想法可以通过几种方式中的任何一种来确定。在我的Ubuntu系统上,/etc/timezone包含行America/Los_Angeles。在CentOS上,它应该类似于Scientific Linux,/etc/localtime是一个二进制时区数据文件。

在两个系统上,可以通过设置$TZ环境变量UTC或表示UTC的空字符串来覆盖系统默认时区。如果我将$TZ设置为UTC"",则您的程序输出为:

Fri Jan  2 00:00:00 1970

历史永远是历史上的同一时刻,但它可以用不同的方式表达。例如(使用GNU Coreutils date命令,显示纪元本身,而不是像程序那样在纪元之后24小时):

$ date -d @0
Wed Dec 31 16:00:00 PST 1969
$ date -u -d @0
Thu Jan  1 00:00:00 UTC 1970
$ TZ=UTC date -d @0
Thu Jan  1 00:00:00 UTC 1970
$ TZ= date -d @0
Thu Jan  1 00:00:00 UTC 1970
$ 

请注意,如果您在英国,则当地时间仅与UTC的部分时间相匹配。

[1]好吧,几乎总是如此。 POSIX保证time_t值表示自纪元以来的秒数,但C标准仅表示它是能够表示时间的算术类型。并且你可以在time_t对象中存储你喜欢的任何值,并且让它意味着你喜欢什么,但是处理time_t值的所有标准C和POSIX函数都将它们视为自纪元以来的秒数。

[2]由于历史原因,ctime()asctime()生成的格式相当尴尬。它的格式为Sun Sep 16 01:03:52 1973\n\0。注意缺少任何时区信息;尾随'\n'也可能令人困惑(因为它,我在日志文件中看到了无关的空白行)。 strftime()功能为您提供了更大的灵活性。我建议尽可能使用ISO 8601格式。

答案 1 :(得分:1)

秒数应为UTC - 自UTC时间1970年1月1日00:00起经过的秒数

查看time_t的描述:

http://www.cplusplus.com/reference/ctime/time_t/

答案 2 :(得分:1)

您所指的手册页

  

ctime(),gmtime()和localtime()函数都接受数据参数   输入time_t表示日历时间。当被解释为绝对时   时间值,它表示自纪元以来经过的秒数,   1970-01-01 00:00:00 +0000(UTC)。

这是some ctime implementation

char *
ctime(timep)
const time_t * const    timep;
{
    return asctime(localtime(timep));
}

如您所见,它使用本地时间,即相对于当前进程的时区的时间。