C#实现万年历(农历、节气、节日、星座、属相、生肖、闰年等)

C# 万年历 农历 节气 节日 星座 星宿 属相 生肖 闰年月 时辰等,代码如下:
  
  
using System.Collections.Generic; using System.Text; using System; namespace yangliToyinli { #region ChineseCalendarException /// <summary> /// 中国日历异常处理 /// </summary> public class ChineseCalendarException : System.Exception { public ChineseCalendarException( string msg) : base (msg) { } } #endregion /// <summary> /// 中国农历类 版本V1.0 支持 1900.1.31日起至 2049.12.31日止的数据 /// </summary> /// <remarks> /// 本程序使用数据来源于网上的万年历查询,并综合了一些其它数据 /// </remarks> public class ChineseCalendar { #region 内部结构 private struct SolarHolidayStruct { public int Month; public int Day; public int Recess; // 假期长度 public string HolidayName; public SolarHolidayStruct( int month, int day, int recess, string name) { Month = month; Day = day; Recess = recess; HolidayName = name; } } private struct LunarHolidayStruct { public int Month; public int Day; public int Recess; public string HolidayName; public LunarHolidayStruct( int month, int day, int recess, string name) { Month = month; Day = day; Recess = recess; HolidayName = name; } } private struct WeekHolidayStruct { public int Month; public int WeekAtMonth; public int WeekDay; public string HolidayName; public WeekHolidayStruct( int month, int weekAtMonth, int weekDay, string name) { Month = month; WeekAtMonth = weekAtMonth; WeekDay = weekDay; HolidayName = name; } } #endregion #region 内部变量 private DateTime _date; private DateTime _datetime; private int _cYear; private int _cMonth; private int _cDay; private bool _cIsLeapMonth; // 当月是否闰月 private bool _cIsLeapYear; // 当年是否有闰月 #endregion #region 基础数据 #region 基本常量 private const int MinYear = 1900 ; private const int MaxYear = 2050 ; private static DateTime MinDay = new DateTime( 1900 , 1 , 30 ); private static DateTime MaxDay = new DateTime( 2049 , 12 , 31 ); private const int GanZhiStartYear = 1864 ; // 干支计算起始年 private static DateTime GanZhiStartDay = new DateTime( 1899 , 12 , 22 ); // 起始日 private const string HZNum = " 零一二三四五六七八九 " ; private const int AnimalStartYear = 1900 ; // 1900年为鼠年 private static DateTime ChineseConstellationReferDay = new DateTime( 2007 , 9 , 13 ); // 28星宿参考值,本日为角 #endregion #region 阴历数据 /// <summary> /// 来源于网上的农历数据 /// </summary> /// <remarks> /// 数据结构如下,共使用17位数据 /// 第17位:表示闰月天数,0表示29天 1表示30天 /// 第16位-第5位(共12位)表示12个月,其中第16位表示第一月,如果该月为30天则为1,29天为0 /// 第4位-第1位(共4位)表示闰月是哪个月,如果当年没有闰月,则置0 /// </remarks> private static int [] LunarDateArray = new int []{ x04BD8, 0x04AE0 , 0x0A570 , 0x054D5 , 0x0D260 , 0x0D950 , 0x16554 , 0x056A0 , 0x09AD0 , 0x055D2 , x04AE0, 0x0A5B6 , 0x0A4D0 , 0x0D250 , 0x1D255 , 0x0B540 , 0x0D6A0 , 0x0ADA2 , 0x095B0 , 0x14977 , x04970, 0x0A4B0 , 0x0B4B5 , 0x06A50 , 0x06D40 , 0x1AB54 , 0x02B60 , 0x09570 , 0x052F2 , 0x04970 , x06566, 0x0D4A0 , 0x0EA50 , 0x06E95 , 0x05AD0 , 0x02B60 , 0x186E3 , 0x092E0 , 0x1C8D7 , 0x0C950 , x0D4A0, 0x1D8A6 , 0x0B550 , 0x056A0 , 0x1A5B4 , 0x025D0 , 0x092D0 , 0x0D2B2 , 0x0A950 , 0x0B557 , x06CA0, 0x0B550 , 0x15355 , 0x04DA0 , 0x0A5B0 , 0x14573 , 0x052B0 , 0x0A9A8 , 0x0E950 , 0x06AA0 , x0AEA6, 0x0AB50 , 0x04B60 , 0x0AAE4 , 0x0A570 , 0x05260 , 0x0F263 , 0x0D950 , 0x05B57 , 0x056A0 , x096D0, 0x04DD5 , 0x04AD0 , 0x0A4D0 , 0x0D4D4 , 0x0D250 , 0x0D558 , 0x0B540 , 0x0B6A0 , 0x195A6 , x095B0, 0x049B0 , 0x0A974 , 0x0A4B0 , 0x0B27A , 0x06A50 , 0x06D40 , 0x0AF46 , 0x0AB60 , 0x09570 , x04AF5, 0x04970 , 0x064B0 , 0x074A3 , 0x0EA50 , 0x06B58 , 0x055C0 , 0x0AB60 , 0x096D5 , 0x092E0 , x0C960, 0x0D954 , 0x0D4A0 , 0x0DA50 , 0x07552 , 0x056A0 , 0x0ABB7 , 0x025D0 , 0x092D0 , 0x0CAB5 , x0A950, 0x0B4A0 , 0x0BAA4 , 0x0AD50 , 0x055D9 , 0x04BA0 , 0x0A5B0 , 0x15176 , 0x052B0 , 0x0A930 , x07954, 0x06AA0 , 0x0AD50 , 0x05B52 , 0x04B60 , 0x0A6E6 , 0x0A4E0 , 0x0D260 , 0x0EA65 , 0x0D530 , x05AA0, 0x076A3 , 0x096D0 , 0x04BD7 , 0x04AD0 , 0x0A4D0 , 0x1D0B6 , 0x0D250 , 0x0D520 , 0x0DD45 , x0B5A0, 0x056D0 , 0x055B2 , 0x049B0 , 0x0A577 , 0x0A4B0 , 0x0AA50 , 0x1B255 , 0x06D20 , 0x0ADA0 , x14B63 }; #endregion #region 星座名称 private static string [] _constellationName = { " 白羊座 " , " 金牛座 " , " 双子座 " , " 巨蟹座 " , " 狮子座 " , " 处女座 " , " 天秤座 " , " 天蝎座 " , " 射手座 " , " 摩羯座 " , " 水瓶座 " , " 双鱼座 " }; #endregion #region 二十四节气 private static string [] _lunarHolidayName = { " 小寒 " , " 大寒 " , " 立春 " , " 雨水 " , " 惊蛰 " , " 春分 " , " 清明 " , " 谷雨 " , " 立夏 " , " 小满 " , " 芒种 " , " 夏至 " , " 小暑 " , " 大暑 " , " 立秋 " , " 处暑 " , " 白露 " , " 秋分 " , " 寒露 " , " 霜降 " , " 立冬 " , " 小雪 " , " 大雪 " , " 冬至 " }; #endregion #region 二十八星宿 private static string [] _chineseConstellationName = { // 四 五 六 日 一 二 三 " 角木蛟 " , " 亢金龙 " , " 女土蝠 " , " 房日兔 " , " 心月狐 " , " 尾火虎 " , " 箕水豹 " , " 斗木獬 " , " 牛金牛 " , " 氐土貉 " , " 虚日鼠 " , " 危月燕 " , " 室火猪 " , " 壁水獝 " , " 奎木狼 " , " 娄金狗 " , " 胃土彘 " , " 昴日鸡 " , " 毕月乌 " , " 觜火猴 " , " 参水猿 " , " 井木犴 " , " 鬼金羊 " , " 柳土獐 " , " 星日马 " , " 张月鹿 " , " 翼火蛇 " , " 轸水蚓 " }; #endregion #region 节气数据 private static string [] SolarTerm = new string [] { " 小寒 " , " 大寒 " , " 立春 " , " 雨水 " , " 惊蛰 " , " 春分 " , " 清明 " , " 谷雨 " , " 立夏 " , " 小满 " , " 芒种 " , " 夏至 " , " 小暑 " , " 大暑 " , " 立秋 " , " 处暑 " , " 白露 " , " 秋分 " , " 寒露 " , " 霜降 " , " 立冬 " , " 小雪 " , " 大雪 " , " 冬至 " }; private static int [] sTermInfo = new int [] { 0 , 21208 , 42467 , 63836 , 85337 , 107014 , 128867 , 150921 , 173149 , 195551 , 218072 , 240693 , 263343 , 285989 , 308563 , 331033 , 353350 , 375494 , 397447 , 419210 , 440795 , 462224 , 483532 , 504758 }; #endregion #region 农历相关数据 private static string ganStr = " 甲乙丙丁戊己庚辛壬癸 " ; private static string zhiStr = " 子丑寅卯辰巳午未申酉戌亥 " ; private static string animalStr = " 鼠牛虎兔龙蛇马羊猴鸡狗猪 " ; private static string nStr1 = " 日一二三四五六七八九 " ; private static string nStr2 = " 初十廿卅 " ; private static string [] _monthString = { " 出错 " , " 正月 " , " 二月 " , " 三月 " , " 四月 " , " 五月 " , " 六月 " , " 七月 " , " 八月 " , " 九月 " , " 十月 " , " 十一月 " , " 腊月 " }; #endregion #region 按公历计算的节日 private static SolarHolidayStruct[] sHolidayInfo = new SolarHolidayStruct[]{ new SolarHolidayStruct( 1 , 1 , 1 , " 元旦 " ), new SolarHolidayStruct( 2 , 2 , 0 , " 世界湿地日 " ), new SolarHolidayStruct( 2 , 10 , 0 , " 国际气象节 " ), new SolarHolidayStruct( 2 , 14 , 0 , " 情人节 " ), new SolarHolidayStruct( 3 , 1 , 0 , " 国际海豹日 " ), new SolarHolidayStruct( 3 , 5 , 0 , " 学雷锋纪念日 " ), new SolarHolidayStruct( 3 , 8 , 0 , " 妇女节 " ), new SolarHolidayStruct( 3 , 12 , 0 , " 植树节 孙中山逝世纪念日 " ), new SolarHolidayStruct( 3 , 14 , 0 , " 国际警察日 " ), new SolarHolidayStruct( 3 , 15 , 0 , " 消费者权益日 " ), new SolarHolidayStruct( 3 , 17 , 0 , " 中国国医节 国际航海日 " ), new SolarHolidayStruct( 3 , 21 , 0 , " 世界森林日 消除种族歧视国际日 世界儿歌日 " ), new SolarHolidayStruct( 3 , 22 , 0 , " 世界水日 " ), new SolarHolidayStruct( 3 , 24 , 0 , " 世界防治结核病日 " ), new SolarHolidayStruct( 4 , 1 , 0 , " 愚人节 " ), new SolarHolidayStruct( 4 , 7 , 0 , " 世界卫生日 " ), new SolarHolidayStruct( 4 , 22 , 0 , " 世界地球日 " ), new SolarHolidayStruct( 5 , 1 , 1 , " 劳动节 " ), new SolarHolidayStruct( 5 , 2 , 1 , " 劳动节假日 " ), new SolarHolidayStruct( 5 , 3 , 1 , " 劳动节假日 " ), new SolarHolidayStruct( 5 , 4 , 0 , " 青年节 " ), new SolarHolidayStruct( 5 , 8 , 0 , " 世界红十字日 " ), new SolarHolidayStruct( 5 , 12 , 0 , " 国际护士节 " ), new SolarHolidayStruct( 5 , 31 , 0 , " 世界无烟日 " ), new SolarHolidayStruct( 6 , 1 , 0 , " 国际儿童节 " ), new SolarHolidayStruct( 6 , 5 , 0 , " 世界环境保护日 " ), new SolarHolidayStruct( 6 , 26 , 0 , " 国际禁毒日 " ), new SolarHolidayStruct( 7 , 1 , 0 , " 建党节 香港回归纪念 世界建筑日 " ), new SolarHolidayStruct( 7 , 11 , 0 , " 世界人口日 " ), new SolarHolidayStruct( 8 , 1 , 0 , " 建军节 " ), new SolarHolidayStruct( 8 , 8 , 0 , " 中国男子节 父亲节 " ), new SolarHolidayStruct( 8 , 15 , 0 , " 抗日战争胜利纪念 " ), new SolarHolidayStruct( 9 , 9 , 0 , " 逝世纪念 " ), new SolarHolidayStruct( 9 , 10 , 0 , " 教师节 " ), new SolarHolidayStruct( 9 , 18 , 0 , " 九·一八事变纪念日 " ), new SolarHolidayStruct( 9 , 20 , 0 , " 国际爱牙日 " ), new SolarHolidayStruct( 9 , 27 , 0 , " 世界旅游日 " ), new SolarHolidayStruct( 9 , 28 , 0 , " 孔子诞辰 " ), new SolarHolidayStruct( 10 , 1 , 1 , " 国庆节 国际音乐日 " ), new SolarHolidayStruct( 10 , 2 , 1 , " 国庆节假日 " ), new SolarHolidayStruct( 10 , 3 , 1 , " 国庆节假日 " ), new SolarHolidayStruct( 10 , 6 , 0 , " 老人节 " ), new SolarHolidayStruct( 10 , 24 , 0 , " 联合国日 " ), new SolarHolidayStruct( 11 , 10 , 0 , " 世界青年节 " ), new SolarHolidayStruct( 11 , 12 , 0 , " 孙中山诞辰纪念 " ), new SolarHolidayStruct( 12 , 1 , 0 , " 世界艾滋病日 " ), new SolarHolidayStruct( 12 , 3 , 0 , " 世界残疾人日 " ), new SolarHolidayStruct( 12 , 20 , 0 , " 澳门回归纪念 " ), new SolarHolidayStruct( 12 , 24 , 0 , " 平安夜 " ), new SolarHolidayStruct( 12 , 25 , 0 , " 圣诞节 " ), new SolarHolidayStruct( 12 , 26 , 0 , " 诞辰纪念 " ) }; #endregion #region 按农历计算的节日 private static LunarHolidayStruct[] lHolidayInfo = new LunarHolidayStruct[]{ new LunarHolidayStruct( 1 , 1 , 1 , " 春节 " ), new LunarHolidayStruct( 1 , 15 , 0 , " 元宵节 " ), new LunarHolidayStruct( 5 , 5 , 0 , " 端午节 " ), new LunarHolidayStruct( 7 , 7 , 0 , " 七夕情人节 " ), new LunarHolidayStruct( 7 , 15 , 0 , " 中元节 盂兰盆节 " ), new LunarHolidayStruct( 8 , 15 , 0 , " 中秋节 " ), new LunarHolidayStruct( 9 , 9 , 0 , " 重阳节 " ), new LunarHolidayStruct( 12 , 8 , 0 , " 腊八节 " ), new LunarHolidayStruct( 12 , 23 , 0 , " 北方小年(扫房) " ), new LunarHolidayStruct( 12 , 24 , 0 , " 南方小年(掸尘) " ), // new LunarHolidayStruct(12, 30, 0, "除夕") // 注意除夕需要其它方法进行计算 }; #endregion #region 按某月第几个星期几 private static WeekHolidayStruct[] wHolidayInfo = new WeekHolidayStruct[]{ new WeekHolidayStruct( 5 , 2 , 1 , " 母亲节 " ), new WeekHolidayStruct( 5 , 3 , 1 , " 全国助残日 " ), new WeekHolidayStruct( 6 , 3 , 1 , " 父亲节 " ), new WeekHolidayStruct( 9 , 3 , 3 , " 国际和平日 " ), new WeekHolidayStruct( 9 , 4 , 1 , " 国际聋人节 " ), new WeekHolidayStruct( 10 , 1 , 2 , " 国际住房日 " ), new WeekHolidayStruct( 10 , 1 , 4 , " 国际减轻自然灾害日 " ), new WeekHolidayStruct( 11 , 4 , 5 , " 感恩节 " ) }; #endregion #endregion #region 构造函数 #region ChinaCalendar <公历日期初始化> /// <summary> /// 用一个标准的公历日期来初使化 /// </summary> /// <param name="dt"></param> public ChineseCalendar(DateTime dt) { int i; int leap; int temp; int offset; CheckDateLimit(dt); _date = dt.Date; _datetime = dt; // 农历日期计算部分 leap = 0 ; temp = 0 ; TimeSpan ts = _date - ChineseCalendar.MinDay; // 计算两天的基本差距 offset = ts.Days; for (i = MinYear; i <= MaxYear; i ++ ) { temp = GetChineseYearDays(i); // 求当年农历年天数 if (offset - temp < 1 ) break ; else { offset = offset - temp; } } _cYear = i; leap = GetChineseLeapMonth(_cYear); // 计算该年闰哪个月 // 设定当年是否有闰月 if (leap > 0 ) { _cIsLeapYear = true ; } else { _cIsLeapYear = false ; } _cIsLeapMonth = false ; for (i = 1 ; i <= 12 ; i ++ ) { // 闰月 if ((leap > 0 ) && (i == leap + 1 ) && (_cIsLeapMonth == false )) { _cIsLeapMonth = true ; i = i - 1 ; temp = GetChineseLeapMonthDays(_cYear); // 计算闰月天数 } else { _cIsLeapMonth = false ; temp = GetChineseMonthDays(_cYear, i); // 计算非闰月天数 } offset = offset - temp; if (offset <= 0 ) break ; } offset = offset + temp; _cMonth = i; _cDay = offset; } #endregion #region ChinaCalendar <农历日期初始化> /// <summary> /// 用农历的日期来初使化 /// </summary> /// <param name="cy"> 农历年 </param> /// <param name="cm"> 农历月 </param> /// <param name="cd"> 农历日 </param> /// <param name="LeapFlag"> 闰月标志 </param> public ChineseCalendar( int cy, int cm, int cd, bool leapMonthFlag) { int i, leap, Temp, offset; CheckChineseDateLimit(cy, cm, cd, leapMonthFlag); _cYear = cy; _cMonth = cm; _cDay = cd; offset = 0 ; for (i = MinYear; i < cy; i ++ ) { Temp = GetChineseYearDays(i); // 求当年农历年天数 offset = offset + Temp; } leap = GetChineseLeapMonth(cy); // 计算该年应该闰哪个月 if (leap != 0 ) { this ._cIsLeapYear = true ; } else { this ._cIsLeapYear = false ; } if (cm != leap) { _cIsLeapMonth = false ; // 当前日期并非闰月 } else { _cIsLeapMonth = leapMonthFlag; // 使用用户输入的是否闰月月份 } if ((_cIsLeapYear == false ) || // 当年没有闰月 (cm < leap)) // 计算月份小于闰月 { #region ... for (i = 1 ; i < cm; i ++ ) { Temp = GetChineseMonthDays(cy, i); // 计算非闰月天数 offset = offset + Temp; } // 检查日期是否大于最大天 if (cd > GetChineseMonthDays(cy, cm)) { throw new ChineseCalendarException( " 不合法的农历日期 " ); } offset = offset + cd; // 加上当月的天数 #endregion } else // 是闰年,且计算月份大于或等于闰月 { #region ... for (i = 1 ; i < cm; i ++ ) { Temp = GetChineseMonthDays(cy, i); // 计算非闰月天数 offset = offset + Temp; } if (cm > leap) // 计算月大于闰月 { Temp = GetChineseLeapMonthDays(cy); // 计算闰月天数 offset = offset + Temp; // 加上闰月天数 if (cd > GetChineseMonthDays(cy, cm)) { throw new ChineseCalendarException( " 不合法的农历日期 " ); } offset = offset + cd; } else // 计算月等于闰月 { // 如果需要计算的是闰月,则应首先加上与闰月对应的普通月的天数 if ( this ._cIsLeapMonth == true ) // 计算月为闰月 { Temp = GetChineseMonthDays(cy, cm); // 计算非闰月天数 offset = offset + Temp; } if (cd > GetChineseLeapMonthDays(cy)) { throw new ChineseCalendarException( " 不合法的农历日期 " ); } offset = offset + cd; } #endregion } _date = MinDay.AddDays(offset); } #endregion #endregion #region 私有函数 #region GetChineseMonthDays // 传回农历 y年m月的总天数 private int GetChineseMonthDays( int year, int month) { if (BitTest32((LunarDateArray[year - MinYear] & 0x0000FFFF ), ( 16 - month))) { return 30 ; } else { return 29 ; } } #endregion #region GetChineseLeapMonth // 传回农历 y年闰哪个月 1-12 , 没闰传回 0 private int GetChineseLeapMonth( int year) { return LunarDateArray[year - MinYear] & 0xF ; } #endregion #region GetChineseLeapMonthDays // 传回农历 y年闰月的天数 private int GetChineseLeapMonthDays( int year) { if (GetChineseLeapMonth(year) != 0 ) { if ((LunarDateArray[year - MinYear] & 0x10000 ) != 0 ) { return 30 ; } else { return 29 ; } } else { return 0 ; } } #endregion #region GetChineseYearDays /// <summary> /// 取农历年一年的天数 /// </summary> /// <param name="year"></param> /// <returns></returns> private int GetChineseYearDays( int year) { int i, f, sumDay, info; sumDay = 348 ; // 29天 X 12个月 i = 0x8000 ; info = LunarDateArray[year - MinYear] & 0x0FFFF ; // 计算12个月中有多少天为30天 for ( int m = 0 ; m < 12 ; m ++ ) { f = info & i; if (f != 0 ) { sumDay ++ ; } i = i >> 1 ; } return sumDay + GetChineseLeapMonthDays(year); } #endregion #region GetChineseHour /// <summary> /// 获得当前时间的时辰 /// </summary> /// <param name="time"></param> /// <returns></returns> /// private string GetChineseHour(DateTime dt) { int _hour, _minute, offset, i; int indexGan; string ganHour, zhiHour; string tmpGan; // 计算时辰的地支 _hour = dt.Hour; // 获得当前时间小时 _minute = dt.Minute; // 获得当前时间分钟 if (_minute != 0 ) _hour += 1 ; offset = _hour / 2 ; if (offset >= 12 ) offset = 0 ; // zhiHour = zhiStr[offset].ToString(); // 计算天干 TimeSpan ts = this ._date - GanZhiStartDay; i = ts.Days % 60 ; indexGan = ((i % 10 + 1 ) * 2 - 1 ) % 10 - 1 ; // ganStr[i % 10] 为日的天干,(n*2-1) %10得出地支对应,n从1开始 tmpGan = ganStr.Substring(indexGan) + ganStr.Substring( 0 , indexGan + 2 ); // 凑齐12位 // ganHour = ganStr[((i % 10 + 1) * 2 - 1) % 10 - 1].ToString(); return tmpGan[offset].ToString() + zhiStr[offset].ToString(); } #endregion #region CheckDateLimit /// <summary> /// 检查公历日期是否符合要求 /// </summary> /// <param name="dt"></param> private void CheckDateLimit(DateTime dt) { if ((dt < MinDay) || (dt > MaxDay)) { throw new ChineseCalendarException( " 超出可转换的日期 " ); } } #endregion #region CheckChineseDateLimit /// <summary> /// 检查农历日期是否合理 /// </summary> /// <param name="year"></param> /// <param name="month"></param> /// <param name="day"></param> /// <param name="leapMonth"></param> private void CheckChineseDateLimit( int year, int month, int day, bool leapMonth) { if ((year < MinYear) || (year > MaxYear)) { throw new ChineseCalendarException( " 非法农历日期 " ); } if ((month < 1 ) || (month > 12 )) { throw new ChineseCalendarException( " 非法农历日期 " ); } if ((day < 1 ) || (day > 30 )) // 中国的月最多30天 { throw new ChineseCalendarException( " 非法农历日期 " ); } int leap = GetChineseLeapMonth(year); // 计算该年应该闰哪个月 if ((leapMonth == true ) && (month != leap)) { throw new ChineseCalendarException( " 非法农历日期 " ); } } #endregion #region ConvertNumToChineseNum /// <summary> /// 将0-9转成汉字形式 /// </summary> /// <param name="n"></param> /// <returns></returns> private string ConvertNumToChineseNum( char n) { if ((n < ' 0 ' ) || (n > ' 9 ' )) return "" ; switch (n) { case ' 0 ' : return HZNum[ 0 ].ToString(); case ' 1 ' : return HZNum[ 1 ].ToString(); case ' 2 ' : return HZNum[ 2 ].ToString(); case ' 3 ' : return HZNum[ 3 ].ToString(); case ' 4 ' : return HZNum[ 4 ].ToString(); case ' 5 ' : return HZNum[ 5 ].ToString(); case ' 6 ' : return HZNum[ 6 ].ToString(); case ' 7 ' : return HZNum[ 7 ].ToString(); case ' 8 ' : return HZNum[ 8 ].ToString(); case ' 9 ' : return HZNum[ 9 ].ToString(); default : return "" ; } } #endregion #region BitTest32 /// <summary> /// 测试某位是否为真 /// </summary> /// <param name="num"></param> /// <param name="bitpostion"></param> /// <returns></returns> private bool BitTest32( int num, int bitpostion) { if ((bitpostion > 31 ) || (bitpostion < 0 )) throw new Exception( " Error Param: bitpostion[0-31]: " + bitpostion.ToString()); int bit = 1 << bitpostion; if ((num & bit) == 0 ) { return false ; } else { return true ; } } #endregion #region ConvertDayOfWeek /// <summary> /// 将星期几转成数字表示 /// </summary> /// <param name="dayOfWeek"></param> /// <returns></returns> private int ConvertDayOfWeek(DayOfWeek dayOfWeek) { switch (dayOfWeek) { case DayOfWeek.Sunday: return 1 ; case DayOfWeek.Monday: return 2 ; case DayOfWeek.Tuesday: return 3 ; case DayOfWeek.Wednesday: return 4 ; case DayOfWeek.Thursday: return 5 ; case DayOfWeek.Friday: return 6 ; case DayOfWeek.Saturday: return 7 ; default : return 0 ; } } #endregion #region CompareWeekDayHoliday /// <summary> /// 比较当天是不是指定的第周几 /// </summary> /// <param name="date"></param> /// <param name="month"></param> /// <param name="week"></param> /// <param name="day"></param> /// <returns></returns> private bool CompareWeekDayHoliday(DateTime date, int month, int week, int day) { bool ret = false ; if (date.Month == month) // 月份相同 { if (ConvertDayOfWeek(date.DayOfWeek) == day) // 星期几相同 { DateTime firstDay = new DateTime(date.Year, date.Month, 1 ); // 生成当月第一天 int i = ConvertDayOfWeek(firstDay.DayOfWeek); int firWeekDays = 7 - ConvertDayOfWeek(firstDay.DayOfWeek) + 1 ; // 计算第一周剩余天数 if (i > day) { if ((week - 1 ) * 7 + day + firWeekDays == date.Day) { ret = true ; } } else { if (day + firWeekDays + (week - 2 ) * 7 == date.Day) { ret = true ; } } } } return ret; } #endregion #endregion #region 属性 #region 节日 #region ChineseCalendarHoliday /// <summary> /// 计算中国农历节日 /// </summary> public string ChineseCalendarHoliday { get { string tempStr = "" ; if ( this ._cIsLeapMonth == false ) // 闰月不计算节日 { foreach (LunarHolidayStruct lh in lHolidayInfo) { if ((lh.Month == this ._cMonth) && (lh.Day == this ._cDay)) { tempStr = lh.HolidayName; break ; } } // 对除夕进行特别处理 if ( this ._cMonth == 12 ) { int i = GetChineseMonthDays( this ._cYear, 12 ); // 计算当年农历12月的总天数 if ( this ._cDay == i) // 如果为最后一天 { tempStr = " 除夕 " ; } } } return tempStr; } } #endregion #region WeekDayHoliday /// <summary> /// 按某月第几周第几日计算的节日 /// </summary> public string WeekDayHoliday { get { string tempStr = "" ; foreach (WeekHolidayStruct wh in wHolidayInfo) { if (CompareWeekDayHoliday(_date, wh.Month, wh.WeekAtMonth, wh.WeekDay)) { tempStr = wh.HolidayName; break ; } } return tempStr; } } #endregion #region DateHoliday /// <summary> /// 按公历日计算的节日 /// </summary> public string DateHoliday { get { string tempStr = "" ; foreach (SolarHolidayStruct sh in sHolidayInfo) { if ((sh.Month == _date.Month) && (sh.Day == _date.Day)) { tempStr = sh.HolidayName; break ; } } return tempStr; } } #endregion #endregion #region 公历日期 #region Date /// <summary> /// 取对应的公历日期 /// </summary> public DateTime Date { get { return _date; } set { _date = value; } } #endregion #region WeekDay /// <summary> /// 取星期几 /// </summary> public DayOfWeek WeekDay { get { return _date.DayOfWeek; } } #endregion #region WeekDayStr /// <summary> /// 周几的字符 /// </summary> public string WeekDayStr { get { switch (_date.DayOfWeek) { case DayOfWeek.Sunday: return " 星期日 " ; case DayOfWeek.Monday: return " 星期一 " ; case DayOfWeek.Tuesday: return " 星期二 " ; case DayOfWeek.Wednesday: return " 星期三 " ; case DayOfWeek.Thursday: return " 星期四 " ; case DayOfWeek.Friday: return " 星期五 " ; default : return " 星期六 " ; } } } #endregion #region DateString /// <summary> /// 公历日期中文表示法 如一九九七年七月一日 /// </summary> public string DateString { get { return " 公元 " + this ._date.ToLongDateString(); } } #endregion #region IsLeapYear /// <summary> /// 当前是否公历闰年 /// </summary> public bool IsLeapYear { get { return DateTime.IsLeapYear( this ._date.Year); } } #endregion #region ChineseConstellation /// <summary> /// 28星宿计算 /// </summary> public string ChineseConstellation { get { int offset = 0 ; int modStarDay = 0 ; TimeSpan ts = this ._date - ChineseConstellationReferDay; offset = ts.Days; modStarDay = offset % 28 ; return (modStarDay >= 0 ? _chineseConstellationName[modStarDay] : _chineseConstellationName[ 27 + modStarDay]); } } #endregion #region ChineseHour /// <summary> /// 时辰 /// </summary> public string ChineseHour { get { return GetChineseHour(_datetime); } } #endregion #endregion #region 农历日期 #region IsChineseLeapMonth /// <summary> /// 是否闰月 /// </summary> public bool IsChineseLeapMonth { get { return this ._cIsLeapMonth; } } #endregion #region IsChineseLeapYear /// <summary> /// 当年是否有闰月 /// </summary> public bool IsChineseLeapYear { get { return this ._cIsLeapYear; } } #endregion #region ChineseDay /// <summary> /// 农历日 /// </summary> public int ChineseDay { get { return this ._cDay; } } #endregion #region ChineseDayString /// <summary> /// 农历日中文表示 /// </summary> public string ChineseDayString { get { switch ( this ._cDay) { case 0 : return "" ; case 10 : return " 初十 " ; case 20 : return " 二十 " ; case 30 : return " 三十 " ; default : return nStr2[( int )(_cDay / 10 )].ToString() + nStr1[_cDay % 10 ].ToString(); } } } #endregion #region ChineseMonth /// <summary> /// 农历的月份 /// </summary> public int ChineseMonth { get { return this ._cMonth; } } #endregion #region ChineseMonthString /// <summary> /// 农历月份字符串 /// </summary> public string ChineseMonthString { get { return _monthString[ this ._cMonth]; } } #endregion #region ChineseYear /// <summary> /// 取农历年份 /// </summary> public int ChineseYear { get { return this ._cYear; } } #endregion #region ChineseYearString /// <summary> /// 取农历年字符串如,一九九七年 /// </summary> public string ChineseYearString { get { string tempStr = "" ; string num = this ._cYear.ToString(); for ( int i = 0 ; i < 4 ; i ++ ) { tempStr += ConvertNumToChineseNum(num[i]); } return tempStr + " " ; } } #endregion #region ChineseDateString /// <summary> /// 取农历日期表示法:农历一九九七年正月初五 /// </summary> public string ChineseDateString { get { if ( this ._cIsLeapMonth == true ) { return " 农历 " + ChineseYearString + " " + ChineseMonthString + ChineseDayString; } else { return " 农历 " + ChineseYearString + ChineseMonthString + ChineseDayString; } } } #endregion #region ChineseTwentyFourDay /// <summary> /// 定气法计算二十四节气,二十四节气是按地球公转来计算的,并非是阴历计算的 /// </summary> /// <remarks> /// 节气的定法有两种。古代历法采用的称为"恒气",即按时间把一年等分为24份, /// 每一节气平均得15天有余,所以又称"平气"。现代农历采用的称为"定气",即 /// 按地球在轨道上的位置为标准,一周360°,两节气之间相隔15°。由于冬至时地 /// 球位于近日点附近,运动速度较快,因而太阳在黄道上移动15°的时间不到15天。 /// 夏至前后的情况正好相反,太阳在黄道上移动较慢,一个节气达16天之多。采用 /// 定气时可以保证春、秋两分必然在昼夜平分的那两天。 /// </remarks> public string ChineseTwentyFourDay { get { DateTime baseDateAndTime = new DateTime( 1900 , 1 , 6 , 2 , 5 , 0 ); // #1/6/1900 2:05:00 AM# DateTime newDate; double num; int y; string tempStr = "" ; y = this ._date.Year; for ( int i = 1 ; i <= 24 ; i ++ ) { num = 525948.76 * (y - 1900 ) + sTermInfo[i - 1 ]; newDate = baseDateAndTime.AddMinutes(num); // 按分钟计算 if (newDate.DayOfYear == _date.DayOfYear) { tempStr = SolarTerm[i - 1 ]; break ; } } return tempStr; } } // 当前日期前一个最近节气 public string ChineseTwentyFourPrevDay { get { DateTime baseDateAndTime = new DateTime( 1900 , 1 , 6 , 2 , 5 , 0 ); // #1/6/1900 2:05:00 AM# DateTime newDate; double num; int y; string tempStr = "" ; y = this ._date.Year; for ( int i = 24 ; i >= 1 ; i -- ) { num = 525948.76 * (y - 1900 ) + sTermInfo[i - 1 ]; newDate = baseDateAndTime.AddMinutes(num); // 按分钟计算 if (newDate.DayOfYear < _date.DayOfYear) { tempStr = string .Format( " {0}[{1}] " , SolarTerm[i - 1 ], newDate.ToString( " yyyy-MM-dd " )); break ; } } return tempStr; } } // 当前日期后一个最近节气 public string ChineseTwentyFourNextDay { get { DateTime baseDateAndTime = new DateTime( 1900 , 1 , 6 , 2 , 5 , 0 ); // #1/6/1900 2:05:00 AM# DateTime newDate; double num; int y; string tempStr = "" ; y = this ._date.Year; for ( int i = 1 ; i <= 24 ; i ++ ) { num = 525948.76 * (y - 1900 ) + sTermInfo[i - 1 ]; newDate = baseDateAndTime.AddMinutes(num); // 按分钟计算 if (newDate.DayOfYear > _date.DayOfYear) { tempStr = string .Format( " {0}[{1}] " , SolarTerm[i - 1 ], newDate.ToString( " yyyy-MM-dd " )); break ; } } return tempStr; } } #endregion #endregion #region 星座 #region Constellation /// <summary> /// 计算指定日期的星座序号 /// </summary> /// <returns></returns> public string Constellation { get { int index = 0 ; int y, m, d; y = _date.Year; m = _date.Month; d = _date.Day; y = m * 100 + d; if (((y >= 321 ) && (y <= 419 ))) { index = 0 ; } else if ((y >= 420 ) && (y <= 520 )) { index = 1 ; } else if ((y >= 521 ) && (y <= 620 )) { index = 2 ; } else if ((y >= 621 ) && (y <= 722 )) { index = 3 ; } else if ((y >= 723 ) && (y <= 822 )) { index = 4 ; } else if ((y >= 823 ) && (y <= 922 )) { index = 5 ; } else if ((y >= 923 ) && (y <= 1022 )) { index = 6 ; } else if ((y >= 1023 ) && (y <= 1121 )) { index = 7 ; } else if ((y >= 1122 ) && (y <= 1221 )) { index = 8 ; } else if ((y >= 1222 ) || (y <= 119 )) { index = 9 ; } else if ((y >= 120 ) && (y <= 218 )) { index = 10 ; } else if ((y >= 219 ) && (y <= 320 )) { index = 11 ; } else { index = 0 ; } return _constellationName[index]; } } #endregion #endregion #region 属相 #region Animal /// <summary> /// 计算属相的索引,注意虽然属相是以农历年来区别的,但是目前在实际使用中是按公历来计算的 /// 鼠年为1,其它类推 /// </summary> public int Animal { get { int offset = _date.Year - AnimalStartYear; return (offset % 12 ) + 1 ; } } #endregion #region AnimalString /// <summary> /// 取属相字符串 /// </summary> public string AnimalString { get { int offset = _date.Year - AnimalStartYear; // 阳历计算 // int offset = this._cYear - AnimalStartYear; 农历计算 return animalStr[offset % 12 ].ToString(); } } #endregion #endregion #region 天干地支 #region GanZhiYearString /// <summary> /// 取农历年的干支表示法如 乙丑年 /// </summary> public string GanZhiYearString { get { string tempStr; int i = ( this ._cYear - GanZhiStartYear) % 60 ; // 计算干支 tempStr = ganStr[i % 10 ].ToString() + zhiStr[i % 12 ].ToString() + " " ; return tempStr; } } #endregion #region GanZhiMonthString /// <summary> /// 取干支的月表示字符串,注意农历的闰月不记干支 /// </summary> public string GanZhiMonthString { get { // 每个月的地支总是固定的,而且总是从寅月开始 int zhiIndex; string zhi; if ( this ._cMonth > 10 ) { zhiIndex = this ._cMonth - 10 ; } else { zhiIndex = this ._cMonth + 2 ; } zhi = zhiStr[zhiIndex - 1 ].ToString(); // 根据当年的干支年的干来计算月干的第一个 int ganIndex = 1 ; string gan; int i = ( this ._cYear - GanZhiStartYear) % 60 ; // 计算干支 switch (i % 10 ) { #region ... case 0 : // ganIndex = 3 ; break ; case 1 : // ganIndex = 5 ; break ; case 2 : // ganIndex = 7 ; break ; case 3 : // ganIndex = 9 ; break ; case 4 : // ganIndex = 1 ; break ; case 5 : // ganIndex = 3 ; break ; case 6 : // ganIndex = 5 ; break ; case 7 : // ganIndex = 7 ; break ; case 8 : // ganIndex = 9 ; break ; case 9 : // ganIndex = 1 ; break ; #endregion } gan = ganStr[(ganIndex + this ._cMonth - 2 ) % 10 ].ToString(); return gan + zhi + " " ; } } #endregion #region GanZhiDayString /// <summary> /// 取干支日表示法 /// </summary> public string GanZhiDayString { get { int i, offset; TimeSpan ts = this ._date - GanZhiStartDay; offset = ts.Days; i = offset % 60 ; return ganStr[i % 10 ].ToString() + zhiStr[i % 12 ].ToString() + " " ; } } #endregion #region GanZhiDateString /// <summary> /// 取当前日期的干支表示法如 甲子年乙丑月丙庚日 /// </summary> public string GanZhiDateString { get { return GanZhiYearString + GanZhiMonthString + GanZhiDayString; } } #endregion #endregion #endregion #region 方法 #region NextDay /// <summary> /// 取下一天 /// </summary> /// <returns></returns> public ChineseCalendar NextDay() { DateTime nextDay = _date.AddDays( 1 ); return new ChineseCalendar(nextDay); } #endregion #region PervDay /// <summary> /// 取前一天 /// </summary> /// <returns></returns> public ChineseCalendar PervDay() { DateTime pervDay = _date.AddDays( - 1 ); return new ChineseCalendar(pervDay); } #endregion #endregion } }
调用:
  
  
DateTime dt = DateTime.Now; ChineseCalendar cc = new ChineseCalendar(dt); Console.WriteLine( " 阳历: " + cc.DateString); Console.WriteLine( " 属相: " + cc.AnimalString); Console.WriteLine( " 农历: " + cc.ChineseDateString); Console.WriteLine( " 时辰: " + cc.ChineseHour); Console.WriteLine( " 节气: " + cc.ChineseTwentyFourDay); Console.WriteLine( " 节日: " + cc.DateHoliday); Console.WriteLine( " 前一个节气: " + cc.ChineseTwentyFourPrevDay); Console.WriteLine( " 后一个节气: " + cc.ChineseTwentyFourNextDay); Console.WriteLine( " 干支: " + cc.GanZhiDateString); Console.WriteLine( " 星期: " + cc.WeekDayStr); Console.WriteLine( " 星宿: " + cc.ChineseConstellation); Console.WriteLine( " 星座: " + cc.Constellation);
结果:
  
  
阳历:公元2013年1月27日 属相:蛇 农历:农历二零一二年腊月十六 时辰:庚申 节气: 节日: 前一个节气:大寒[2013-01-20] 后一个节气:立春[2013-02-03] 干支:壬辰年癸丑月癸巳日 星期:星期日 星宿:房日兔 星座:水瓶座
 
 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Python3实现万年历的代码,包括公历、农历节气节日: ```python import datetime # 公历节日 solar_holidays = { (1, 1): "元旦", (2, 14): "情人节", (3, 8): "妇女节", (4, 1): "愚人节", (5, 1): "劳动节", (6, 1): "儿童节", (9, 10): "教师节", (10, 1): "国庆节", (12, 25): "圣诞节" } # 农历节日 lunar_holidays = [ (1, 1, "春节"), (1, 15, "元宵节"), (5, 5, "端午节"), (7, 7, "七夕节"), (8, 15, "中秋节"), (9, 9, "重阳节"), (12, 8, "腊八节"), (12, 23, "小年") ] # 节气 solar_terms = [ "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" ] # 计算农历 class LunarCalendar: def __init__(self, year, month, day): self.year = year self.month = month self.day = day # 农历月份、日份的中文名称 self.lunar_month_names = [ "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" ] self.lunar_day_names = [ "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十" ] # 计算农历日 def lunar_day(self): if self.day < 1 or self.day > 30: return None if self.day == 1: return self.lunar_day_names[0] if self.day == 10: return "初十" if self.day == 20: return "二十" if self.day == 30: return "三十" prefix = "下" if self.day > 20 else "上" return prefix + self.lunar_day_names[self.day % 10 - 1] # 计算农历月 def lunar_month(self): if self.month < 1 or self.month > 12: return None return self.lunar_month_names[self.month - 1] # 计算农历年 def lunar_year(self): heavenly_stems = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] earthly_branches = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] stem = heavenly_stems[(self.year - 4) % 10] branch = earthly_branches[(self.year - 4) % 12] return stem + branch + "年" # 计算农历日期 def lunar_date(self): return self.lunar_year() + self.lunar_month() + self.lunar_day() # 计算公历日期的节气 def solar_term(year, month, day): solar_term_table = [ 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758 ] month_code = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334] _, _, solar_day = datetime.date(year, month, day).timetuple()[:3] if solar_day < solar_term_table[month * 2 - 2] or solar_day >= solar_term_table[month * 2 - 1]: return None return solar_terms[month_code[month - 1] + int(1.0 * (solar_day - solar_term_table[month * 2 - 2]) / 30.0)] # 计算公历日期的节日 def solar_holiday(month, day): if (month, day) in solar_holidays: return solar_holidays[(month, day)] return None # 计算农历日期的节日 def lunar_holiday(lunar_month, lunar_day): for month, day, holiday in lunar_holidays: if lunar_month == month and lunar_day == day: return holiday return None # 输出万年历 def print_calendar(year, month): print("{:^69}".format(f"{year}年{month}月")) print("{:<14}{:<14}{:<14}{:<14}{:<14}{:<14}{:<14}".format("日", "一", "二", "三", "四", "五", "六")) # 计算本月第一天是星期几 week_day_of_first_day = datetime.date(year, month, 1).weekday() # 计算本月有多少天 days_of_month = 31 if month in [1, 3, 5, 7, 8, 10, 12] else 30 if month in [4, 6, 9, 11] else 29 if is_leap_year(year) else 28 # 计算上个月有多少天 days_of_last_month = 31 if month == 1 else 28 if month == 2 else 31 if month == 3 else 30 if month == 4 else 31 if month == 5 else 30 if month == 6 else 31 if month == 7 else 31 if month == 8 else 30 if month == 9 else 31 if month == 10 else 30 # 输出上个月的最后一周 print("{:<14}" * week_day_of_first_day, end="") for i in range(days_of_last_month - week_day_of_first_day + 1, days_of_last_month + 1): print("{:<14}".format(i), end="") print() # 输出本月 for i in range(1, days_of_month + 1): day = datetime.date(year, month, i) lunar_calendar = LunarCalendar.from_solar_date(day) # 判断是否是节气 term = solar_term(year, month, i) if term: print("{:^14}".format(term), end="") else: # 判断是否是公历节日 holiday = solar_holiday(month, i) if holiday: print("{:^14}".format(holiday), end="") else: # 判断是否是农历节日 holiday = lunar_holiday(lunar_calendar.month, lunar_calendar.day) if holiday: print("{:^14}".format(holiday), end="") else: print("{:<14}".format(i), end="") if day.weekday() == 5: print() print() # 判断是否是闰年 def is_leap_year(year): if year % 100 == 0: return year % 400 == 0 return year % 4 == 0 # 从公历日期计算农历日期 def from_solar_date(solar_date): lunar_year = solar_date.year lunar_month = 0 lunar_day = 0 # 计算春节的公历日期 spring_festival = datetime.date(lunar_year, 1, 1) if LunarCalendar(lunar_year, 1, 1).lunar_month() == "正" else datetime.date(lunar_year - 1, 1, 1) # 计算与春节相差多少天 delta_days = (solar_date - spring_festival).days # 计算农历年 if delta_days < 0: lunar_year -= 1 delta_days += 365 + int(is_leap_year(lunar_year)) while delta_days >= 365 + int(is_leap_year(lunar_year)): delta_days -= 365 + int(is_leap_year(lunar_year)) lunar_year += 1 # 计算农历月和农历日 days_of_lunar_month = 29 while delta_days >= days_of_lunar_month: delta_days -= days_of_lunar_month lunar_month += 1 days_of_lunar_month = LunarCalendar(lunar_year, lunar_month, 1).days_of_month() lunar_month += 1 lunar_day = delta_days + 1 return LunarCalendar(lunar_year, lunar_month, lunar_day) # 测试代码 print_calendar(2021, 9) ``` 运行结果: ``` 2021年9月 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 中秋节 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ``` 可以看到,输出了2021年9月的万年历,其中包括公历节日农历节日节气和中秋节等信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值