C++ 實現萬年歷(原創)


任務要求

功能要求:

1)提供菜單方式選擇,假定輸入的年份在1940-2040年之間。

2)輸入一個年份,輸出是在屏幕上顯示該年的日歷。

3)輸入年月,輸出該月的日歷,如圖2-1所示:

  

                          2- 1 月日歷

4)輸入年份、月份、日期,計算得到的是這一天據今天有多少天,星期幾。

5)輸入公歷的年月日,輸出農歷年月日。

6)輸入農歷節氣,輸出當年農歷的年月日及公歷年月日。可以假定只涉及年份是1940年到2040年。

總體設計

將文件三部分 Date.h、main.cpp、Date.cpp

1) Date.h:包括函數的聲明。

2) main.cpp:包含調用與模擬交互界面的函數代碼

3) Date.cpp:

//輸入輸入一個年份,輸出是在屏幕上顯示該年的日歷。

void print_annual_calendar(int year)

//輸入年月,輸出該月的日歷。

void print_monthly_calendar(int year,int month)

//輸入年份、月份、日期,計算得到的是這一天據今天有多少天,星期幾。

void print_number_week(int year,int month ,int day)

//輸入公歷,顯示農歷。

void gregorian_to_lunar (int year,int month,int day)

//輸入農歷節氣,輸出當年農歷的年月日和公歷年月日。

void solar_term(char *str)

詳細設計說明

(1) 查詢距今多少天,星期幾?

①計算某一日期到1939年1月1日的天數:getDaysTo1939(int year, int month, int day)

  1. 判斷是否是閏年(平年365天,閏年366天),函數如表4-1所示:

4- 1 isLeapYear函數

定義函數

bool isLeapYear(int year)

返回值

若year年是閏年返回true,否則返回false

參數說明

year參數是要判斷的年份

  1. 判斷某年某月有多少天?函數如表4-2所示:

4- 2 getDaysOfMonth函數

定義函數

int getDaysOfMonth(int year,int month)

返回值

返回year年month月的天數

參數說明

year、month參數分別是要查詢的年、月

 例如:計算2020年8月14日到1939年1月1日的天數。首先1939-2019年是整數年,直接判斷是否是閏年,然后增加天數。2020年不是整年,但1-7月是整數月,根據年、月獲取當月天數累加。最后再加天數day,便得出相距與1939年1月1日的天數。

②計算查詢日期距今天多少天?getDaysOfMonthToToday(int year, int month, int day) ,函數如表4-3所示:

  1. 通過函數獲取系統時間,通過getDaysTo1939(),獲取系統時間距1939年1月1日的天數num1。
  2. 使用鍵盤輸入的日期,通過getDaysTo1939(),獲取輸入日期距1939年1月1日的天數num2。
  3. 使用num1-num2計算輸入日期距今天的天數,正數為已過去時間,負數為未來時間。

4- 3 getDaysOfMonthToToday函數

定義函數

int getDaysOfMonthToToday(int year,int month,int day)

返回值

返回距今天數,正值為過去,負值為未來

參數說明

year、month、day 分別為要查詢的年、月、日

 

③計算輸入日期是星期幾:getDayOfWeek(int year,int month,int day) ,函數如表4-4所示:

 

  1. 知道1939年1月1日是星期日,然后計算查詢日期與1939年距離多少天,然后利用(天數%7)獲取余數,得出星期屬性。

4- 4 getDayOfWeek函數

定義函數

String getDayOfWeek(int year,int month,int day)

返回值

返回字符串星期數

參數說明

year、month、day 分別為要查詢的年、月、日

 

 

(2) 打印月日歷

  1. 獲取當月1日是星期幾,通過getDayOfWeek1()獲取當月一號是星期幾,然后通過打印空格使得當月1日,停在所對應的星期下方,函數如表4-5所示:

4- 5 getDayOfWeek1函數

定義函數

int getDayOfWeek1(int year,int month,int day)

返回值

返回星期數,0代表星期天

參數說明

year、month、day 分別為要查詢的年、月、日

 

  1. 獲取當月天數,通過getDaysOfMonth()獲取,打印完最后一天時間便結束,函數如表4-6所示:

4- 6 getDaysOfMonth函數

定義函數

int getDaysOfMonth(int year,int month)

返回值

返回year年month月天數

參數說明

year、month分別為要查詢的年、月

 

 

(3) 打印年日歷

① 打印季度日歷,函數如表4-7所示:

  1. 首先打印日歷頭信息三遍(由於是按照季度輸出,一行包含三個月),格式:(月份 SUN MON SUN MON TUE WED THU FRI SAT)
  2. 依次打印日歷的第一行,每月的第一日對應的星期數,通過打印空格來調整。
  3. 依次打印連續的日期。最后一行,日期與日期之間依然要使用空格來調整位置。

4- 7 print_seasons_calendar函數

定義函數

void print_seasons_calendar(int year,int num)

返回值

無返回值

參數說明

year、num分別為要打印的年、季度,num可取1,2,3,4

 

① 打印年日歷,函數如表4-8所示:

  1. 通過for循環打印四個季度的日歷,便完成年日歷的輸出。

4- 8 print_annual_calendar函數

定義函數

void print_annual_calendar(int year)

返回值

無返回值

參數說明

year為要打印的年份

 

 

(4) 公歷轉農歷

① 計算輸入的時間距離1939年1月1日的天數。

② 獲取農歷年天數(通過農歷數據表查詢):getDayOfNongYear(int year)

  1. 獲取農歷年是否為閏年,返回閏月月份,函數如表4-9所示:

4- 9 isNongLeapYear函數

定義函數

int isNongLeapYear(int year)

返回值

返回農歷year年閏月月份,0表示不閏

參數說明

year為要查詢的年

 

  1. 獲取每個月有多少天,函數如表4-10所示:

4- 10 getDaysOfMonthOfNongMonth函數

定義函數

int getDaysOfMonthOfNongMonth(int year,int month)

返回值

返回農歷year年month月的天數

參數說明

year、month分別為要查詢的年、月

 

  1. 獲取閏月大小,函數如表4-11所示: 

4- 11 is_large_month函數

定義函數

bool is_large_month(int year)

返回值

閏大月返回true,閏小月返回false

參數說明

year為要查詢的年

 

③ 計算農歷日期,函數如表4-12所示:

  1. 由於1939年1月1日農歷往往是1938年,所以首先減去公歷1939年1月1日到農歷1939年正月初一的天數。
  2. 循環計算便得出農歷日期。日期的文字形式可以保存在數組中進行拼接輸出。

4- 12 gregorian_to_lunar函數

定義函數

void gregorian_to_lunar (int year,int month,int day)

返回值

無返回值

參數說明

year、month、day分別為要轉換的年、月、日

 

 

(5) 查詢節氣時間,函數如表4-13所示:

  1. 計算二十四節氣對應的公歷日期(通過壽星公式計算)
  2. 得出公歷日期,直接使用公歷轉農歷函數,打印農歷日期。

4- 13 solar_term函數

定義函數

void solar_term(int year,char* str)

返回值

無返回值

參數說明

year代表要查詢的年份,str表示查詢的節氣名稱,如立秋。

調試與測試

(1) 交互界面顯示

 

 

(2) 打印年日歷

 

                      圖3- 2 年日歷

(3) 打印月日歷

            3- 3  月日歷

(4) 查詢距今多少天,星期幾? 

                   3- 4  距今天數,星期數

(5) 公歷轉農歷

                    3- 5  公歷轉農歷

 (6) 查詢節氣時間

                圖3- 6  查詢二十四節氣

代碼實現

Date.h:
#ifndef DATE_H
#define DATE_H
/*輸入年份、月份、日期,計算得到的是這一天據今天有多少天?星期幾?*/
void print_number_week(int year,int month,int day);
/*輸入年月,輸出該月的日歷。*/
void print_monthly_calendar(int year,int month);
/*輸入輸入一個年份,輸出是在屏幕上顯示該年的日歷。*/
void print_annual_calendar(int year);
/*輸入公歷,顯示農歷。*/
void gregorian_to_lunar (int year,int month,int day);
/*輸入年份,二十四節氣*/
void solar_term(int year,char* str);
/*歡迎界面*/
void print();
#endif // DATE_H

main.cpp:
#include <iostream>
#include "Date.h"
using namespace std;

int main()
{

    int num;
    char solar_Terms[3];
    int year,month,day;
    print();
    while(1)
    {

        cout<<"\n請選擇服務序號:";
        cin>>num;
        switch(num)
        {
        case 1:
            cout<<"請輸入要查詢的年份:";
            cin>>year;
            print_annual_calendar(year);
            break;
        case 2:
            cout<<"請輸入要查詢的年、月:";
            cin>>year>>month;
            print_monthly_calendar(year,month);
            break;
        case 3:
            cout<<"請輸入要查詢的年、月、日:";
            cin>>year>>month>>day;
            print_number_week(year,month,day);
            break;
        case 4:
            cout<<"請輸入要查詢的年、月、日:";
            cin>>year>>month>>day;
            gregorian_to_lunar (year,month,day);
            break;
        case 5:
            cout<<"請輸入要查詢的年份及節氣:";
            cin>>year>>solar_Terms;
            solar_term(year,solar_Terms);
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

Date.cpp:
#include "Date.h"
#include <stdio.h>
#include <ctime>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string.h>

using namespace std;


/*農歷查詢表  來源:https://www.jianshu.com/p/57e7bd43c00b    */
/*第1位    表示假如有閏月,0代表閏小月,1代表閏大月
 *第2-4位  表示12個二進制位 一位表示一個月是大月還是小月
 *最后1位  表示閏哪個月,0表示不閏*/
unsigned int LunarCalendar[199] =
{
    /*1900年開始*/
    /*0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
    0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
    0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
    0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,*/
    /*我的日歷要求1940-2040年 以上用不到*/

    0x0c950,/*1939年*/   /*查詢公歷1940年1月,農歷其實是1939年*/
    0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
    0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
    0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
    0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
    0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
    0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
    0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
    0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
    0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
    0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
    0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0
};

/*獲取系統時間*/
void gettime(int &year,int &month,int &day)
{
    time_t time1;
    struct tm *ptime;
    time(&time1);
    ptime = localtime(&time1);
    year=ptime->tm_year + 1900;
    month=ptime->tm_mon + 1;
    day=ptime->tm_mday;
}

/*判斷year年是否是閏年*/
bool isLeapYear(int year)
{
    /*可以被4且100整除或者可以被400整除*/
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/*獲取year年month月有多少天*/
int getDaysOfMonth(int year,int month)
{
    /*平年各月公歷天數*/
    int days[12]= {31,28,31,30,31,30,31,31,30,31,30,31};
    if(isLeapYear(year)&&month==2)
        return 29;
    else
        return days[month-1];
}

/*獲取year年month月day日到1939年1月1日的天數*/
int getDayTo1939(int year,int month,int day)
{
    int days=0;
    /*從1939年開始計算,直到year-1年,它們都是整數年*/
    for(int i=year-1; i>=1939; i--)
    {
        if(isLeapYear(i))
            days+=366;
        else
            days+=365;
    }
    /*計算year年1月到year年month-1月  它們是整數月*/
    for(int i=month-1; i>0; i--)
    {
        days+=getDaysOfMonth(year,i);
    }
    /*計算year年month月1日到yera年month月day日天數*/
    days+=day;
    return days-1;
}

/*獲取year年month月day日是星期幾*/
string getDayOfWeek(int year,int month,int day)
{
    string weeks[7]= {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
    /*獲取year年month月day日到1939年1月1日的天數*/
    int days=getDayTo1939(year,month,day);
    int week=days%7;
    return weeks[week];
}
/*整型版星期幾*/
int getDayOfWeek1(int year,int month,int day)
{
    int days=getDayTo1939(year,month,day);
    int week=days-(days/7)*7;
    return week;
}

/*獲取year年month月day日到現在的天數 正值為過去,負值為未來*/
int getDaysOfMonthToToday(int year,int month,int day)
{
    int nowyear;
    int nowmonth;
    int nowday;
    gettime(nowyear,nowmonth,nowday);
    /*現在時間到1939年1月1日的天數*/
    int nowto1939=getDayTo1939(nowyear,nowmonth,nowday);
    /*輸入的時間到1939年1月1日的天數*/
    int tempto1939=getDayTo1939(year,month,day);
    /*正數為過去,負數為未來*/
    return nowto1939-tempto1939;
}

/*檢查年月日合法性*/
bool checkDate(int year,int month,int day)
{
    /*還需要判斷 year年month月  是否含day天,比如4月有30天,輸入31就是錯誤的*/
    if(year<1939||year>2041||month<0||month>12||day<0||day>getDaysOfMonth(year,month))
        return false;
    else
        return true;
}


void print_number_week(int year,int month,int day)
{
    if(!checkDate(year,month,day))
    {
        cout<<"日期輸入出錯,請確保日期正確性!"<<endl;
        return;
    }
    if(getDaysOfMonthToToday(year,month,day)>0)
        cout<<year<<""<<month<<""<<day<<"日\t"<<getDayOfWeek(year,month,day)<<"\t距現在已過去"<<getDaysOfMonthToToday(year,month,day)<<""<<endl;
    else
        cout<<year<<""<<month<<""<<day<<"日\t"<<getDayOfWeek(year,month,day)<<"\t距現在還有"<<-getDaysOfMonthToToday(year,month,day)<<""<<endl;
}

/*輸入年份月份輸出月日歷表*/
void print_monthly_calendar(int year,int month)
{
    if(year>2041||year<1939||month>12||month<1)
    {
        cout<<"日期輸入出錯,請確保日期正確性!"<<endl;
        return;
    }
    cout<<"\t"<<year<<""<<month<<""<<endl;
    cout<<" SUN MON TUE WED THU FRI SAT"<<endl;
    /*計算year年month月1日星期幾*/
    int week=getDayOfWeek1(year,month,1);
    /*調整1日到對應的星期數*/
    for(int i=1; i<=week&&week!=7; i++)
        cout<<"    ";
    /*打印日歷信息*/
    for(int i=1; i<=getDaysOfMonth(year,month); i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week+i)%7==0)
            cout<<endl;
    }
}


/*輸入年份、季度 一行輸出3個月*/
void print_seasons_calendar(int year,int num)
{
    if(num>4||num<0)
    {
        cout<<"輸入季度出錯!"<<endl;
        return;
    }
    int month=1+3*(num-1);
    /*打印日歷頭*/
    cout<<month<<" SUN MON TUE WED THU FRI SAT\t"<<month+1<<" SUN MON TUE WED THU FRI SAT\t"<<month+2<<" SUN MON TUE WED THU FRI SAT"<<endl;
    /*week1、week2、week3 分別代表一個季度的三個月的一日對應星期數*/
    int week1=getDayOfWeek1(year,month,1);
    int week2=getDayOfWeek1(year,month+1,1);
    int week3=getDayOfWeek1(year,month+2,1);
    /*tmp1、tmp2、tmp3分別代表三個月的最大天數*/
    int tmp1=getDaysOfMonth(year,month),tmp2=getDaysOfMonth(year,month+1),tmp3=getDaysOfMonth(year,month+2);

    int day1,day2,day3;

    /*依次輸出第一行信息*/
    cout<<"  ";
    for(int i=1; i<=week1 &&week1!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp1; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week1+i)%7==0)
        {
            day1=i+1;
            break;
        }
    }
    cout<<"    ";
    for(int i=1; i<=week2 && week2!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp2; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week2+i)%7==0)
        {
            day2=i+1;
            break;
        }
    }
    cout<<"    ";
    for(int i=1; i<=week3 && week3!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp3; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week3+i)%7==0)
        {
            day3=i+1;
            cout<<endl;
            break;
        }
    }

    /*打印余下信息*/
    for(int j=0; j<5; j++)
    {
        /*如果三個月信息全部打印完,則退出*/
        if(day1>tmp1&&day2>tmp2&&day3>tmp3)
            break;
        /*數字21代表一行三個周,可容納21天*/
        for(int i=0; i<21;)
        {
            cout<<"  ";
            while(i<7)
            {
                i++;
                /*如果沒打印完就打印數字,如果整月天數已經打印完,則輸出空格*/
                if(day1<=tmp1)
                    cout<<setw(3)<<day1++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
            /*打印月份與月份之間的間隔*/
            cout<<"    ";
            while(i<14&&i>=7)
            {
                i++;
                if(day2<=tmp2)
                    cout<<setw(3)<<day2++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
            cout<<"    ";
            while(i<21&&i>=14)
            {
                i++;
                if(day3<=tmp3)
                    cout<<setw(3)<<day3++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
        }
        cout<<endl;
    }
    cout<<endl;
}

/*顯示歡迎界面*/
void print()
{
    cout<<"\n\t\t歡迎來到我的日歷表(1940-2040年)"<<endl;
    cout<<"\t\t功能選擇:"<<endl;
    cout<<"\t\t1.查詢年日歷表"<<endl;
    cout<<"\t\t2.查詢月日歷表"<<endl;
    cout<<"\t\t3.查詢距今多少天?星期幾?"<<endl;
    cout<<"\t\t4.輸入公歷查詢農歷"<<endl;
    cout<<"\t\t5.輸入節氣查詢對應公歷、農歷"<<endl;
    cout<<"\t\t*****按0退出*****"<<endl;
}

/*輸出年日歷表*/
void print_annual_calendar(int year)
{
    if(year>2041||year<1939)
    {
        cout<<"日期輸入出錯,請確保日期正確性!"<<endl;
        return;
    }
    cout<<"\t\t\t\t\t  "<<"------------"<<endl;
    cout<<"\t\t\t\t\t  "<<year<<"年日歷表"<<endl;
    cout<<"\t\t\t\t\t  "<<"------------"<<endl;

    /*循環輸出四個季度 打印完整年日歷*/
    for(int i=1; i<=4; i++)
    {
        print_seasons_calendar(year,i);
    }
}


string nongMonth[]= {" ","正月","二月","三月","四月","五月","六月","七月","八月","九月","十月","冬月","臘月"};
string nongday[]= {"","","","","","","","","","",""};
string nongday2[]= {"","","廿",""};


/*判斷潤大小月*/
bool is_large_month(int year)
{
    /*查表找出是否為閏月 判斷high是不是為0*/
    int high =(LunarCalendar[year-1939]>>16);
    if(high==0x00)
        return false;
    else
        return true;
}
/*返回 潤幾月  0代表不閏*/
int isNongLeapYear(int year)
{
    /*輸出農歷潤幾月*/
    int low = LunarCalendar[year-1939] & 0xF;
    return low;
}

/*判斷農歷某年某月多少天*/      /*LunarCalendar 表示農歷對照表*/
int getDaysOfMonthOfNongMonth(int year,int month)
{
    /*查表,根據大小月,計算農歷月天數*/
    int bit=1 << (16-month);
    if((LunarCalendar[year-1939]/*&0x0000FFFF*/&bit)==0)
        return 29;
    else
        return 30;
}

/*判斷某年農歷多少天*/
int getDayOfNongYear(int year)
{
    int days=0;
    /*農歷十二個月天數*/
    for(int i=1; i<=12; i++)
    {
        days+=getDaysOfMonthOfNongMonth(year,i);
    }
    /*假如有閏月,加上閏月天數*/
    if(isNongLeapYear(year)!=0)
    {
        if(is_large_month(year))
            days+=30;
        else
            days+=29;
    }
    return days;
}


/*輸出農歷日歷*/
void printNong(int days)
{
    int year=1939,month=1,day=1;
    /*由於1939年1月1日往往是農歷1938年,所以減去48天,從1939年正月初一計算,因為本計算器計算范圍為1940年-2040年 所以可以滿足*/
    days-=48;

    /*判斷減去下一年的天數,會不會是負值,不是便減去並增加農歷年*/
    for(int i=1939; (days-getDayOfNongYear(i))>0; i++)
    {
        days-=getDayOfNongYear(i);
        year=i+1;
    }
    int num;
    int signal=0;
    /*判斷減去下一月天數,會不會是負值,不會便農歷月加1*/
    for(int j=1; ((days-getDaysOfMonthOfNongMonth(year,j))>0)&&j<12; j++)
    {
        days-=getDaysOfMonthOfNongMonth(year,j);
        if(j==isNongLeapYear(year))
        {
            if(is_large_month(year))
            {
                days-=30;
                num=30;
            }
            else
            {
                days-=29;
                num=29;
            }
        }
        /*當減去農歷月的時候,加入變為負值,那么再加回來*/
        if(days<0)
        {
            /*農歷閏月標記*/
            signal=1;
            days +=num;
            month=j;
            break;
        }
        month=month+1;
    }
    /*剩余天數便是農歷日*/
    day=days;
    cout<<year<<"";
    if(signal==1)
        cout<<"";
    cout<<nongMonth[month];
    if(day>0&&day<=10)
    {
        cout<<""<<nongday[day];
    }
    else if(day>10&&day<20)
    {
        cout<<""<<nongday[day%10];
    }
    else if(day==20)
    {
        cout<<"二十";
    }
    else if(day>20 && day<30)
    {
        cout<<"廿"<<nongday[day%10];
    }
    else if(day==30)
    {
        cout<<"三十";
    }
    cout<<endl;
}

/*打印農歷*/
void gregorian_to_lunar (int year,int month,int day)
{
    if(!checkDate(year,month,day))
    {
        cout<<"日期輸入出錯,請確保日期正確性!"<<endl;
        return;
    }
    cout<<"公歷:"<<year<<""<<month<<""<<day<<""<<"   "<<"農歷:";
    int days=getDayTo1939(year,month,day);
    /*根據天數打印農歷*/
    printNong(days);
}

/*通式壽星公式 計算二十四節氣  公式來源:https://www.jianshu.com/p/1f814c6bb475*/
/*20,21世紀C值*/
float C_value_21[]= {3.87,18.73,5.63,20.646,4.81,20.1,5.52,21.04,5.678,21.37,7.108,22.83,7.5,23.13,7.646,23.042,8.318,23.438,7.438,22.36,7.18,21.94,5.4055,20.12};
float C_value_20[]= {4.6295,19.4599,6.3826,21.4155,5.59,20.888,6.318,21.86,6.5,22.2,7.928,23.65,28.35,23.95,8.44,23.822,9.098,24.218,8.218,23.08,7.9,22.6,6.11,20.84};
/*節氣基礎月*/
float C_month[]= {2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
void solar_term(int year1,char* str)
{
    int year,month,day;
    year=year1;
    int tmp=-1;//表示節氣順序
    const char* temp[24]= {"立春","雨水","驚蟄","春分","清明","谷雨","立夏","小滿","芒種","夏至","小暑","大暑","立秋","處暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至","小寒","大寒"};
    /*比較字符並賦值tmp 如:0就代表立春*/
    for(int i=0; i<24; i++)
    {
        if(strcmp(str,temp[i])==0)
        {
            tmp=i;
            break;
        }
    }
    if(tmp==-1)
    {
        cout<<"節氣拼寫出錯!"<<endl;
        return;
    }

    if(tmp==0||tmp==1||tmp==22||tmp==23)
    {
        if(year>=2000)
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_21[tmp])-floor((year%100-1)/4);
        }
        else
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_20[tmp])-floor((year%100-1)/4);
        }
    }
    else
    {
        if(year>=2000)
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_21[tmp])-floor((year%100)/4);
        }
        else
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_20[tmp])-floor((year%100)/4);
        }
    }

//特殊情況
    if((year==2026 && tmp==1)||(year==1918 && tmp==21)||(year==2021 && tmp==21)||(year==2019 && tmp==22))
    {
        day--;
    }
    if((year==2084 && tmp==3)||(year==1911 && tmp==6)||(year==2008 && tmp==7)||(year==1902 && tmp==8)||(year==1928 && tmp==9)||(year==1925 && tmp==10)||(year==2016 && tmp==10)||(year==1922&& tmp==11)||(year==2002&&tmp==12)||(year==1927&&tmp==14)||(year==1942&&tmp==15)||(year==2089 && tmp==17)||(year==2089&&tmp==18)||(year==1978&&tmp==19)||(year==2054 && tmp==20)||(year==1982&&tmp==22)||(year==2000 && tmp==23)||(year==2082&&tmp==23))
    {
        day++;
    }
    if(C_month[tmp]>12)
    {
        month=1;
    }
    cout<<temp[tmp]<<": ";
    /*根據公式計算的年月日,將其轉換為農歷*/
    gregorian_to_lunar (year,month,day);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM