AVR里边计算天数差的法子
打算计算天数差,翻了翻网上的讨论,都用了循环。可是像M8这样的芯片,RAM倒是有几个,可速度就不是很快。用循环在PC上也许更合适。想了想,反正每400年公历就经历一个循环,找出400年内的润平年数,就能用乘加的方法一次性算出相对某个400年周期的总天数,然后天数差就好算了。
从表中看出,公元0年、400年...2000年是闰年(当然历法中没规定0年),所以起始加一,然后再屏蔽掉一个闰年就能得到400年内的全部闰年数,再用年数乘365之后就得到本年之前经过的总天数了。之后确定本年内的天数,就得到包括当前日期在内的全部天数。这样就回避了循环。
用OCTAVE验证之后写了下面的程序。还附了一个计算annual date的程序,两个加起来比较好用。
程序里叫做qdt_time_t的类型不过是包含年月日整型变量的一个结构而已。/*
The days of the past years can be calculated by using the following formula:
The year: 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
MOD 400: 0 1 2 3 4 5 6 7 8 9 10 11 12
Leap year: 0 1 0 0 0 1 0 0 0 1 0 0 0
Days past: 0 366 365 365 365 366 365 365 365 366 365 365 365
The sums: 0 366 731 1096 1461 1827 2192 2557 2922 3288 3653 4018 4383
Formula: n = 1 + y*365 + fix((y-1)/4) - fix((y-1)/100) + fix((y-1)/400)
Before 2012, we have 4383 + 146097 * 5 = 734868 days past. Where 146097 = 365 * 400 + 97 is a 400 years cycle.
*/
uint32_t qdt_to_long_date(const qdt_time_t *time)
{
uint16_t year = time->year;
/* The DOY means what day is today of the year. It is an annual date. */
uint32_t days;
if(year == 0){
days = 0;
}else{
days = 1 + year * 365UL;
year --;
days += year/4 - year/100 + year/400;
}
/* Add the annual date at the final. */
days += qdt_day_of_annual(time);
return days;
}
uint16_t qdt_day_of_annual(const qdt_time_t *time)
{
/* Days accumulation table of an ordinary year. */
static const uint16_t PROGMEM annual_table[] = {
/*x1 2 3 4 5 6 7 8 9 10 11 12 */
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
/* Use buffered values. */
uint8_t month = time->month;
uint8_t day = time->day;
/* Using 16-bit unsigned integer accumulator. */
uint16_t days = day + pgm_read_word(&annual_table);
/* Append one day in leap year. */
if((month > 2) && qdt_is_leap_year(time)){
days += 1;
}
return days;
}
uint8_t qdt_is_leap_year(const qdt_time_t *time)
{
/* For every 400 years, it's transmigrated. */
uint16_t year = time->year % 400;
return ((year == 0) || ((year % 4 == 0) && (year % 100 != 0)));
}
啊呀格式好乱,凑合看吧。 又试了试,还能计算星期数:uint8_t qdt_day_of_week(const qdt_time_t *time)
{
uint32_t days;
/* Calculate the days with the Saturday compensation. */
days = (qdt_to_long_date(time) - 1) + 6;
return days % 7;
} 初验好像对的,有错误就以后更正。 擦,高手的帖子,顶一下,这算是科研了,一般人还真不知道为何要琢磨这个
页:
[1]