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 个月。