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

时间:2013-11-03 18:33:18

标签: c datetime timestamp

我试图在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   = ?????;
}

由于

1 个答案:

答案 0 :(得分:2)

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 *余烬是第10个月。