123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- // LunarCalendar.cpp : 定义 DLL 的初始化例程。
- //
- #include "stdafx.h"
- #include "Def.h"
- #include "LunarCalendar.h"
- #include <bitset>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- //
- //TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
- // 则从此 DLL 导出的任何调入
- // MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
- // 该函数的最前面。
- //
- // 例如:
- //
- // extern "C" BOOL PASCAL EXPORT ExportedFunction()
- // {
- // AFX_MANAGE_STATE(AfxGetStaticModuleState());
- // // 此处为普通函数体
- // }
- //
- // 此宏先于任何 MFC 调用
- // 出现在每个函数中十分重要。这意味着
- // 它必须作为函数中的第一个语句
- // 出现,甚至先于所有对象变量声明,
- // 这是因为它们的构造函数可能生成 MFC
- // DLL 调用。
- //
- // 有关其他详细信息,
- // 请参阅 MFC 技术说明 33 和 58。
- //
- // CLunarCalendarApp
- BEGIN_MESSAGE_MAP(CLunarCalendarApp, CWinApp)
- END_MESSAGE_MAP()
- // CLunarCalendarApp 构造
- CLunarCalendarApp::CLunarCalendarApp()
- {
- // TODO: 在此处添加构造代码,
- // 将所有重要的初始化放置在 InitInstance 中
- }
- // 唯一的一个 CLunarCalendarApp 对象
- CLunarCalendarApp theApp;
- // CLunarCalendarApp 初始化
- BOOL CLunarCalendarApp::InitInstance()
- {
- CWinApp::InitInstance();
- return TRUE;
- }
- extern "C" BOOL __declspec(dllexport) IsValidLunanrDate2(LPCTSTR lpDate)
- {
- if (lpDate == NULL || _tcscmp(lpDate, _T("")) == 0)
- return FALSE;
- CString strDate = lpDate;
- if (strDate.IsEmpty()) return FALSE;
- static int lunar_year, lunar_month, lunar_day;
- lunar_year = lunar_month = lunar_day = 0;
- lunar_year = _ttoi(strDate.Left(4));
- lunar_month = _ttoi(strDate.Mid(5, 2));
- lunar_day = _ttoi(strDate.Mid(8, 2));
- //越界检查,如果越界,返回无效日期;
- if (lunar_year <= BEGIN_YEAR || lunar_year > BEGIN_YEAR + NUMBER_YEAR - 1)
- return FALSE;
- if (lunar_month < 1 || lunar_month > 12)
- return FALSE;
- // 1.农历年是否有闰月;
- int nYearIndex = lunar_year - BEGIN_YEAR;
- int leap_month = (LUNAR_YEARS[nYearIndex] >> 20) & 0xF;
- // 2.月份大小月天数;
- int month_day = 0;
- if ((LUNAR_YEARS[nYearIndex] >> (7 + 13 - lunar_month)) & 0x1)
- month_day = 30;
- else
- month_day = 29;
- if (lunar_day < 0 || lunar_day > month_day)
- return FALSE;
- return TRUE;
- }
- extern "C" BOOL __declspec(dllexport) IsValidLunanrDate(int lunar_year, int lunar_month, int lunar_day)
- {
- //越界检查,如果越界,返回无效日期;
- if (lunar_year <= BEGIN_YEAR || lunar_year > BEGIN_YEAR + NUMBER_YEAR - 1)
- return FALSE;
- if (lunar_month < 1 || lunar_month > 12)
- return FALSE;
- // 1.农历年是否有闰月;
- int nYearIndex = lunar_year - BEGIN_YEAR;
- int leap_month = (LUNAR_YEARS[nYearIndex] >> 20) & 0xF;
- // 2.月份大小月天数;
- int month_day = 0;
- if ((LUNAR_YEARS[nYearIndex] >> (7 + 13 - lunar_month)) & 0x1)
- month_day = 30;
- else
- month_day = 29;
- if (lunar_day < 0 || lunar_day > month_day)
- return FALSE;
- return TRUE;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:IsValidSolarDate
- // 描述:判断日期是否有效;
- // 参数:
- // strDate 格式如:2014-01-02 或 2014/01/02;
- // 返回:有效;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" BOOL __declspec(dllexport) IsValidSolarStrDate(LPCTSTR lpStrDate, BOOL bThisyear)
- {
- if (lpStrDate == NULL) return FALSE;
- CString strDate = lpStrDate;
- // 判断日期合法性;
- static int nYear = 0;
- static int nMonth = 0;
- static int nDay = 0;
- nYear = nMonth = nDay = 0;
- if (bThisyear)
- nYear = CTime::GetCurrentTime().GetYear();
- else
- nYear = _ttoi(strDate.Left(4));
- nMonth = _ttoi(strDate.Mid(5, 2));
- nDay = _ttoi(strDate.Mid(8, 2));
- if ((nDay <= 0) || (nDay > 31) || (nMonth <= 0) || (nMonth > 12)) return FALSE;
- if ((nYear % 400 == 0) || (nYear % 4 == 0 && nYear % 100 != 0))
- {
- if (nDay > nLeapMonth[nMonth - 1]) return FALSE;
- }
- else
- {
- if (nDay > nNormalMonth[nMonth - 1]) return FALSE;
- }
- return TRUE;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:IsValidSolarDate
- // 描述:判断日期是否有效;
- // 参数:
- // nSolarYear 公历年;
- // nSolarMonth 公历月;
- // nSolarDay 公历日;
- // 返回:有效;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" BOOL __declspec(dllexport) IsValidSolarDate(CONST int &nSolarYear, CONST int &nSolarMonth, CONST int &nSolarDay)
- {
- if (nSolarYear < 0 ) return FALSE;
- // 判断日期合法性;
- if ((nSolarDay <= 0) || (nSolarDay > 31) || (nSolarMonth <= 0) || (nSolarMonth > 12)) return FALSE;
- if ((nSolarYear % 400 == 0) || (nSolarYear % 4 == 0 && nSolarYear % 100 != 0))
- {
- if (nSolarDay > nLeapMonth[nSolarMonth - 1]) return FALSE;
- }
- else
- {
- if (nSolarDay > nNormalMonth[nSolarMonth - 1]) return FALSE;
- }
- return TRUE;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:DayOfSolarYear
- // 描述:计算这个公历日期是这一年中的第几天
- // 参数:
- // nSolarYear 公历年;
- // nSolarMonth 公历月;
- // nSolarDay 公历日;
- // 返回:如果日期正确,返回公历日期在这一年中的第几天; 否则返回-1;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" int __declspec(dllexport) DayOfSolarYear(IN const int &nSolarYear,IN const int &nSolarMonth, IN const int &nSolarDay)
- {
- if( !IsValidSolarDate(nSolarYear,nSolarMonth,nSolarDay) )
- return -1;
- const int *t_year_yday_ = NORMAL_YDAY;
- //判断是否是公历闰年;
- if (nSolarYear % 4 == 0)
- {
- if (nSolarYear % 100 != 0)
- t_year_yday_ = LEAP_YDAY;
- if (nSolarYear % 400 == 0)
- t_year_yday_ = LEAP_YDAY;
- }
- return t_year_yday_[nSolarMonth - 1] + nSolarDay;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 函数:SolarToLuanrDate
- // 描述:将公历日期转为对应的农历日期
- // 参数:
- // nSolarYear 公历年;
- // nSolarMonth 公历月;
- // nSolarDay 公历日;
- // 返回:返回结构体;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- INT SolarToLuanrDate(OUT LunarDate &tagLunarDate, IN const int &nSolarYear, IN const int &nSolarMonth, IN const int &nSolarDay)
- {
- if( !IsValidSolarDate(nSolarYear,nSolarMonth,nSolarDay) )
- return -1;
- tagLunarDate.nYear = nSolarYear;
- //越界检查,如果越界,返回无效日期;
- if (nSolarYear <= BEGIN_YEAR || nSolarYear > BEGIN_YEAR + NUMBER_YEAR - 1)
- return -1;
- int year_index = nSolarYear - BEGIN_YEAR;
- //计算春节的公历日期;
- int spring_ny_month = (LUNAR_YEARS[year_index] & 0x60) >> 5;
- int spring_ny_day = (LUNAR_YEARS[year_index] & 0x1F);
- //计算今天是公历年的第几天;
- int today_solar_yd = DayOfSolarYear(nSolarYear, nSolarMonth, nSolarDay);
- if(today_solar_yd == -1)
- return -1;
- //计算春节是公历年的第几天;
- int spring_ny_yd = DayOfSolarYear(nSolarYear, spring_ny_month, spring_ny_day);
- if(spring_ny_yd == -1)
- return -1;
- //计算今天是农历年的第几天 = 农历今天在的公历第几天 - 今年农历春节在公历的第几天;
- int today_luanr_yd = today_solar_yd - spring_ny_yd + 1;
- //如果今天在春节的前面,重新计算today_luanr_yd;
- if (today_luanr_yd <= 0)
- {
- //农历年比当前公历年小1;
- year_index--;
- tagLunarDate.nYear--;
- //越界,返回无效日期;
- if (year_index < 0)
- return -1;
- // 去年农历春节月;
- spring_ny_month = (LUNAR_YEARS[year_index] & 0x60) >> 5;
- // 去年农历春节日;
- spring_ny_day = (LUNAR_YEARS[year_index] & 0x1F);
- // 去年公历年共多少天;
- int year_total_day = DayOfSolarYear(tagLunarDate.nYear, 12, 31);
- if(year_total_day == -1)
- return -1;
- spring_ny_yd = DayOfSolarYear(nSolarYear, spring_ny_month, spring_ny_day);
- if(spring_ny_yd == -1)
- return -1;
- // 计算今天是农历年的第几天;
- today_luanr_yd = today_solar_yd + year_total_day - spring_ny_yd + 1;
- }
- int luanr_month = 1;
- //计算月份和日期;
- for (; luanr_month <= 13; luanr_month++)
- {
- int month_day = 29;
- if ((LUNAR_YEARS[year_index] >> (7 + 13 - luanr_month)) & 0x1)
- month_day = 30;
- if (today_luanr_yd <= month_day)
- break;
- else
- today_luanr_yd -= month_day;
- }
- tagLunarDate.nDay = today_luanr_yd;
- //处理闰月;
- int leap_month = (LUNAR_YEARS[year_index] >> 20) & 0xf;
- if (leap_month > 0 && leap_month < luanr_month)
- {
- luanr_month--;
- //如果当前月为闰月,设置闰月标志;
- if (luanr_month == leap_month)
- tagLunarDate.bIsLeapMonth = true;
- }
- if ( leap_month > 12 )
- return -1;
- tagLunarDate.nMonth = luanr_month;
- return 0L;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:GetLunarDate
- // 描述:将公历日期转为对应的农历日期
- // 参数:
- // nSolarYear 公历年;
- // nSolarMonth 公历月;
- // nSolarDay 公历日;
- // 返回:暂时未细致处理返回值的定义,错误的值都为负数;
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" INT __declspec(dllexport) GetLunarDate(OUT LPTSTR lpLunarDate,IN const int &nSolarYear, IN const int &nSolarMonth, IN const int &nSolarDay)
- {
- if( !IsValidSolarDate(nSolarYear,nSolarMonth,nSolarDay) )
- return -1;
- LunarDate luanr_date;
- luanr_date.nYear = nSolarYear;
- luanr_date.nMonth = 0;
- luanr_date.nDay = 0;
- luanr_date.bIsLeapMonth = false;
- //越界检查,如果越界,返回无效日期;
- if (nSolarYear <= BEGIN_YEAR || nSolarYear > BEGIN_YEAR + NUMBER_YEAR - 1)
- return -2;
- int year_index = nSolarYear - BEGIN_YEAR;
- //计算春节的公历日期;
- int spring_ny_month = (LUNAR_YEARS[year_index] & 0x60) >> 5;
- int spring_ny_day = (LUNAR_YEARS[year_index] & 0x1F);
- //计算今天是公历年的第几天;
- int today_solar_yd = DayOfSolarYear(nSolarYear, nSolarMonth, nSolarDay);
- if (today_solar_yd == -1)
- return -3;
- //计算春节是公历年的第几天;
- int spring_ny_yd = DayOfSolarYear(nSolarYear, spring_ny_month, spring_ny_day);
- if (spring_ny_yd == -1)
- return -4;
- //计算今天是农历年的第几天 = 农历今天在的公历第几天 - 今年农历春节在公历的第几天;
- int today_luanr_yd = today_solar_yd - spring_ny_yd + 1;
- //如果今天在春节的前面,重新计算today_luanr_yd;
- if (today_luanr_yd <= 0)
- {
- //农历年比当前公历年小1;
- year_index--;
- luanr_date.nYear--;
- //越界,返回无效日期;
- if (year_index < 0)
- return -2;
- // 去年农历春节月;
- spring_ny_month = (LUNAR_YEARS[year_index] & 0x60) >> 5;
- // 去年农历春节日;
- spring_ny_day = (LUNAR_YEARS[year_index] & 0x1F);
- // 去年公历年共多少天;
- int year_total_day = DayOfSolarYear(luanr_date.nYear, 12, 31);
- if (year_total_day == -1)
- return -1;
- spring_ny_yd = DayOfSolarYear(nSolarYear, spring_ny_month, spring_ny_day);
- if (spring_ny_yd == -1)
- return -1;
- // 计算今天是农历年的第几天;
- today_luanr_yd = today_solar_yd + year_total_day - spring_ny_yd + 1;
- }
- int luanr_month = 1;
- //计算月份和日期;
- for (; luanr_month <= 13; luanr_month++)
- {
- int month_day = 29;
- if ((LUNAR_YEARS[year_index] >> (7 + 13 - luanr_month)) & 0x1)
- month_day = 30;
- if (today_luanr_yd <= month_day)
- break;
- else
- today_luanr_yd -= month_day;
- }
- luanr_date.nDay = today_luanr_yd;
- //处理闰月;
- int leap_month = (LUNAR_YEARS[year_index] >> 20) & 0xf;
- if (leap_month > 0 && leap_month < luanr_month)
- {
- luanr_month--;
- //如果当前月为闰月,设置闰月标志;
- if (luanr_month == leap_month)
- luanr_date.bIsLeapMonth = true;
- }
- if ( leap_month > 12)
- return -1;
- luanr_date.nMonth = luanr_month;
- _stprintf_s(lpLunarDate, 11, _T("%04d-%02d-%02d"),luanr_date.nYear,luanr_date.nMonth,luanr_date.nDay);
- return 0L;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:LuanrToSolarDate
- // 描述:将农历日期转为对应的公历日期
- // 参数:
- // nLunarYear 农历年;
- // nLunarMonth 农历月;
- // nLunarDay 农历日;
- // bIsLeapMonth TRUE,若该年有闰月且正好是输入月份,返回闰月对应的公历;
- // 返回:返回公历日期在这一年中的第几天;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" BOOL __declspec(dllexport) LuanrToSolarDate(OUT LPTSTR lpSolarDate,IN const int &nLunarYear, IN const int &nLunarMonth, IN const int &nLunarDay, BOOL bIsLeapMonth/*=FALSE*/)
- {
- // 越界检查,如果越界,返回无效日期;
- if (nLunarYear <= BEGIN_YEAR || nLunarYear > BEGIN_YEAR + NUMBER_YEAR - 1)
- return FALSE;
- // 1.判断该农历年是否有闰月;
- INT nIndexYear = nLunarYear - BEGIN_YEAR;
- INT nLeapMonth = (LUNAR_YEARS[nIndexYear] >> 20) & 0xF;
- int nDays = 0;
- long nMonths = (LUNAR_YEARS[nIndexYear] & 0x0FFF80) >> 7;
- std::bitset<13> btMonth(nMonths);
- for ( int i = 0; i < nLunarMonth-1; i++ )
- {
- nDays += btMonth[i] ? 30 : 29;
- }
- if ( bIsLeapMonth && nLeapMonth != 0 )
- {
- nDays += btMonth[nLunarMonth-1] ? 30 : 29;
- }
- nDays += nLunarDay;
- // 公历年是否是闰年;
- BOOL isLeapYear = FALSE;
- if ((nLunarYear % 400 == 0) || (nLunarYear % 4 == 0 && nLunarYear % 100 != 0))
- {
- isLeapYear = TRUE;
- }
- else
- {
- isLeapYear = FALSE;
- }
- // 正月的公历月份;
- int SolarNewYearMonth = (LUNAR_YEARS[nIndexYear] & 0x000060) >> 5;
- // 正月初一的公历日期;
- int SolarNewYearDay = LUNAR_YEARS[nIndexYear] & 0x00001F;
- int nSolarDay = 0;
- int nSolarDays = 0;
- int nSolarMonth = -1;
- if ( isLeapYear )
- {
- nSolarDays = LEAP_YDAY[SolarNewYearMonth-1] + SolarNewYearDay + nDays;
- for ( int i = SolarNewYearMonth; i < 12; i++)
- {
- if ( nSolarDays >= LEAP_YDAY[i] && nSolarDays < LEAP_YDAY[i+1])
- {
- nSolarMonth = i+1;
- nSolarDay = nSolarDays - LEAP_YDAY[i] -1;
- }
- }
- if ( nSolarMonth == -1 )
- nSolarDays -= LEAP_YDAY[12];
- }
- else
- {
- nSolarDays = NORMAL_YDAY[SolarNewYearMonth-1]+ SolarNewYearDay + nDays;
- for ( int i = SolarNewYearMonth; i < 12; i++)
- {
- if ( nSolarDays >= NORMAL_YDAY[i] && nSolarDays < NORMAL_YDAY[i+1])
- {
- nSolarMonth = i+1;
- nSolarDay = nSolarDays - NORMAL_YDAY[i] -1;
- }
- }
- if ( nSolarMonth == -1 )
- nSolarDays -= NORMAL_YDAY[12];
- }
- _stprintf_s(lpSolarDate, 11, _T("%4d-%02d-%02d"), nLunarYear, nSolarMonth, nSolarDay);
- if ( nSolarMonth == -1 )
- {// 超出本年;
- int nYear = nLunarYear+1 ;
- if ((nYear % 400 == 0) || (nYear % 4 == 0 && nYear % 100 != 0))
- {
- isLeapYear = TRUE;
- }
- else
- {
- isLeapYear = FALSE;
- }
- if ( isLeapYear )
- {
- for ( int i = 0; i < 12; i++)
- {
- if ( nSolarDays >= LEAP_YDAY[i] && nSolarDays < LEAP_YDAY[i+1])
- {
- nSolarMonth = i+1;
- nSolarDay = nSolarDays - LEAP_YDAY[i] -1;
- }
- }
- }
- else
- {
- for ( int i = 0; i < 12; i++)
- {
- if ( nSolarDays >= NORMAL_YDAY[i] && nSolarDays < NORMAL_YDAY[i+1])
- {
- nSolarMonth = i+1;
- nSolarDay = nSolarDays - NORMAL_YDAY[i] -1;
- }
- }
- }
- _stprintf_s(lpSolarDate, 11, _T("%4d-%02d-%02d"), nYear, nSolarMonth, nSolarDay);
- }
- return true;
- }
- // ------------------------------------------------------------------------------------------------------------------------
- // 对外接口函数
- //
- // 函数:
- // 描述:判断输入的农历日期的月份是否有闰月;
- // 参数:
- // nLunarYear 农历年;
- // 返回:若有闰月返回闰月值,否则返回0;
- //
- // ------------------------------------------------------------------------------------------------------------------------
- extern "C" INT __declspec(dllexport) IsLeapMonth(IN const int &nLunarYear)
- {
- // 越界检查,如果越界,返回无效日期;
- if (nLunarYear <= BEGIN_YEAR || nLunarYear > BEGIN_YEAR + NUMBER_YEAR - 1)
- return -1;
- // 1.判断该农历年是否有闰月;
- return (LUNAR_YEARS[nLunarYear - BEGIN_YEAR] >> 20) & 0xF;
- }
|