農曆演算法簡介以及公式
一、節氣的計算
先給節氣進行編號,從近日點開始的第乙個節氣編為0,編號如下及其相應的月份如下:
0 小寒 臘月
6 清明 三月
12 小暑 六月
18 寒露 九月
1 大寒 臘月
7 穀雨 三月
13 大暑 六月
19 霜降 九月
2 立春 正月
8 立夏 四月
14 立秋 七月
20 立冬 十月
3 雨水 正月
9 小滿 四月
15 處暑 七月
21 小雪 十月
4 驚蟄 二月
10 芒種 五月
16 白露 八月
22 大雪 冬月
5 春分 二月
11 夏至 五月
17 秋分 八月
23 冬至 冬月
把當天和2023年1月0日(星期日)的差稱為積日,那麼第y年(2023年算第0年)第x 個節氣的積日是
f = 365.242 * y + 6.2 + 15.22 * x - 1.9 * sin(0.262 * x)
這個公式的誤差在0.05天左右。
二、朔日的計算
從2023年開始的第m個朔日的公式是
m = 1.6 + 29.5306 * m + 0.4 * sin(1 - 0.45058 * m)
這個公式的誤差在0.2天左右。
三、年份的確定
2023年1月0日是農曆癸亥年,所以用當年減去1864,用10除得的餘數作為年份天乾的,用12除得的餘數作為年份的地支,數字對應的天乾和地支如下。
數字 0
1 23 4
5 67 8
9 10
11 天乾
甲 乙丙 丁
戊 己庚 辛
壬 癸地支
子 丑寅 卯
辰 巳午 未
申 酉戌 亥
當年的1月0日換算為積日,可以用年份減去1900得到的年數被4整除,所得商數作為 y(d4),餘數作為y(m4),y(m4)為零的年份是公曆閏年,積日是
d(1) = 1461 * y(d4) - 1
y(m4)不為零的年份是公曆平年,積日是
d(1) = 1461 * y(d4) + 365 * y(m4)
四、月份的確定
計算前一年冬至的積日f(0),並用f(0)計算冬至所在的朔月m及其朔日m(0),就可以推算冬至的農曆日期,冬至所在的農曆月份總是十一月。計算下乙個中氣f(1)和下乙個朔日m(1),如果f(1)
太陽公轉週期,一年時間約365.2425天。
公曆為了對齊公轉週期,4年一閏,100年一停閏,400年加一閏。 400年共97閏, (365×400+97)/400 = 365.2425
農曆,乙個月相週期為一月,月相週期大約為29.53, 有大小月之分,大月30天,小月29天。月相變化受到地球公轉和月亮圍繞地球轉的共同影響,兩個都是橢圓軌道,且不在乙個平面上,非常複雜。所以,大小月變化規律不是乙個簡單的規律。
農曆為了對齊公轉週期,每19年加7個閏月,
因為,農曆的推算比較複雜, 大多使用查表法進行計算,包括我這裡提供的演算法。
我一直想實現乙個計算軌道的推算方法,因為人懶,現在還沒有什麼進展。我會繼續關注。
現在看到網上沒有找到滿意的c++查表農曆演算法法實現,所以自己實現了乙個。
以下檔案在linux g++ (gcc) 4.1.2 環境編譯通過
//file: lunarday.h
//author: [email protected]
//2007-02-13 11:22:04
#ifndef luanr_calendar_h
#define luanr_calendar_h
namespace lunar
date;
//公曆轉農曆
date luanrdate(
int solar_year,
int solar_month,
int solar_day);}
//file: lunarday.cpp
//author: [email protected]
//2007-02-13 11:22:48
#include
"lunarday.h"
#include
<
ctime
>
#include
#include
#include
<
iostream
>
using
namespace
std;
using lunar:
:date;
//使用位元位記錄每年的情況
//0~4 共5bit 春節日份
//5~6 共2bit 春節月份
//7~19 共13bit 13個月的大小月情況(如果無閏月,最後位無效),大月為1,小月為0
//20~23 共4bit 記錄閏月的月份,如果沒有閏月為0
static
const
int begin_year = 1901;
static
const
int number_year = 199;
static
const
unsigned
int lunar_years[199]=;
//計算這個公曆日期是一年中的第幾天
static
int dayofsolaryear(
int year,
int month,
int day )
;//閏年的情況
static
const
int leap_yday[12]=;
const
int*t_year_yday_ = normal_yday;
//判斷是否是公曆閏年
if( year % 4 =
=0 )
return t_year_yday_[month -1]
+(day -1);}
date lunar:
:luanrdate(
int solar_year,
int solar_month,
int solar_day)
int luanr_month = 1;
//計算月份和日期
for(
;luanr_month<
=13;luanr_month++)
luanr_date.day = today_luanr_yd;
//處理閏月
int leap_month =
(lunar_years[year_index]
>
>20)
& 0xf;
if(leap_month > 0 &
& leap_month < luanr_month )
assert
(leap_month <
= 12)
;luanr_date.month = luanr_month;
return luanr_date;
}
測試主函式,列印當前農曆日期
//file: chdate.cpp
//author: [email protected]
//2007-02-13 11:21:45
#include
<
iostream
>
#include
<
ctime
>
#include
"lunarday.h"
int main(
int argc,
char
*argv)
makefile檔案,如下
#makefile for chdate
cpp = g++
ld = g++
cc_flag =
ld_flag =
file_list = lunarday.cpp chdate.cpp
obj_list = $(file_list:%.cpp=%.o)
bin = chdate
default: $(bin)
$(bin): $(obj_list)
$(ld) $(ld_flag) -o $(bin) $(obj_list)
%.o : %.cpp
@$(cpp) $(cc_flag) -c $< -o $@
clean:
rm $(obj_list) $(bin)
執行效果如下
sideleft@doom:~/workspace/luanrday$ ./chdate
2023年12月26日
php實現的農曆演算法例項
再加當年的幾個月 total gmdate z gmmktime 0,0,0,month,1,year 用農曆的天數累加來判斷是否超過陽曆的天數 flag1 0 判斷跳出迴圈的條件 lcj 0 while lcj 120 lci if flag1 1 break lcj 由上,得到的 lci 為當前...
C 實現農曆日曆的方法
具體實現方法如下 複製 如下 天乾 private static string tiangan 地支 private static string dizhi 十二生肖 private static string shengxiao 農曆日期 private static string dayname...
C 公曆轉農曆演算法
using system using system.collections.generic using system.text 地支 private static string dizhi 十二生肖 private static string shengxiao 農曆日期 private stati...