本帖最后由 mars4zhu 于 2015-4-10 15:36 编辑
LPCOpen的rtc_ut.c的闰年BUG与解决
在使用LPCOpen的rtcut例程时,发现计算日期与实际日期相差一天。
为查找原因,做了一下测试,发现RTC与UT之间的转换有误差,
-
- struct tm testTime;
- uint32_t testCounter = 0;
-
- /* Convert tm structure to RTC tick count */
- ConvertTimeRtc(&startTime, &rtcCount);
- ConvertRtcTime(rtcCount, &testTime);
- ConvertTimeRtc(&testTime, &testCounter);
- ConvertRtcTime(testCounter, &testTime);
- ConvertTimeRtc(&testTime, &testCounter);
- ConvertRtcTime(testCounter, &testTime);
- ConvertTimeRtc(&testTime, &testCounter);
- ConvertRtcTime(testCounter, &testTime);
- ConvertTimeRtc(&testTime, &testCounter);
- ConvertRtcTime(testCounter, &testTime);
-
复制代码
将testTime与testCounter之间相互转换,发现每次相互转换后,都会相差一天。
深入探究rtc_ut的源代码,发现其错误在对闰年判断上。
原来的代码判断闰年方式仅仅是能被4整除就是闰年,
-
- /* Leap year check for less than 1 year time */
- if ((year % 4) == 0) {
- curLeapYear = 1;
- }
- else {
- curLeapYear = 0;
- }
复制代码
而刚好使用1900年作为基准年,错误地将1900年当做了闰年,使得在对rtc->ut转换中,多算了一天,而ut->rtc中,却没有将1900年的这一年计算进入,从而每次相互转换时,会造成一天的误差。
而正确的判断闰年方法是:
能被四整除的且不能被100整除的为闰年,能被100整除的,必须也能被400整除才是闰年。
这就是通常所说的:四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,1900年则是平年。
改正后的代码如下:
@note 将rtc_ut.c代码中的(year%4)==0全部替换成isLeapYear(year)即可。
- /**
- * @brief test if it is a leap year
- * @param year : the year to test, 1998, 2015
- * @return true if the year is leap, else false
- * @note replace the code "(year%4) == 0" with "isLeapYear(year)"
- */
- bool isLeapYear(int year)
- {
- if ((year%100) == 0) {
- if ((year%400) == 0)
- return true;
- else
- return false;
- }
- else {
- if ((year%4 == 0))
- return true;
- else
- return false;
- }
- }
复制代码