求助关于农历节气的算法

舟_雨 2008-03-06 03:32:22
小弟最近在写一个日历的程序,农历和星期都搞定了......可是
还需要在上面显示节气,比如什么“惊蛰”“立夏”“大寒小寒”……之类的东西。。。。天啦。。。。彻底晕了。。
我实在找不出来这些节气有什么规律可言,求助呀!呜呜!望高人点拨小弟!先谢谢啦!thank you in advance
...全文
2577 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
MobileCard 2010-08-08
  • 打赏
  • 举报
回复
对农历而言,子时(23:00-1:00)是新的一天的开始。也就是说,只要到23:00就算是第二天了。
rty 2009-01-20
  • 打赏
  • 举报
回复
用上面的算法算出来2012年的大寒是1-20号,但是查日梭万年历,2012年的大寒是1-21号,哪个是正确的啊???
chenjfeng2008 2008-07-30
  • 打赏
  • 举报
回复
大节之间相距16天,其他的相距15天
mLee79 2008-03-10
  • 打赏
  • 举报
回复
又找到个农历的网站, 发现有的节气的时间相差了2个小时, 不过日期倒没怎么差 ..
不过好像这些网站都注明:
"注意:由于农历24节气交节时刻采用近似算法,可能存在少量误差(30分钟内);时干支为当前时辰。 "
这个精度应该够了..
如果要准确点, 用权威机构发布的数据 每隔几年矫正一次应该会好些 ...

mLee79 2008-03-10
  • 打赏
  • 举报
回复
在 1900-2100 年应该还好, 检查了下, 最可能出错的几十天:
1957-11-07 23:59:46
1910-02-04 23:59:40
1910-04-05 23:59:40
2040-10-07 23:59:31
1915-08-08 23:59:31
2012-12-06 23:59:00
1960-09-08 00:01:04
2043-08-08 00:01:49
2038-02-04 00:01:59
2038-04-05 00:01:59
这些没有问题,其他的应该问题不大..
如果你的检查的有问题的话, 应该是它用的是 子时==23:00 计算的, 在23:00 以后的要加一天, 也检查了下:
2055-02-18 23:00:02
2078-09-22 22:59:42
2061-07-06 22:59:38
1984-12-21 22:59:30
1989-03-20 22:59:21
2058-07-22 22:59:20
2094-08-22 22:58:59
1921-12-07 23:01:07
好像也没有问题 ...

不过我检查的不是权威机构发布的数据, 那些好像要钱 ...


mathe 2008-03-10
  • 打赏
  • 举报
回复
基本应该差不多,不过如果运气不好,可能会有时候偶尔差一天(这好遇上半夜12点整左右的情况)。
我比较了2007和2008年的日历,发现节气之间长度的误差稍微有点大,能够达到几分钟。(也就是说,地球绕太阳运行速度由于收到其他行星影响,不是那么有规律)
mLee79 2008-03-10
  • 打赏
  • 举报
回复
这样吧, 检查过几年的数据, 应该差不多:


#include <stdio.h>
#include <stdlib.h>

static const double x_1900_1_6_2_5 = 693966.08680556;

double get_solar_term( int y , int n )
{
static const int termInfo[] = {
0 ,21208 ,42467 ,63836 ,85337 ,107014,
128867,150921,173149,195551,218072,240693,
263343,285989,308563,331033,353350,375494,
397447,419210,440795,462224,483532,504758
};
return x_1900_1_6_2_5+365.2422*(y-1900)+termInfo[n]/(60.*24);
}
int format_date( unsigned _days , char* result );
int main( int argc , char* argv[] )
{
static const char* solar_term_name[] = {
"小寒","大寒","立春","雨水",
"惊蛰","春分","清明","谷雨",
"立夏","小满","芒种","夏至",
"小暑","大暑","立秋","处暑",
"白露","秋分","寒露","霜降",
"立冬","小雪","大雪","冬至"
};
char str_d[100];
int year = 2008 , i;
if( argc == 2 )
{
year = atoi( argv[1] );
if( year < 1900 || year > 2099 )
year = 2008;
}
for( i = 0; i < 24; ++i )
{
format_date( (unsigned)get_solar_term( year , i ) , str_d );
printf( "%s : %s\n" , solar_term_name[i] , str_d );
}

return 0;
}

int format_date( unsigned _days , char* result )
{
static const int mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
int y , m , d , diff;
unsigned days;

days = 100 * (_days - _days/(3652425L/(3652425L-3652400L)) );
y = days / 36524; days %= 36524;
m = 1 + days/3044; /* [1..12] */
d = 1 + (days%3044)/100; /* [1..31] */

diff =y*365+y/4-y/100+y/400+mdays[m-1]+d-((m<=2&&((y&3)==0)&&((y%100)!=0||y%400==0))) - _days;

if( diff > 0 && diff >= d ) /* ~0.5% */
{
if( m == 1 )
{
--y; m = 12;
d = 31 - ( diff - d );
}
else
{
d = mdays[m-1] - ( diff - d );
if( --m == 2 )
d += ((y&3)==0) && ((y%100)!=0||y%400==0);
}
}
else
{
if( (d -= diff) > mdays[m] ) /* ~1.6% */
{
if( m == 2 )
{
if(((y&3)==0) && ((y%100)!=0||y%400==0))
{
if( d != 29 )
m = 3 , d -= 29;
}
else
{
m = 3 , d -= 28;
}
}
else
{
d -= mdays[m];
if( m++ == 12 )
++y , m = 1;
}
}
}

return sprintf( result , "%04d-%02d-%02d" , y , m , d );
}

mLee79 2008-03-10
  • 打赏
  • 举报
回复
没这么麻烦的, 用公历是很容易得到节气的...
办法就跟 mathe 的差不多, 不过精度要求不需要精确到秒这么高的, 精确到分钟足够了 ...
这样可以得到 y 年第 n 个节气的日期(公历), 从小寒开始.
1900-2100 年应该是没问题的, 其他的没有农历数据, 没检查过.


void getTermDay( int y , int n )
{
static const int termInfo[] = {
0 ,21208 ,42467 ,63836 ,85337 ,107014,
128867,150921,173149,195551,218072,240693,
263343,285989,308563,331033,353350,375494,
397447,419210,440795,462224,483532,504758
};
static const XDATE dt_1900_1_6_2_5 = { /* 1900/1/6 02:05:00 小寒 */
-36519 /* 距离 2000/1/1 的天数*/ , 7500000 /* 毫秒数 */
};
XDATE result = dt_1900_1_6_2_5;
XDATE_TM date_tm;

double day_diff = 365.2422 * (y-1900) + termInfo[n] / ( 60. * 24 );

result.days_from_y2000 += (int)day_diff;
result.millisecond += (int)((day_diff-(int)day_diff) * 24 * 60 * 60 * 1000);

if( result.millisecond >= XMILLISECOND_ONE_DAY )
result.millisecond -= XMILLISECOND_ONE_DAY , ++result.days_from_y2000;

X_date_2_tm( &result , &date_tm );

printf( "%d %d %d %d\n" , n , date_tm.year , date_tm.month , date_tm.day );
}

sooqing 2008-03-07
  • 打赏
  • 举报
回复
夏历其实是阴阳历,没有明显的规律,只能做一个表,查表
舟_雨 2008-03-07
  • 打赏
  • 举报
回复
天啦!!!!!!!!!!!
做完这个日历的模块加进节气后,我想我应该可以去做天文学家了。.....
这个节气咋就这么难列!!!!!!哎。
我现在把它们在做表,然后查表。。。。。
mathe 2008-03-07
  • 打赏
  • 举报
回复
冬至和夏至分别是地球近日点和远日点,如果我们有了地球绕太阳轨道方程(椭圆轨道,所以知道长轴半径和离心率就可以了),和地球绕太阳的周期,由于24节气是将360度等分24份角度,我们就可以计算出24个节气是地球在轨道上的位置(严格不变的)
然后按照开普乐的定律(第二定律?),行星在单位时间内扫过的面积是相同的,分别可以计算出每年各个节气到夏至的时间长度(这个也应该是常数,可以用秒表示)。
所以,从上面分析来看,基本上我们只要保存各个节气到冬至的时间长度,然后保存任何一年的冬至点时间(至少要精确到秒),那么我们就可以计算出24节气的确切时间(用公历时间表示比较方便)
mathe 2008-03-07
  • 打赏
  • 举报
回复
24节气应该只根据太阳在黄道上的位置来确定的(也就是同月球无关),我觉得应该是挺规律的。
NowCan 2008-03-07
  • 打赏
  • 举报
回复
根据太阳、地球、月亮的公转、自转周期可以算出来,但是相当繁。一般都是查表了。
medie2005 2008-03-06
  • 打赏
  • 举报
回复
see this:
http://topic.csdn.net/t/20030117/20/1369916.html

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧