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

2024-02-04

我试图用 C 语言实现两个简单的转换器,即日期/时间到时间戳,反之亦然,而不依赖于时间库例程,例如 mktime 等。

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

  • unsigned char 年份:0 到 99(代表范围 2000 到 2099)

  • 无符号字符月份:1 到 12

  • 无符号字符日:1 到 31

  • 无符号字符小时:0 到 23

  • 无符号字符分钟:0 到 59

  • 第二个无符号字符: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   = ?????;
}

Thanks


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 日。正如这个答案所做的那样not需要处理大约100年和400年的闰年,我一直保持这种风格。

一般来说,一旦添加了这两条规则,如果将一年的开始日期移至 3 月 1 日并于 2 月 28 日/29 日结束,那么数学计算就会变得更容易。 FWIW,这个is对儒略/公历古代发展的更一致的看法。因此 *Oct*ober 是第 8 个月,*Dec*ember 是第 10 个月。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将日期/时间转换为时间戳,反之亦然 的相关文章

随机推荐