我正在尝试实施自己的NTP客户端。
我可以发送和接收NTP消息,我现在需要做的是将其转换为"真实"时间。我已经创建了一个函数来执行此操作,但由于某种原因,我得到了所有字段都正确,除了1天后的日期字段。
我还用笔,纸和计算器进行了一些快速计算,我得到了相同的结果,因此必须有一些我不知道的东西。
这是我的代码:
void setTime(uint32_t seconds, uint32_t fraction)
{
int yearsPassed = seconds / (60 * 60 * 24 * 365);
year = 1900 + yearsPassed;
int leapYears = yearsPassed / 4;
int secondsLeft = seconds - yearsPassed * 365 * 24 * 60 * 60;
secondsLeft -= leapYears * 60 * 60 * 24;
int daysPassed = secondsLeft / (60 * 60 * 24);
secondsLeft -= daysPassed * 60 * 60 * 24;
int hoursPassed = secondsLeft / (60*60);
secondsLeft -= hoursPassed * 60 * 60;
int minutesPassed = secondsLeft / 60;
secondsLeft -= minutesPassed * 60;
hour = hoursPassed + SUMMERTIME_OFFSET;
minute = minutesPassed;
second = secondsLeft;
us = (fraction * (pow((float)10,(float)6)) / (pow((float)2,(float)32)));
month = getMonth(daysPassed);
day = getDay(month, daysPassed);
}
使用此代码我可以获得时间2015/4/28 14:3:15.351731,但日期应该是29而不是28.我最初的想法是我计算错误的闰年并且错过了1天那,但这似乎是正确的。
修改
getMonth()和getDay()的代码。它们还没有完全实现,因为我想编写尽可能少的代码来测试它的工作原理。
int getMonth(int daysPassed)
{
if (daysPassed < 32)
return 1;
else if (daysPassed < 60)
return 2;
else if (daysPassed < 91)
return 3;
else if (daysPassed < 121)
return 4;
else if (daysPassed < 152)
return 5;
else
return 6;
}
int getDay(int month, int daysPassed)
{
switch (month)
{
case 1:
return daysPassed;
break;
case 2:
return daysPassed - 31;
break;
case 3:
return daysPassed - 59;
break;
case 4:
return daysPassed - 90;
break;
case 5:
return daysPassed - 120;
break;
default:
return 6;
break;
}
}
答案 0 :(得分:1)
您的daysPast
上有一个fencepost错误,因为它是已完成的天,而不是部分天的数量。< / p>
考虑1秒的输入(哎呀,更好的是,让它成为单元测试),它应该解析为1/1/1900 00:00:01 - 它会将你的daysPast
设为0,同时是过去的天数,它并不代表当天。
当然,您还需要考虑当年是否计算一年中的闰年;为了完整性,并且在2100年的兼容性,你的算法闰年是一个天真的。