Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/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 从秒开始的快速时间结构_C_Date_Time_Vector_Ntp - Fatal编程技术网

C 从秒开始的快速时间结构

C 从秒开始的快速时间结构,c,date,time,vector,ntp,C,Date,Time,Vector,Ntp,我正在寻找最快的方法来确定NTP时间戳向量的日期组件 本例中的输入是自1900-01-01以来测量的NTP时间戳或秒,通过添加2208988800或减去(如果是相反的方式)往返于unix时间是微不足道的。我需要将时间戳分解为其他API的日期组件,这些API只接受日期作为其组件,特别是年、月和日 使用time.h(glibc)中的ANSI C方法,我可以很容易地导出组件,但是对于较大的向量来说,它太慢了。一个较小的向量可能包含172800个值,但更现实地说,我希望能够尽快处理一个包含1314000

我正在寻找最快的方法来确定NTP时间戳向量的日期组件

本例中的输入是自1900-01-01以来测量的NTP时间戳或秒,通过添加2208988800或减去(如果是相反的方式)往返于unix时间是微不足道的。我需要将时间戳分解为其他API的日期组件,这些API只接受日期作为其组件,特别是年、月和日

使用
time.h
glibc
)中的ANSI C方法,我可以很容易地导出组件,但是对于较大的向量来说,它太慢了。一个较小的向量可能包含172800个值,但更现实地说,我希望能够尽快处理一个包含1314000个值的向量

我在想,我可以自己压缩时间,通过迭代地减去时间戳输入,用每个日期组件的第二个除数减去时间戳,从而消除少量的
glibc
开销,直到我到达日期,基本上是
glibc
所做的,但没有时区和一些额外(小)开销

我很快发现这样做仍然很慢

我的工作是这样的:

typedef struct simple_time_ {
    int year;
    int month;
    int day;
} simple_time;

size_t time_cruncher(const time_t *ntp_vector, simple_time *out, size_t len)
{
    size_t i;
    time_t corrected;
    struct tm cal;
    for(i=0;i<len;i++) {
        corrected = ntp_vector[i] - 2208988800; /* NTP Offset */
        gmtime_r(&corrected, &cal);
        simple_time[i].year = cal.tm_year + 1900;
        simple_time[i].month = cal.tm_mon + 1;
        simple_time[i].day = cal.tm_mday;
    }
    return i;
}
typedef struct simple\u time\u{
国际年;
整月;
国际日;
}简单时间;
大小\u t时间\u处理器(常量时间\u t*ntp\u向量、简单时间*out、大小长度)
{
尺寸i;
校正时间;
struct-tm-cal;

对于(i=0;i,考虑到您的许多连续时间戳很可能在同一个月内,请利用这一点

Pseudo code
1) Calculate the y,m,d for the given timestamp 't' as you have above.
2) now calculate the t0 = gmtime(y, m, 1) and t1 = gmtime(y, m+1, 1).  (Dec + 1 is OK)
3) As long as your timestamps are t0 <= t < t1, a simple add/divide is need to determine the day of the month.
4) Should 't' fall outside the range,  go to step 1.
伪代码
1) 如上文所述,计算给定时间戳“t”的y、m、d。
2) 现在计算t0=gmtime(y,m,1)和t1=gmtime(y,m+1,1)。(Dec+1正常)

3) 只要您的时间戳是t0如果您的时间戳在日期范围1901到2099之间,您就可以利用每四年是闰年这一事实(由于不是闰年,可以进一步扩展到包括1900年内的日期)

我从一个日期派生出这段代码,在这段代码中,我使用了如中所示的“移位月”方法

#包括
#包括
#包括
无效的
dt_to_ymd(无符号整数n,整数*yp,整数*mp,整数*dp){
无符号整数z,c;
int y,m,d;
断言(n 12)
y++,m-=12;
如果(yp)*yp=y+1899;
如果(mp)*mp=m;
如果(dp)*dp=d;
}
常量结构测试{
国际年;
整月;
国际日;
uint64_t时间戳;
}测试[]={
{ 1900,  1,  1,          0 },
{ 1970,  1,  1, 2208988800 },
{ 1972,  1,  1, 2272060800 },
{ 1999, 12, 31, 3155587200 },
{ 2013,  7,  4, 3581884800 },
{ 2100,  2, 28, 6316444800 },
};
int
main(){
int i,NTEST;
NTEST=sizeof(测试)/sizeof(*测试);
对于(i=0;i
你考虑过并行化你的循环吗?我只是在假设,但我想,
gmtime\u r
在保持无错误的情况下已经尽可能快了。@TaylorBrandstetter这就是我写这篇文章时正在尝试的。我只是想看看是否有人知道一个优雅的算法。并行化是最重要的从我坐的地方开始的下一个逻辑步骤。
#include <stdio.h>
#include <assert.h>
#include <stdint.h>

void
dt_to_ymd(unsigned int n, int *yp, int *mp, int *dp) {
    unsigned int z, c;
    int y, m, d;

    assert(n <= 73107); /* 2100-02-28 */

    z = n + 307;                    /* 1 + 306 (306 days between March 1 and December 31) */
    y = (4 * z) / 1461;
    c = z - (1461 * y - 1) / 4;     /* day of the year [1, 366]  */
    m = (5 * c + 456) / 153;        /* month of the year [1, 12] */
    d = c - (153 * m - 457) / 5;    /* day of the month [1, 31]  */

    if (m > 12)
        y++, m -= 12;

    if (yp) *yp = y + 1899;
    if (mp) *mp = m;
    if (dp) *dp = d;
}

const struct test {
    int year;
    int month;
    int day;
    uint64_t timestamp;
} tests[] =  {
    { 1900,  1,  1,          0 },
    { 1970,  1,  1, 2208988800 },
    { 1972,  1,  1, 2272060800 },
    { 1999, 12, 31, 3155587200 },
    { 2013,  7,  4, 3581884800 },
    { 2100,  2, 28, 6316444800 },
};

int 
main() {
    int i, ntests;

    ntests = sizeof(tests) / sizeof(*tests);
    for (i = 0; i < ntests; i++) {
        const struct test t = tests[i];

        {
            unsigned int n;
            int y, m, d;

            n = t.timestamp / 86400;
            dt_to_ymd(n, &y, &m, &d);
            if (t.year != y || t.month != m || t.day != d) {
                printf("dt_to_ymd(%u)\n", n);
                printf("  got: %.4d-%.2d-%.2d\n", y, m, d);
                printf("  exp: %.4d-%.2d-%.2d\n", t.year, t.month, t.day);
            }
        }
    }
    return 0;
}