c-在不使用std库例程的情况下,在日期/时间和时间戳之间进行转换



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

我之前在"将日期/时间转换为时间戳"下发布了一个类似的问题,反之亦然,现在我想再次提交它,并做一些显著的更改:

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

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;

我想对以下转换例程有第二种意见(给定法律输入):

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;
}

我已经在大量的法律意见中对此进行了测试(2000年1月1日至2099年12月31日)。如有任何建设性意见(性能改进建议、可读性等),我们将不胜感激。。。

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

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

为了提高性能,请考虑不要每秒(甚至每一次计时器滴答)执行epoch_to_date_time(),而是只有在较小的单位溢出时才选择性地增加时间单位;g.类似

void another_second_passed(date_time_t *date_time)
{   // *date_time to persist from call to call, initialized once from RTC
if (++date_time->second < 60) return;   // finished in 59 of 60 cases
date_time->second = 0;
if (++date_time->minute < 60) return;   // finished in 59 of 60 cases
date_time->minute = 0;
…
}

最新更新