Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在闰秒时,`gmtime()`会将秒报告为60吗?_C_Time_Posix_Unix Timestamp_Utc - Fatal编程技术网

C 在闰秒时,`gmtime()`会将秒报告为60吗?

C 在闰秒时,`gmtime()`会将秒报告为60吗?,c,time,posix,unix-timestamp,utc,C,Time,Posix,Unix Timestamp,Utc,我有一台运行在TZ=UTC中的服务器,代码如下: time_t t = time(NULL); struct tm tm; gmtime_r(&t, &tm); 1483228799 2016-12-31 23:59:59 1483228800 2017-01-01 00:00:00 问题是当服务器在闰秒之内时,willtm.tm_sec==60 例如,如果我在以下时间跨度内: 1998-12-31T23:59:60.00 - 915 148 800.00 199

我有一台运行在
TZ=UTC
中的服务器,代码如下:

time_t t = time(NULL);
struct tm tm;
gmtime_r(&t, &tm);
1483228799    2016-12-31 23:59:59
1483228800    2017-01-01 00:00:00
问题是当服务器在闰秒之内时,will
tm.tm_sec==60

例如,如果我在以下时间跨度内:

1998-12-31T23:59:60.00 - 915 148 800.00
1998-12-31T23:59:60.25 - 915 148 800.25
1998-12-31T23:59:60.50 - 915 148 800.50
1998-12-31T23:59:60.75 - 915 148 800.75
1999-01-01T00:00:00.00 - 915 148 800.00

gmtime()
返回
tm==1998-12-31T23:59:60
时间
time=915148800
,一旦跳出闰秒,返回
tm==1999-01-01T00:00:00
相同的
时间
绝对没有简单的答案。如果有闰秒,就有60秒,你需要1)在操作系统中知道有一个闰秒到期,2)你使用的C库也知道闰秒,并用它做些事情

很多操作系统和库都没有

我发现最好的是现代版本的Linux内核与gpsd和ntpd合作,使用GPS接收机作为时间基准。GPS在其系统数据流中宣传闰秒,gpsd、ntpd和Linux内核可以在闰秒发生时保持时钟,并且系统时钟也正确。我不知道glibc用闰秒做了什么明智的事

在其他Unix上,您的里程数会有所不同。相当多

Windows是一个******灾难区域。例如,C#中的DateTime类不知道历史闰秒。下次收到网络时间更新时,系统时钟将跳变1秒

问题是当服务器在闰秒之内时,will
tm.tm_sec==60

不可以。在典型的UNIX系统上,
time\u t
统计自新纪元(1970-01-01 00:00:00 GMT)以来的非闰秒数。因此,将
time\u t
转换为
struct tm
将始终生成
tm\u sec
值介于0和59之间的时间结构

忽略
time\u t
推算中的闰秒可以将
time\u t
转换为人类可读的日期/时间,而无需完全了解该时间之前的所有闰秒。它还可以在将来明确地转换
time\t
值;包括闰秒将使这成为不可能,因为闰秒的存在在未来6个月后是未知的

UNIX和类UNIX系统有几种处理闰秒的方法。最典型的情况是:

  • 闰秒重复一个
    time\u t
    值。(这是对标准进行严格解释的结果,但会导致许多应用程序出现故障,因为时间似乎已经倒流了。)

  • 在闰秒周围的一段时间内,系统运行稍微慢一点,以便在更宽的时间段内“涂抹”闰秒。(此解决方案已被许多大型云平台采用,包括和。它避免了任何本地时钟不一致,代价是使受影响的系统在整个时间内与UTC不同步长达半秒。)

  • 系统时间设置为TAI。因为这不包括闰秒,所以不需要进行闰秒处理。(这是罕见的,因为它会使系统与UTC系统(世界上大部分地区都是UTC系统)保持几秒钟的不同步。但对于与外部世界几乎没有联系的系统来说,这可能是一个可行的选择,因此无法了解即将到来的闰秒。)

  • 系统完全不知道闰秒,但其NTP客户端将在闰秒使系统时钟偏离正确时间1秒后更正时钟。()


  • 简单的回答是,不,实际上,
    gmtime\u r
    永远不会用60填充
    tm\u sec
    。这是不幸的,但却是不可避免的

    基本问题是,根据Posix标准,
    time\u t
    是自1970-01-01 UTC以来的秒数,假设没有闰秒

    在最近的闰秒中,进展如下:

    time_t t = time(NULL);
    struct tm tm;
    gmtime_r(&t, &tm);
    
    1483228799    2016-12-31 23:59:59
    1483228800    2017-01-01 00:00:00
    
    是的,那里应该有闰秒,
    23:59:60
    。但是在
    1483228799
    1483228800
    之间没有可能的
    time\t

    我知道有两种方法可以让
    gmtime
    变量返回以
    :60
    结尾的时间:

  • 您可以在UTC以外的设备上运行操作系统时钟,通常是TAI或TAI-10,并使用所谓的“正确”时区转换为UTC(或本地时间)进行显示。有关这方面的一些讨论,请参阅

  • 您可以使用
    clock\u gettime()
    并定义一个新的clkid值,可能是
    clock\u UTC
    ,它通过在必要时故意使用非规范化的
    struct timespec
    值来解决时间问题。例如,获取介于
    1483228799
    1483228800
    之间的时间值的方法是将
    tv_sec
    设置为
    1483228799
    tv_nsec
    设置为
    100000000
    。有关更多详细信息,请参阅

  • 方法#1工作得很好,但没有人使用它,因为没有人希望在UTC之外的任何设备上运行内核时钟。(您最终会遇到文件系统时间戳之类的问题,以及嵌入这些时间戳的
    tar
    之类的程序。)

    在我看来,Way#2是一个很好的想法,但据我所知,它从未在发布的操作系统中实现过。(碰巧,我有一个适用于Linux的工作实现,但我还没有发布我的工作。)要想让way#2正常工作,您需要一个新的
    gmtime
    变体,可能是
    gmtime\u ts\r
    ,它接受
    struct timespec
    而不是
    time\t


    增编:我刚刚重读了你的问题标题。您问,“当服务器处于闰秒时,
    gmtime()
    会报告60秒吗?”我们可以回答“是的,但是”,并声明,因为大多数服务器不能表示时间