|
- #include "calendar.h"
- #include
- #define GET_DAYOFWEEK_FAILED 0xff
- #define LUNAR_CALENDAR_TABLE_SIZE (MAX_YEAR - MIN_YEAR + 1)
- #define MONTH_TABLE_SIZE 12
- #define GET_SPRING_FESTIVAL_DAY(n) (BYTE)((DWORD)(n) & 0x0000001f)
- #define GET_SPRING_FESTIVAL_MONTH(n) (BYTE)(((DWORD)(n) & 0x00000060) >> 5)
- #define GET_LUNAR_MONTH_BITS(n) (WORD)(((DWORD)(n) & 0x000fff80) >> 7)
- #define GET_LUNAR_LEAP_MONTH(n) (BYTE)(((DWORD)(n) & 0x00f00000) >> 20)
- #define LUNAR_FIRST_MONTH_OFFSET 12
- #define MAX_LUNAR_MONTH 13 //阴历最多月份数
- #define LUNAR_LITTLE_MONTH_DAYS 29 //阴历小月的天数
- #define LEAP_MONTH_DAYS 29 //阳历闰月的天数
- #define IS_LEAP_YEAR(year) ((((WORD)(year) % 4 == 0) && ((WORD)(year) % 100 != 0)) || ((WORD)(year) % 400 == 0))
- //每月1号距离元旦的天数,不考虑闰年
- code const WORD g_wDaysToNewYearDayTable[MONTH_TABLE_SIZE] =
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- //每月的天数,不考虑闰年
- code const BYTE g_MonthDaysTable[MONTH_TABLE_SIZE] =
- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- /***********************************************************************************************
- 100年农历公历对应数表
- 格式: b23-b20 表示闰月月份,无闰月用0表示
- b19-b7 表示农历第1 - 13月的大小,其中1表示大月(对应30天),0表示小月(对应29天)
- b6-b5表示当年春节对应公历月份,其中1表示1月,2表示2月
- b4-b0表示当年春节对应公历当月的日期
- **********************************************************************************************/
- code const DWORD g_dwLunarCalendarTable[LUNAR_CALENDAR_TABLE_SIZE] =
- {
-
- 0x0C9645, 0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, //2000-2009
- 0x0A954E, 0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, //2010-2019
- 0x474AB9, 0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x69573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, //2020-2029
- 0x05AA43, 0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, //2030-2039
- 0x0B5A4C, 0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, //2040-2049
- /*
- 0x355B37, 0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06B244, 0x4AB638, 0x0AAE4C, //2050-2059
- 0x092E42, 0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, //2060-2069
- 0x052D4B, 0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, //2070-2079
- 0x3A93B6, 0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, //2080-2089
- 0x8E933E, 0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5, //2090-2099
- */
- };
- static BOOL IsDateValid(const DATE* pDate)
- {
- if(pDate == NULL)
- return FALSE;
- if(pDate->wYear < MIN_YEAR || pDate->wYear > MAX_YEAR)
- return FALSE;
- if(pDate->Month == 0 || pDate->Month > 12)
- return FALSE;
-
- if(pDate->Day == 0 || pDate->Day > g_MonthDaysTable[pDate->Month - 1])
- {
- if(IS_LEAP_YEAR(pDate->wYear) && pDate->Month == 2 && pDate->Day == LEAP_MONTH_DAYS)
- {
- return TRUE;
- }
- return FALSE;
- }
-
- return TRUE;
- }
- //计算所求日期是本年中的第几天
- static WORD GetDayOfYear(const DATE* pDate)
- {
-
- WORD wDayOfYear = g_wDaysToNewYearDayTable[pDate->Month - 1] + pDate->Day;
- if(pDate->Month > 2 && IS_LEAP_YEAR(pDate->wYear))
- {
- return wDayOfYear + 1; //闰年多加一天
- }
-
- return wDayOfYear;
- }
- /*
- W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D
- Y是年份数,D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天
- */
- BYTE GetDayOfWeek(const DATE* pDate)
- {
- WORD wTempYear = 0;
- BYTE nDayOfWeek = 0;
- if(pDate == NULL)
- return GET_DAYOFWEEK_FAILED;
- if(!IsDateValid(pDate))
- return GET_DAYOFWEEK_FAILED;
- wTempYear = pDate->wYear - 1;
-
-
- return ((pDate->wYear - 1) + (pDate->wYear - 1) / 4
- - (pDate->wYear - 1) / 100 + (pDate->wYear - 1) / 400 + GetDayOfYear(pDate)) % 7;
- // nDayOfWeek = (wTempYear + wTempYear / 4 - wTempYear / 100 + wTempYear / 400 + GetDayOfYear(pDate)) % 7;
- // return nDayOfWeek ? nDayOfWeek : 7;
- }
- BOOL GetLunarDate(const DATE* pDate, DATE* pLunarDate)
- {
- idata DWORD dwLunarCalendar = 0;
- idata WORD wSpringFestivalOfYear = 0;
- idata WORD wDayOfYear = 0;
- BYTE LunarLeapMonth = 0;
- WORD wLunarMonthBits = 0;
- BYTE i = 0 ;
- BYTE j = 0;
- WORD wTempDays = 0;
- WORD wDaysToSpringFestival = 0; //距春节的天数,或在春节前或在春节后
- idata DATE tempDate;
- if(pDate == NULL || pLunarDate == NULL)
- return FALSE;
- dwLunarCalendar = g_dwLunarCalendarTable[pDate->wYear - MIN_YEAR];
- tempDate.wYear = pDate->wYear;
- tempDate.Month = GET_SPRING_FESTIVAL_MONTH(dwLunarCalendar);
- tempDate.Day = GET_SPRING_FESTIVAL_DAY(dwLunarCalendar);
- wSpringFestivalOfYear = GetDayOfYear(&tempDate);
- wDayOfYear = GetDayOfYear(pDate);
- LunarLeapMonth = GET_LUNAR_LEAP_MONTH(dwLunarCalendar);
- wLunarMonthBits = GET_LUNAR_MONTH_BITS(dwLunarCalendar);
- if(!IsDateValid(pDate))
- return FALSE;
- if(wDayOfYear >= wSpringFestivalOfYear) //所求的日期在春节后面或当天
- {
- wDaysToSpringFestival = wDayOfYear - wSpringFestivalOfYear;
- for (i = 0; i < MAX_LUNAR_MONTH; i++)
- {
- j = (BYTE)TEST_BIT(wLunarMonthBits, LUNAR_FIRST_MONTH_OFFSET - i);
- wTempDays += (LUNAR_LITTLE_MONTH_DAYS + j);
-
- //若已经超出相距天数则说明所求日期就在农历当月
- if (wTempDays > wDaysToSpringFestival)
- {
- pLunarDate->Day = (LUNAR_LITTLE_MONTH_DAYS + j) - (wTempDays - wDaysToSpringFestival) + 1;
-
-
- //若是在闰月或是在闰月之后则调整月份
- if (LunarLeapMonth != 0 && i >= LunarLeapMonth)
- {
- pLunarDate->Month = i;
- }
- else
- {
- pLunarDate->Month = i + 1;
- }
-
-
- pLunarDate->wYear = pDate->wYear;
-
-
- break;
- }
- }
- }
- /**********************************************************
- 在MIN_YEAR ~ MAX_YEAR内,没有闰腊月
- ***********************************************************/
- if(wDayOfYear < wSpringFestivalOfYear) //所求的日期在春节前面
- {
- pLunarDate->wYear = pDate->wYear - 1;
- wDaysToSpringFestival = wSpringFestivalOfYear - wDayOfYear;
- if (LunarLeapMonth == 0) //若无闰月,将农历月份信息向右移动一位,使第一位是腊月
- {
- wLunarMonthBits >>= 1;
- }
-
-
- i = (BYTE)(wLunarMonthBits & 0x0001); //腊月是否是大月
- j = (BYTE)((wLunarMonthBits & 0x0002) >> 1); //11月是否是大月
-
-
- if (wDaysToSpringFestival <= (LUNAR_LITTLE_MONTH_DAYS + i))
- {
- pLunarDate->Month = 12;
- pLunarDate->Day = (LUNAR_LITTLE_MONTH_DAYS + i) - wDaysToSpringFestival + 1;
- }
- else
- {
- pLunarDate->Month = 11;
- pLunarDate->Day = (LUNAR_LITTLE_MONTH_DAYS + j) - (wDaysToSpringFestival - (LUNAR_LITTLE_MONTH_DAYS + i)) + 1;
-
- }
-
- }
- return TRUE;
- }
复制代码 |
|