此程序来源网络,部分程序存在问题,不过其方法也可以参考。
具体算法见函数void get_solar_day_date(void),这样阳历日历的星期排法就确定了。
表1:
变量定义:
Public:
Unsigned int temp_total_day;
Unsigned char gc_solar_calendar_year;
Unsigned char gc_solar_calendar_month;
Unsigned char gc_solar_calendar_date;
Unsigned char gc_lunar_calendar_year;
Unsigned char gc_lunar_calendar_month;
Unsigned char gc_lunar_calendar_date;
Unsigned char start_day_of_week;
说明:函数get_solar_day_date(void)的输入变量:gc_solar_calendar_year和gc_solar_calendar_month
输出变量:start_day_of_week和temp_total_day
void get_solar_day_date(void) { unsigned char temp01; start_day_of_week = 2; temp_total_day = 0; calculate_temp = 1; if (gc_solar_calendar_year > 99) { start_day_of_week = 6; calculate_temp = 100; } for (temp01 = calculate_temp; temp01 < 12; temp01++) { if (temp01 % 4 == 0) { start_day_of_week += 2; temp_total_day += 366; } else { start_day_of_week += 1; temp_total_day += 365; } } for (temp01 = 1; temp01 <= 12; temp01++) { switch (temp01) { case 1, 3, 5, 7, 8, 10, 12: start_day_of_week += 3; temp_total_day += 31; break; case 2: if (((gc_solar_calendar_year % 4) == 0) && (gc_solar_calendar_year != 200)) { start_day_of_week += 1; temp_total_day += 29; } else { start_day_of_week += 0; temp_total_day += 28; } break; case 4, 6, 9, 11: start_day_of_week += 2; temp_total_day += 30; break; } } start_day_of_week %= 7; }
200年需要200 × 2 = 400个字节,构成阴历压缩数据表lunar_calendar_month_table[]如下
const char lunar_calendar_month_table[] = { //从阴历年1900年到2100年 /*the total day of each month pointer */ 月份 1 2 3 4 5 6 7 8 9 10 11 12 闰年 31 29 31 30 31 30 31 31 30 31 30 31 非闰年 31 28 31 30 31 30 31 31 30 31 30 31 /* from 1901~2100*/ /* (0110)110000001001 (0110)leap month,110000001001 lunar month total day: 1:29 0:30*/ 0x00, 0x04, 0xad, 0x08, 0x5a, 0x01, 0xd5, 0x54, 0xb4, 0x09, 0x64, 0x05, 0x59, 0x45, 0x95, 0x0a, 0xa6, 0x04, 0x55, 0x24, 0xad, 0x08, 0x5a, 0x62, 0xda, 0x04, 0xb4, 0x05, 0xb4, 0x55, 0x52, 0x0d, 0x94, 0x0a, 0x4a, 0x2a, 0x56, 0x02, 0x6d, 0x71, 0x6d, 0x01, 0xda, 0x02, 0xd2, 0x52, 0xa9, 0x05, 0x49, 0x0d, 0x2a, 0x45, 0x2b, 0x09, 0x56, 0x01, 0xb5, 0x20, 0x6d, 0x01, 0x59, 0x69, 0xd4, 0x0a, 0xa8, 0x05, 0xa9, 0x56, 0xa5, 0x04, 0x2b, 0x09, 0x9e, 0x38, 0xb6, 0x08, 0xec, 0x74, 0x6c, 0x05, 0xd4, 0x0a, 0xe4, 0x6a, 0x52, 0x05, 0x95, 0x0a, 0x5a, 0x42, 0x5b, 0x04, 0xb6, 0x04, 0xb4, 0x22, 0x6a, 0x05, 0x52, 0x75, 0xc9, 0x0a, 0x52, 0x05, 0x35, 0x55, 0x4d, 0x0a, 0x5a, 0x02, 0x5d, 0x31, 0xb5, 0x02, 0x6a, 0x8a, 0x68, 0x05, 0xa9, 0x0a, 0x8a, 0x6a, 0x2a, 0x05, 0x2d, 0x09, 0xaa, 0x48, 0x5a, 0x01, 0xb5, 0x09, 0xb0, 0x39, 0x64, 0x05, 0x25, 0x75, 0x95, 0x0a, 0x96, 0x04, 0x4d, 0x54, 0xad, 0x04, 0xda, 0x04, 0xd4, 0x44, 0xb4, 0x05, 0x54, 0x85, 0x52, 0x0d, 0x92, 0x0a, 0x56, 0x6a, 0x56, 0x02, 0x6d, 0x02, 0x6a, 0x41, 0xda, 0x02, 0xb2, 0xa1, 0xa9, 0x05, 0x49, 0x0d, 0x0a, 0x6d, 0x2a, 0x09, 0x56, 0x01, 0xad, 0x50, 0x6d, 0x01, 0xd9, 0x02, 0xd1, 0x3a, 0xa8, 0x05, 0x29, 0x85, 0xa5, 0x0c, 0x2a, 0x09, 0x96, 0x54, 0xb6, 0x08, 0x6c, 0x09, 0x64, 0x45, 0xd4, 0x0a, 0xa4, 0x05, 0x51, 0x25, 0x95, 0x0a, 0x2a, 0x72, 0x5b, 0x04, 0xb6, 0x04, 0xac, 0x52, 0x6a, 0x05, 0xd2, 0x0a, 0xa2, 0x4a, 0x4a, 0x05, 0x55, 0x94, 0x2d, 0x0a, 0x5a, 0x02, 0x75, 0x61, 0xb5, 0x02, 0x6a, 0x03, 0x61, 0x45, 0xa9, 0x0a, 0x4a, 0x05, 0x25, 0x25, 0x2d, 0x09, 0x9a, 0x68, 0xda, 0x08, 0xb4, 0x09, 0xa8, 0x59, 0x54, 0x03, 0xa5, 0x0a, 0x91, 0x3a, 0x96, 0x04, 0xad, 0xb0, 0xad, 0x04, 0xda, 0x04, 0xf4, 0x62, 0xb4, 0x05, 0x54, 0x0b, 0x44, 0x5d, 0x52, 0x0a, 0x95, 0x04, 0x55, 0x22, 0x6d, 0x02, 0x5a, 0x71, 0xda, 0x02, 0xaa, 0x05, 0xb2, 0x55, 0x49, 0x0b, 0x4a, 0x0a, 0x2d, 0x39, 0x36, 0x01, 0x6d, 0x80, 0x6d, 0x01, 0xd9, 0x02, 0xe9, 0x6a, 0xa8, 0x05, 0x29, 0x0b, 0x9a, 0x4c, 0xaa, 0x08, 0xb6, 0x08, 0xb4, 0x38, 0x6c, 0x09, 0x54, 0x75, 0xd4, 0x0a, 0xa4, 0x05, 0x45, 0x55, 0x95, 0x0a, 0x9a, 0x04, 0x55, 0x44, 0xb5, 0x04, 0x6a, 0x82, 0x6a, 0x05, 0xd2, 0x0a, 0x92, 0x6a, 0x4a, 0x05, 0x55, 0x0a, 0x2a, 0x4a, 0x5a, 0x02, 0xb5, 0x02, 0xb2, 0x31, 0x69, 0x03, 0x31, 0x73, 0xa9, 0x0a, 0x4a, 0x05, 0x2d, 0x55, 0x2d, 0x09, 0x5a, 0x01, 0xd5, 0x48, 0xb4, 0x09, 0x68, 0x89, 0x54, 0x0b, 0xa4, 0x0a, 0xa5, 0x6a, 0x95, 0x04, 0xad, 0x08, 0x6a, 0x44, 0xda, 0x04, 0x74, 0x05, 0xb0, 0x25, 0x54, 0x03, };
确定阳历日和阴历日的对应关系的算法:
对于其他任何一个阳历日和阴历日的对应关系,都可以通过以下算法求得结果。具体算法由如get_lunar_day(void)实现:
说明:函数get_lunar_day(void)的输入变量:gc_solar_calendar_year和gc_solar_calendar
输出变量:gc_lunar_calendar_year、gc_lunar_calendar_month和gc_lunar_calendar_date
void get_lunar_day(void) { unsigned char temp_leap_month; unsigned char temp_flag; unsigned char calculate_temp; unsigned char mc_tpumenus_temp_loop; unsigned char mc_tpumenus_temp_01; temp_leap_month = 0; temp_flag = 1; //条件初始化二次,减少运算数据量. if (gc_solar_calendar_year > 99) { gc_lunar_calendar_year = 99; gc_lunar_calendar_month = 11; gc_lunar_calendar_date = 25; temp_total_day += 25; calculate_temp = 100; } else { gc_lunar_calendar_year = 0; gc_lunar_calendar_month = 11; gc_lunar_calendar_date = 11; temp_total_day += 11; calculate_temp = 1; } if (gc_solar_calendar_year > calculate_temp || gc_solar_calendar_month > 1) { for (mc_tpumenus_temp_loop = 1; mc_tpumenus_temp_loop > 0;) { temp_total_day -= calendar_calculate_lunar_month_total_day(); temp_leap_month = tpumenus_lunar_calendar_month_table[2 * gc_lunar_calendar_year + 1]; temp_leap_month = (temp_leap_month >> 4) & 0x0F; if (gc_lunar_calendar_month == temp_leap_month) { switch (gc_lunar_calendar_year) { case 6, 14, 19, 25, 33, 36, 38, 41, 44, 52, 55, 79, 117, 136, 147, 150, 155, 158, 185, 193: if (temp_total_day < 31) { gc_lunar_calendar_date = temp_total_day; mc_tpumenus_temp_loop = 0; temp_flag = 0; } else { temp_total_day -= 30; } break; //current month:temp_leap_month default: if (temp_total_day < 30) { gc_lunar_calendar_date = temp_total_day; mc_tpumenus_temp_loop = 0; temp_flag = 0; } else { temp_total_day -= 29; } break; } } if (temp_flag) { gc_lunar_calendar_month++; if (gc_lunar_calendar_month == 13) { gc_lunar_calendar_month = 1; gc_lunar_calendar_year++; } if (temp_total_day < 61) { //if temp_total_day>60,ignore compare mc_tpumenus_temp_01 = calendar_calculate_lunar_month_total_day(); if (temp_total_day < (mc_tpumenus_temp_01 + 1)) { mc_tpumenus_temp_loop = 0; gc_lunar_calendar_date = temp_total_day; } } } } } gc_lunar_leap_month = (temp_flag << 4) | temp_leap_month; /*set leap_month flag*/ }
说明:函数calendar_calculate_lunar_month_total_day(void)根据输入变量gc_lunar_calen和gc_lunar_calendar_month,结合压缩数据表lunar_calendar_month_table计算出对应阴历天数。
unsigned char calendar_calculate_lunar_month_total_day(void) { unsigned char mc_tpumenus_temp_01; unsigned char mc_tpumenus_temp_02; if (gc_lunar_calendar_month < 9) { mc_tpumenus_temp_01 = lunar_calendar_month_table[2 * gc_lunar_calendar_year]; mc_tpumenus_temp_02 = gc_lunar_calendar_month - 1; } else { mc_tpumenus_temp_01 = lunar_calendar_month_table[2 * gc_lunar_calendar_year + 1]; mc_tpumenus_temp_02 = gc_lunar_calendar_month - 9; } if ((mc_tpumenus_temp_01 >> mc_tpumenus_temp_02) & 0x01) { return (29); } else { return (30); } }
阳历日和农历节气的对应关系
压缩节气数据表:
根据规律可以得到四个数据表(每个阳历月有两个节气,每个节气需要两个数据表):
const unsigned char calendar_solar_term_table_01[12][33] = { {7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5}, //month 1 {5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 3, 4, 4, 3, 3, 3}, //2 {6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5}, //3 {5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 5, 4, 4, 4, 4, 5}, //4 {6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5}, //5 {6, 6, 7, 7, 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5}, //6 {7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 6, 6, 6, 7, 7}, //7 {8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7}, //8 {8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 7}, //9 {9, 9, 9, 9, 8, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 8}, //10 {8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7}, //11 {7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 6, 6, 6, 7, 7}, //12 }; //这个数据表表示了每个月第一个节气出现的规律 const unsigned char calendar_solar_term_year_01[12][9] = { {13, 49, 85, 117, 149, 185, 201, 250, 250}, //month 1 {13, 45, 81, 117, 149, 185, 201, 250, 250}, //2 {13, 48, 84, 112, 148, 184, 200, 201, 250}, //3 {13, 45, 76, 108, 140, 172, 200, 201, 250}, //4 {13, 44, 72, 104, 132, 168, 200, 201, 250}, //5 {5, 33, 68, 96, 124, 152, 188, 200, 201}, //6 {29, 57, 85, 120, 148, 176, 200, 201, 250}, //7 {13, 48, 76, 104, 132, 168, 196, 200, 201}, //8 {25, 60, 88, 120, 148, 184, 200, 201, 250}, //9 {16, 44, 76, 108, 144, 172, 200, 201, 250}, //10 {28, 60, 92, 124, 160, 192, 200, 201, 250}, //11 {17, 53, 85, 124, 156, 188, 200, 201, 250}, //12 }; //这个数据表表示了每个月第一个节气出现规律对应的阳历年份范围 const unsigned char calendar_solar_term_table_02[12][29] = { {21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20}, {20, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19, 19, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18}, {21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 20}, {20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20, 20, 19, 19, 19, 20, 20}, {21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 21}, {22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 21}, {23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 23}, {23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23}, {23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23}, {24, 24, 24, 24, 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 23}, {23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 22}, {22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 22}, }; //这个数据表表示了每个月第二个节气出现的规律 const unsigned char calendar_solar_term_year_02[12][8] = { {13, 45, 81, 113, 149, 185, 201}, {21, 57, 93, 125, 161, 193, 201}, {21, 56, 88, 120, 152, 188, 200, 201}, {21, 49, 81, 116, 144, 176, 200, 201}, {17, 49, 77, 112, 140, 168, 200, 201}, {28, 60, 88, 116, 148, 180, 200, 201}, {25, 53, 84, 112, 144, 172, 200, 201}, {29, 57, 89, 120, 148, 180, 200, 201}, {17, 45, 73, 108, 140, 168, 200, 201}, {28, 60, 92, 124, 160, 192, 200, 201}, {16, 44, 80, 112, 148, 180, 200, 201}, {17, 53, 88, 120, 156, 188, 200, 201}, }; //这个数据表表示了每个月第二个节气出现规律对应的阳历年份范围 每个阳历月对应的两个农历节气出现的日期,可根据条件规律算法,分别由以下两个函数实现 unsigned char calendar_calculate_solar_term_1(void) { zpage unsigned char done_index; zpage unsigned char solar_term; done_index = 0; while (gc_solar_calendar_year >= calendar_solar_term_year_01[gc_solar_calendar_month - 1][done_index]) { done_index++; } solar_term = calendar_solar_term_table_01[gc_solar_calendar_month - 1][4 * done_index + gc_solar_calendar_year % 4]; if ((gc_solar_calendar_year == 121) && (gc_solar_calendar_month == 4)) { solar_term = 5; } if ((gc_solar_calendar_year == 132) && (gc_solar_calendar_month == 4)) { solar_term = 5; } if ((gc_solar_calendar_year == 194) && (gc_solar_calendar_month == 6)) { solar_term = 6; } return (solar_term); } //计算阳历月对应的第一个节气 unsigned char calendar_calculate_solar_term_2(void) { zpage unsigned char done_index; zpage unsigned char solar_term; done_index = 0; while (gc_solar_calendar_year >= calendar_solar_term_year_02[gc_solar_calendar_month - 1][done_index]) { done_index++; } solar_term = calendar_solar_term_table_02[gc_solar_calendar_month - 1][4 * done_inddx + gc_solar_calendar_year % 4]; if ((gc_solar_calendar_year == 171) && (gc_solar_calendar_month == 3)) { solar_term = 21; } if ((gc_solar_calendar_year == 181) && (gc_solar_calendar_month == 5)) { solar_term = 21; } return (solar_term); } //计算阳历月对应的第二个节气
以上就是万年历的完整算法。它首先计算出对应阳历月第一天对应是星期几,然后根据数据压定,确定对应的阴历日期;而阴历节气,则有条件规律算法实现。