之前要做一個萬年歷,從論壇上輾轉多處,最終發現以下這個陽歷轉換陰歷的程序比較簡單,數據帶入可以直接使用,不過測試發現轉換有問題,后面進行仿真調試找到問題所在,從而進而修改。不知道是我復制出錯,還是自己不經意間修改才導致問題出現,已經修復,需要陽歷轉陰歷的可以拿去。找不到具體來源,因此無法標志引用鏈接地址,如有侵權,聯系刪除。
問題所在:在SPDATE GetSpringDay(uchar GreYear,uchar GreMon,uchar GreDay)函數里面的參數定義,把Offset1定義為uchar類型,后面計算時Offset1數值溢出,將uchar改為uint后,數據不在溢出,進行上機測試,轉換成功。
- //公曆轉農曆(1901-2100)
- //亦木明 2008.1.11
- //2018.12.30清楓城主測試,發現存在問題,通過仿真一步步走找出問題所在,并作出修正
- //原文在哪忘了,只知道作者有“亦木明”的標注,如有侵權聯系刪除
- #include "12c5a60s2.h"//可修改為51的頭文件
- #define TRUE 1
- //公歷年對應的農歷數據,每年三字節,
- //格式第一字節BIT7-4 位表示閏月月份,值為0 為無閏月,BIT3-0 對應農歷第1-4 月的大小
- //第二字節BIT7-0 對應農歷第5-12 月大小,第三字節BIT7 表示農歷第13 個月大小
- //月份對應的位為1 表示本農歷月大(30 天),為0 表示小(29 天).
- //第三字節BIT6-5 表示春節的公歷月份,BIT4-0 表示春節的公歷日期
- //每年的數據對應在數組中的位置庫 (200-(2100-year)-1)*3+Offset1
- //0x09,0x2d,0x47, //2008 0x47 01000111
- //0x4d,0x4A,0xB8, //2001
- typedef struct spdate
- {
- char cYear;
- char cMon;
- char cDay;
- }SPDATE;
- uchar code Data[]={
- 0x04,0xAe,0x53, //1901 0 (200-(2100-1901)-1)*3=0
- 0x0A,0x57,0x48, //1902 3 (200-(2100-1902)-1)*3=3
- 0x55,0x26,0xBd, //1903 6 (200-(2100-1903)-1)*3=3
- 0x0d,0x26,0x50, //1904 9 (200-(2100-year)-1)*3
- 0x0d,0x95,0x44, //1905 12
- 0x46,0xAA,0xB9, //1906 15
- 0x05,0x6A,0x4d, //1907
- 0x09,0xAd,0x42, //1908
- 0x24,0xAe,0xB6, //1909
- 0x04,0xAe,0x4A, //1910
- 0x6A,0x4d,0xBe, //1911
- 0x0A,0x4d,0x52, //1912
- 0x0d,0x25,0x46, //1913
- 0x5d,0x52,0xBA, //1914
- 0x0B,0x54,0x4e, //1915
- 0x0d,0x6A,0x43, //1916
- 0x29,0x6d,0x37, //1917
- 0x09,0x5B,0x4B, //1918
- 0x74,0x9B,0xC1, //1919
- 0x04,0x97,0x54, //1920
- 0x0A,0x4B,0x48, //1921
- 0x5B,0x25,0xBC, //1922
- 0x06,0xA5,0x50, //1923
- 0x06,0xd4,0x45, //1924
- 0x4A,0xdA,0xB8, //1925
- 0x02,0xB6,0x4d, //1926
- 0x09,0x57,0x42, //1927
- 0x24,0x97,0xB7, //1928
- 0x04,0x97,0x4A, //1929
- 0x66,0x4B,0x3e, //1930
- 0x0d,0x4A,0x51, //1931
- 0x0e,0xA5,0x46, //1932
- 0x56,0xd4,0xBA, //1933
- 0x05,0xAd,0x4e, //1934
- 0x02,0xB6,0x44, //1935
- 0x39,0x37,0x38, //1936
- 0x09,0x2e,0x4B, //1937
- 0x7C,0x96,0xBf, //1938
- 0x0C,0x95,0x53, //1939
- 0x0d,0x4A,0x48, //1940
- 0x6d,0xA5,0x3B, //1941
- 0x0B,0x55,0x4f, //1942
- 0x05,0x6A,0x45, //1943
- 0x4A,0xAd,0xB9, //1944
- 0x02,0x5d,0x4d, //1945
- 0x09,0x2d,0x42, //1946
- 0x2C,0x95,0xB6, //1947
- 0x0A,0x95,0x4A, //1948
- 0x7B,0x4A,0xBd, //1949
- 0x06,0xCA,0x51, //1950
- 0x0B,0x55,0x46, //1951
- 0x55,0x5A,0xBB, //1952
- 0x04,0xdA,0x4e, //1953
- 0x0A,0x5B,0x43, //1954
- 0x35,0x2B,0xB8, //1955
- 0x05,0x2B,0x4C, //1956
- 0x8A,0x95,0x3f, //1957
- 0x0e,0x95,0x52, //1958
- 0x06,0xAA,0x48, //1959
- 0x7A,0xd5,0x3C, //1960
- 0x0A,0xB5,0x4f, //1961
- 0x04,0xB6,0x45, //1962
- 0x4A,0x57,0x39, //1963
- 0x0A,0x57,0x4d, //1964
- 0x05,0x26,0x42, //1965
- 0x3e,0x93,0x35, //1966
- 0x0d,0x95,0x49, //1967
- 0x75,0xAA,0xBe, //1968
- 0x05,0x6A,0x51, //1969
- 0x09,0x6d,0x46, //1970
- 0x54,0xAe,0xBB, //1971
- 0x04,0xAd,0x4f, //1972
- 0x0A,0x4d,0x43, //1973
- 0x4d,0x26,0xB7, //1974
- 0x0d,0x25,0x4B, //1975
- 0x8d,0x52,0xBf, //1976
- 0x0B,0x54,0x52, //1977
- 0x0B,0x6A,0x47, //1978
- 0x69,0x6d,0x3C, //1979
- 0x09,0x5B,0x50, //1980
- 0x04,0x9B,0x45, //1981
- 0x4A,0x4B,0xB9, //1982
- 0x0A,0x4B,0x4d, //1983
- 0xAB,0x25,0xC2, //1984
- 0x06,0xA5,0x54, //1985
- 0x06,0xd4,0x49, //1986
- 0x6A,0xdA,0x3d, //1987
- 0x0A,0xB6,0x51, //1988
- 0x09,0x37,0x46, //1989
- 0x54,0x97,0xBB, //1990
- 0x04,0x97,0x4f, //1991
- 0x06,0x4B,0x44, //1992
- 0x36,0xA5,0x37, //1993
- 0x0e,0xA5,0x4A, //1994
- 0x86,0xB2,0xBf, //1995
- 0x05,0xAC,0x53, //1996
- 0x0A,0xB6,0x47, //1997
- 0x59,0x36,0xBC, //1998
- 0x09,0x2e,0x50, //1999
- 0x0C,0x96,0x45, //2000
- 0x4d,0x4A,0xB8, //2001
- 0x0d,0x4A,0x4C, //2002
- 0x0d,0xA5,0x41, //2003
- 0x25,0xAA,0xB6, //2004
- 0x05,0x6A,0x49, //2005
- 0x7A,0xAd,0xBd, //2006
- 0x02,0x5d,0x52, //2007
- 0x09,0x2d,0x47, //2008
- 0x5C,0x95,0xBA, //2009
- 0x0A,0x95,0x4e, //2010
- 0x0B,0x4A,0x43, //2011
- 0x4B,0x55,0x37, //2012
- 0x0A,0xd5,0x4A, //2013
- 0x95,0x5A,0xBf, //2014
- 0x04,0xBA,0x53, //2015
- 0x0A,0x5B,0x48, //2016
- 0x65,0x2B,0xBC, //2017
- 0x05,0x2B,0x50, //2018
- 0x0A,0x93,0x45, //2019
- 0x47,0x4A,0xB9, //2020
- 0x06,0xAA,0x4C, //2021
- 0x0A,0xd5,0x41, //2022
- 0x24,0xdA,0xB6, //2023
- 0x04,0xB6,0x4A, //2024
- 0x69,0x57,0x3d, //2025
- 0x0A,0x4e,0x51, //2026
- 0x0d,0x26,0x46, //2027
- 0x5e,0x93,0x3A, //2028
- 0x0d,0x53,0x4d, //2029
- 0x05,0xAA,0x43, //2030
- 0x36,0xB5,0x37, //2031
- 0x09,0x6d,0x4B, //2032
- 0xB4,0xAe,0xBf, //2033
- 0x04,0xAd,0x53, //2034
- 0x0A,0x4d,0x48, //2035
- 0x6d,0x25,0xBC, //2036
- 0x0d,0x25,0x4f, //2037
- 0x0d,0x52,0x44, //2038
- 0x5d,0xAA,0x38, //2039
- 0x0B,0x5A,0x4C, //2040
- 0x05,0x6d,0x41, //2041
- 0x24,0xAd,0xB6, //2042
- 0x04,0x9B,0x4A, //2043
- 0x7A,0x4B,0xBe, //2044
- 0x0A,0x4B,0x51, //2045
- 0x0A,0xA5,0x46, //2046
- 0x5B,0x52,0xBA, //2047
- 0x06,0xd2,0x4e, //2048
- 0x0A,0xdA,0x42, //2049
- 0x35,0x5B,0x37, //2050
- 0x09,0x37,0x4B, //2051
- 0x84,0x97,0xC1, //2052
- 0x04,0x97,0x53, //2053
- 0x06,0x4B,0x48, //2054
- 0x66,0xA5,0x3C, //2055
- 0x0e,0xA5,0x4f, //2056
- 0x06,0xB2,0x44, //2057
- 0x4A,0xB6,0x38, //2058
- 0x0A,0xAe,0x4C, //2059
- 0x09,0x2e,0x42, //2060
- 0x3C,0x97,0x35, //2061
- 0x0C,0x96,0x49, //2062
- 0x7d,0x4A,0xBd, //2063
- 0x0d,0x4A,0x51, //2064
- 0x0d,0xA5,0x45, //2065
- 0x55,0xAA,0xBA, //2066
- 0x05,0x6A,0x4e, //2067
- 0x0A,0x6d,0x43, //2068
- 0x45,0x2e,0xB7, //2069
- 0x05,0x2d,0x4B, //2070
- 0x8A,0x95,0xBf, //2071
- 0x0A,0x95,0x53, //2072
- 0x0B,0x4A,0x47, //2073
- 0x6B,0x55,0x3B, //2074
- 0x0A,0xd5,0x4f, //2075
- 0x05,0x5A,0x45, //2076
- 0x4A,0x5d,0x38, //2077
- 0x0A,0x5B,0x4C, //2078
- 0x05,0x2B,0x42, //2079
- 0x3A,0x93,0xB6, //2080
- 0x06,0x93,0x49, //2081
- 0x77,0x29,0xBd, //2082
- 0x06,0xAA,0x51, //2083
- 0x0A,0xd5,0x46, //2084
- 0x54,0xdA,0xBA, //2085
- 0x04,0xB6,0x4e, //2086
- 0x0A,0x57,0x43, //2087
- 0x45,0x27,0x38, //2088
- 0x0d,0x26,0x4A, //2089
- 0x8e,0x93,0x3e, //2090
- 0x0d,0x52,0x52, //2091
- 0x0d,0xAA,0x47, //2092
- 0x66,0xB5,0x3B, //2093
- 0x05,0x6d,0x4f, //2094
- 0x04,0xAe,0x45, //2095
- 0x4A,0x4e,0xB9, //2096
- 0x0A,0x4d,0x4C, //2097
- 0x0d,0x15,0x41, //2098
- 0x2d,0x92,0xB5, //2099
- 0x0d,0x53,0x49, //2100
- };
- uchar code Mon1[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,
- 0,31,29,31,30,31,30,31,31,30,31,30,31};
- SPDATE Spdate;
- //獲得當年春節的公曆日期
- SPDATE GetSpringDay(uchar GreYear,uchar GreMon,uchar GreDay)
- {
- //0x09,0x2d,0x47, //2008 0x47 01000111
- int day;
- uchar i,Flag,F;
- uint Offset1;//出現問題在這里,原本定義為uchar類型,下面計算時超出范圍導致錯誤,進行修改為uint類型后,驗證正常
- unsigned char L=0x01,Flag1=1;
- unsigned int Temp16,L1=0x0800;
- //第三字節BIT6-5 表示春節的公歷月份,BIT4-0 表示春節的公歷日期
- Spdate.cYear=GreYear ;
- Spdate.cMon=(Data[(200-(100-GreYear)-1)*3+2]&0x60)>>5; //計算春節公歷月份
- Spdate.cDay=(Data[(200-(100-GreYear)-1)*3+2])&0x1f; //計算春節公歷日期
- //判斷平年,閏年
- if( (!(GreYear%4) && (GreYear%100)) || !(GreYear%400) ) Flag=1;
- else Flag=0;
-
- if(Spdate.cMon>GreMon) //春節離公歷日期的天數
- {
- day=Mon1[Flag][GreMon]-GreDay;
- for(i=GreMon+1;i<=Spdate.cMon-1;i++)
- day+=Mon1[Flag][i];
- day+=Spdate.cDay;
- F=1;
- }
- else if(Spdate.cMon<GreMon) //春節的月份小於目標的月份
- {
- day=Mon1[Flag][Spdate.cMon]-Spdate.cDay;
- for(i=Spdate.cMon+1;i<=GreMon-1;i++)
- day+=Mon1[Flag][i];
- day+=GreDay; // 000000000000000000000000000000000000000000000000000000000000000000
- F=0;
- }
- else
- {
- if(Spdate.cDay>GreDay)
- {
- day=Spdate.cDay-GreDay;
- F=1;
- }
- else if(Spdate.cDay<GreDay)
- {
- day=GreDay-Spdate.cDay;
- F=0;
- }
- else day=0;
- }
- Spdate.cYear=Spdate.cYear;
- Spdate.cMon=1;
- Spdate.cDay=1;
- if(!day) return Spdate ;
- if(F) //春節在公歷日期后
- {
- Spdate.cYear--;
- Spdate.cMon=12;
- //這邊Offset1計算會出現超范圍,因此把uchar類型改為uint后正常
- Offset1=(200-(100-Spdate.cYear)-1)*3;
- while(TRUE)
- {
- //格式第一字節BIT7-4 位表示閏月月份,值為0 為無閏月,BIT3-0 對應農歷第1-4 月的大小
- //第二字節BIT7-0 對應農歷第5-12 月大小,第三字節BIT7 表示農歷第13 個月大小
- //0x4d,0x4A,0xB8, //2001
- if(Data[Offset1+1]&L)
- day-=30;
- else
- day-=29;
- L<<=1;
- if(((Data[Offset1+0]&0xf0)>>4)==Spdate.cMon && Flag1)//(Data[Offset1+0]&0xf0)>>4判斷是否是閏月1平月0
- {
- Flag1=0;
- if(Data[Offset1+2]&0x80) day-=30; else day-=29;
- continue;
- }
- if(day>0) Spdate.cMon--;
- else break;
-
-
- }
- Spdate.cDay=-day+1;
- }
-
- if(!F)
- {
- Spdate.cMon=1;
- //這邊Offset1計算會出現超范圍,因此把uchar類型改為uint后正常
- Offset1=(200-(100-Spdate.cYear)-1)*3;
- Temp16=(Data[Offset1+0]<<8)+Data[Offset1+1];
- while(TRUE)
- {
- if(Temp16 & L1) day-=30; else day-=29;
- if(day>=0)
- Spdate.cMon++;
- else if(day<0)
- {
- if(Temp16 & L1) day+=30; else day+=29;
- break;
- }
- L1>>=1;
- //格式第一字節BIT7-4 位表示閏月月份,值為0 為無閏月,BIT3-0 對應農歷第1-4 月的大小
- //第二字節BIT7-0 對應農歷第5-12 月大小,第三字節BIT7 表示農歷第13 個月大小
- if(((Data[Offset1+0]&0xf0)>>4)==(Spdate.cMon-1) && Flag1) //閏月
- {
- Flag1=0;
- Spdate.cMon--;
- if(Temp16 & L1) day-=30; else day-=29;
- if(day>=0)
- Spdate.cMon++;
- else if(day<0)
- {
- if(Temp16 & L1) day+=30; else day+=29;
- break;
- }
- L1>>=1;
- }
- }
- Spdate.cDay=day+1;
- }
- return Spdate;
- }
- bit YearFlag(uchar cYear) //判斷平年,閏年
- {
- if( (!(cYear%4) && (cYear%100)) || !(cYear%400) ) return 1; else return 0;
- }
- //目標日期是星期幾
- uchar GetWeekDay(uchar cYear,uchar cMon,uchar cDay)
- {
- char i;
- int Sum=0,tmpyear=2000+cYear;
- for(i=1;i<=cMon-1;i++)
- Sum+=Mon1[YearFlag(cYear)][i];
- Sum+=cDay-1;
-
- return (((tmpyear-1)+(tmpyear-1)/4-(tmpyear-1)/100+(tmpyear-1)/400+Sum)%7)+1;
- }
- void main()
- {
- for(;;)
- {
- GetSpringDay(18,12,30); //輸入數據為十進制,不是BCD碼格式,這個請注意
- }
- }
- /*****************************************************************************
- 首先要能記住十大天干和十二地支,
- 十天干: 甲、乙、丙、丁、戊、己、庚、辛、壬、癸;
- 十二地支:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥;
-
- 天干地支紀年法首先是天干在前,地支在后,比如今年2005就為-乙酉年,先來算算天干,
- 有個公式:
- 4、 5、 6、 7、 8、 9、 0、 1、 2、 3 對應的十天干就是
- 甲、乙、丙、丁、戊、己、庚、辛、壬、癸,
- 數字為年代的最后的一位數字,比如今年是2005,最后一位是5,對應的天干就是乙;
- 地支的算法:用年代數除以12,后面的余數就代表某個地支,
- 余數分別為:4、 5、 6、 7、 8、 9、 10、 11、 0(能整除)、1、 2、3.
- 代表地支為:子、丑、寅、卯、辰、巳、午、 未、 申、酉、戌、亥.
- 比如2005年為例:年代末尾數為5,對應的天干為乙,2005除以12,余數為1,對應的地支為酉,所以2005年為乙酉年。
- ******************************************************************************/
復制代碼
全部資料51hei下載地址:
4545456.rar
(10.77 KB, 下載次數: 108)
2018-12-30 22:26 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|