
在网站上找了一些软件时钟程序,在秒时与日历转换时,大多是逐年计算,计算周期会随着年份增加,而增多。于是自己写了一个简化的秒时与日历转换程序,按闰年周期进行除法运算,计算周期固定,不随秒时与基础年时间差增长而增长,效率明显提高。 程序带有闰年计算与星期计算,基础年为2001年1月1日0时0分0秒,算法可支持到3200年2月28日23时59分59秒。但由于RTC计数器是32位,所以硬件只能支持到2137年2月7日6时28分15秒,也足够使用了。 以下为程序代码: /**************************************************************************** * 函数名: GetRTCWeek * 功 能: 计算Week * 输 入: 秒时 * 输 出: 无. * 返 回: 星期 */ //u8 GetRTCWeek(RTC_T *_tRtc) u8 GetRTCWeek(u32 lDay) { //u32 lDay; //lDay = GetSecondFromDateTime(_tRtc)/SECOND_OF_DAY; lDay /= SECOND_OF_DAY; lDay += RTC_BASE_WEEK; lDay %= 7; return (u8)lDay; } /**************************************************************************** * 函数名: GetSecondFromDateTime * 功 能: 基于2001/1/1/00:00:00的日期计算秒时 * 输 入: RTC_T 日期时间结构体 * 输 出: 无. * 返 回: 秒时 */ uint32_t GetSecondFromDateTime(RTC_T *_tRtc) { u32 y,sec,fy; const u32 *ptr; y = (u32)((_tRtc->year - (u16)RTC_BASE_YEAR)&0x0000FFFF); fy = y / 4; sec = fy * DAY_OF_FOURYEAR; if(y/100){//百年不润 sec -= y/100; } if(y/400){//四百年再润 sec += y/400; } y %= 4; sec += y * DAY_OF_YEAR; ptr = DayOfCurrentMonthNormal; if(y == 3 && _tRtc->month > 2 && IsRTCLeapYear(_tRtc->year)){//当前年为润年,并且月份已过2月,天数加1 ptr = DayOfCurrentMonthLeap; } sec += ptr[_tRtc->month]; sec += _tRtc->day - 1; sec *= 24; sec += _tRtc->hour; sec *= 60; sec += _tRtc->minute; sec *= 60; sec += _tRtc->second; return sec; } /**************************************************************************** * 函数名: GetDateTimeFromSecond * 功 能: 由秒时计算基?001/1/1/00:00:00的日期 * 输 入: RTC_T 日期时间结构体 * 输 出: 无. * 返 回: 无 */ void GetDateTimeFromSecond(u32 lSec, RTC_T *_tRtc) { uint16_t y,m; u32 lDay; const u32 *ptr; lDay = lSec / SECOND_OF_DAY; /* 转为基于天的时间 */ _tRtc->year = RTC_BASE_YEAR;//基数年份 y = lDay / DAY_OF_FOURYEAR; y *= 4; _tRtc->year += y; lDay %= DAY_OF_FOURYEAR; if(y/100){//百年不润 lDay += y/100; } if(y/400){//四百年再润 lDay -= y/400; } y = lDay / DAY_OF_YEAR; _tRtc->year += y; /* 得到年份 */ lDay %= DAY_OF_YEAR; ptr = DayOfCurrentMonthNormal; if(y == 3 && IsRTCLeapYear(_tRtc->year)){//当前年为润年,并且月份已过2月,天数加1 ptr = DayOfCurrentMonthLeap; } for(m=12;m>1;m--){ /* 查询月份 */ if(lDay >= ptr[m]) { lDay -= ptr[m]; break; } } _tRtc->month = m; _tRtc->day = lDay+1; _tRtc->week = GetRTCWeek(lSec); lSec = lSec % SECOND_OF_DAY; _tRtc->hour = lSec / SECOND_OF_HOUR; lSec %= SECOND_OF_HOUR; _tRtc->minute = lSec / SECOND_OF_MINUTE; _tRtc->second = lSec % SECOND_OF_MINUTE; } ![]() |