将日期/时间转换为时间戳,反之亦然

我试图在C中实现两个简单的转换器,日期/时间到时间戳,反之亦然,没有任何依赖于时间库例程,如mktime等。

时间戳以秒为单位,日期/时间结构采用以下格式:

  • unsigned char year:0到99(表示范围2000到2099)

  • unsigned char month:1到12

  • unsigned char day:1到31

  • unsigned char小时:0到23

  • unsigned char分钟:0到59

  • unsigned char second:0到59

我想对dt2ts转换器有第二个意见(假设输入是合法的):

unsigned int dt2ts(const dt_t* dt) { static unsigned short days[] = {0,31,59,90,120,151,181,212,243,273,304,334}; return ((((dt->year*365+dt->year/4)+days[dt->month-1]+dt->day)*24+dt->hour)*60+dt->minute)*60+dt->second; } 

除此之外,我将非常感谢帮助完成ts2dt转换器:

 void ts2dt(unsigned int ts,dt_t* dt) { dt->second = ts%60; ts /= 60; dt->minute = ts%60; ts /= 60; dt->hour = ts%24; ts /= 24; dt->day = ?????; dt->month = ?????; dt->year = ?????; } 

谢谢

OP可以很好地处理小时,分钟,秒。 对Y,M,D有点帮助。

注意:从2000年1月1日到2099年12月31日的天数至少需要16位整数。 即使unsigned是2个字节,以下应该工作。

 unsigned DivRem(unsigned Dividend, unsigned Divisor, unsigned *Remainder) { unsigned Quotient = Dividend/Divisor; *Remainder = Dividend - Quotient*Divisor; return Quotient; } void Day2000ToYMD(unsigned DaySince2000Jan1, unsigned *Y, unsigned *M, unsigned *D) { unsigned OlympiadDay; // Every 4 years is an Olympiad *Y = 4*DivRem(DaySince2000Jan1, 365*4+1, &OlympiadDay); *D = 1; if (OlympiadDay >= (31+29-1)) { // deal with Feb 29th and after OlympiadDay--; if (OlympiadDay == (31+29-1)) { (*D)++; } } unsigned YearDay; // Day of the year 0 to 364 *Y += DivRem(OlympiadDay, 365, &YearDay); static const unsigned short days[] = {0,31,59,90,120,151,181,212,243,273,304,334,365}; *M = 1; while (days[*M] <= YearDay) (*M)++; *D += YearDay - days[*M - 1]; } 

[编辑]提供的答案试图将年度概念保持为1月1日至12月31日。由于这个答案不需要处理大约100年和400年的闰年,我一直保持这种风格。

一般来说,一旦添加了这两条规则,如果将一年的年初改为3月1日并在2月28日/ 29日结束,则数学变得更容易。 FWIW,这对朱利安/格里高利历的古代发展的更一致的看法。 因此,* Oct * ober是第8个月,* Dec * ember是第10个月。