在不使用标准库例程的情况下在日期/时间和时间戳之间进行转换

bar*_*nos 5 c datetime timestamp localtime mktime

我试图在 C 中实现两个简单的转换器,日期/时间到时间戳,反之亦然,不依赖于时间库例程(例如 localtime、mktime 等,主要是因为它们中的一些是线程- 不安全)。

我之前在Convert date/time to time-stamp and反之亦然下发布了一个类似的问题,现在想再次提交它,并进行一些显着的更改:

我有以下日期/时间结构:

typedef struct
{
    unsigned char second; // 0-59
    unsigned char minute; // 0-59
    unsigned char hour;   // 0-59
    unsigned char day;    // 1-31
    unsigned char month;  // 1-12
    unsigned char year;   // 0-99 (representing 2000-2099)
}
date_time_t;
Run Code Online (Sandbox Code Playgroud)

我想对以下转换例程(给出合法输入)提出第二意见:

static unsigned short days[4][12] =
{
    {   0,  31,  60,  91, 121, 152, 182, 213, 244, 274, 305, 335},
    { 366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700},
    { 731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065},
    {1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430},
};


unsigned int date_time_to_epoch(date_time_t* date_time)
{
    unsigned int second = date_time->second;  // 0-59
    unsigned int minute = date_time->minute;  // 0-59
    unsigned int hour   = date_time->hour;    // 0-23
    unsigned int day    = date_time->day-1;   // 0-30
    unsigned int month  = date_time->month-1; // 0-11
    unsigned int year   = date_time->year;    // 0-99
    return (((year/4*(365*4+1)+days[year%4][month]+day)*24+hour)*60+minute)*60+second;
}


void epoch_to_date_time(date_time_t* date_time,unsigned int epoch)
{
    date_time->second = epoch%60; epoch /= 60;
    date_time->minute = epoch%60; epoch /= 60;
    date_time->hour   = epoch%24; epoch /= 24;

    unsigned int years = epoch/(365*4+1)*4; epoch %= 365*4+1;

    unsigned int year;
    for (year=3; year>0; year--)
    {
        if (epoch >= days[year][0])
            break;
    }

    unsigned int month;
    for (month=11; month>0; month--)
    {
        if (epoch >= days[year][month])
            break;
    }

    date_time->year  = years+year;
    date_time->month = month+1;
    date_time->day   = epoch-days[year][month]+1;
}
Run Code Online (Sandbox Code Playgroud)

我已经在大量的法律输入中对此进行了测试(在 01/01/2000 和 31/12/2099 之间)。任何建设性的意见将不胜感激(性能改进建议,可读性等)...

更新 - 我在这里的最终目标(因此我发布了这个问题):

我有一个 STM32(基于 ARM 的皮层),带有一个配置为每 10 毫秒中断一次 CPU 的定时器。此外,我连接了一个 RTC,我可以从中读取日期/时间(以 1 秒的分辨率)。访问 RTC 的效率较低,因此我只想读取一次,然后使用 10ms 计时器中断计算日期/时间。我希望避免使用“localtime”,因为我必须用互斥锁来保护它。想到的唯一解决方案是实现我自己的“本地时间”,以及随后的结果 - 我自己的“mktime”(我在上面代码中的时代从 2000 年初开始计算秒数)。

Arm*_*ali 1

为了提高性能,请考虑不要epoch_to_date_time()每秒执行一次(甚至每个计时器滴答声),而是仅在较小的单位溢出时选择性地增加时间单位,例如。G。喜欢

\n\n
void another_second_passed(date_time_t *date_time)\n{   // *date_time to persist from call to call, initialized once from RTC\n    if (++date_time->second < 60) return;   // finished in 59 of 60 cases\n    date_time->second = 0;\n    if (++date_time->minute < 60) return;   // finished in 59 of 60 cases\n    date_time->minute = 0;\n    \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n