获得当前日期+农历日期及生肖

来源:互联网 发布:js 调试工具 编辑:程序博客网 时间:2024/04/26 21:39
    #region 农历、节气
    /// <summary>
    /// 类
    /// </summary>
    public class ChinaCalendar
    {
        /// <summary>
        /// 获得当前日期+农历日期及生肖
        /// </summary>
        public string GetChinaCalendar
        {
            get
            {
               return GetDatetime.ToString("yyyy年MM月dd日") + GetWeek + " 农历" + GetChinaYear + GetChinaMonth + GetChinaDay;
            }
        }




        #region 方法主体
        //默认系统当前日期
        private DateTime dtvalue = Convert.ToDateTime(DateTime.Now.ToShortDateString());


        //用来计算农历的初始日期
        private DateTime baseDate = new DateTime(1900, 1, 31);


        public int chinaYear;       //农历年
        public int chinaMonth;      //农历月
        public int doubleMonth;     //闰月
        public bool isLeap;         //是否闰月标记
        public int chinaDay;        //农历日


        /// <summary>
        /// 获取或设置类中应用日期  
        /// </summary>
        public DateTime GetDatetime
        {
            get { return dtvalue; }
            set
            {
                dtvalue = Convert.ToDateTime(value.ToShortDateString());
                InitializeValue();
            }
        }


        /// <summary>
        /// 获取应用星期  
        /// </summary>
        public string GetWeek
        {
            get
            {


                string XingQi = dtvalue.DayOfWeek.ToString();
                if (XingQi == "Monday")
                {
                    return  "星期一";
                }
                else if (XingQi == "Tuesday")
                {
                    return  "星期二";
                }
                else if (XingQi == "Wednesday")
                {
                    return  "星期三";
                }
                else if (XingQi == "Thursday")
                {
                    return  "星期四";
                }
                else if (XingQi == "Friday")
                {
                    return  "星期五";
                }
                else if (XingQi == "Saturday")
                {
                    return  "星期六";
                }
                else
                {
                    return  "星期日";
                }


            }
        }


        /// <summary>
        /// 获取该年的属相(生肖)
        /// </summary>
        public string GetAnimal
        {
            get { return Animal(); }
        }


        /// <summary>
        ///  获取农历年(天干 地支)
        /// </summary>
        public string GetChinaYear
        {
            get { return ChinaYear(); }
        }


        /// <summary>
        /// 获取农历月或闰月
        /// </summary>
        public string GetChinaMonth
        {
            get { return ChinaMonth(); }
        }


        /// <summary>
        /// 获取农历日
        /// </summary>
        public string GetChinaDay
        {
            get { return ChinaDay(); }
        }


        #region 农历的静态数据


        private static int[] ChinaCalendarInfo = { 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,0x0c950,


                                           0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,


                                           0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,


                                           0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,


                                           0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,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,


                                           0x14b63


                                         };


        private static string[] Animals = { "鼠", "牛", "虎", "兔" , "龙" , "蛇" , "马" , "羊" , "猴" , "鸡" , "狗" , "猪" };


        private static string[] dayStr1 = { "日", "一", "二", "三" , "四" , "五" , "六" , "七" , "八" , "九" , "十" };


        private static string[] dayStr2 = { "初", "十", "廿", "卅" , "□" };


        private static string[] chinaMonthName = { "正月", "二月", "三月", "四月" , "五月" , "六月" , "七月" , "八月" , "九月" , "十月" , "十一" , "腊月" };


        private static string[] Gan = { "甲", "乙", "丙", "丁" , "戊" , "己" , "庚" , "辛" , "壬" , "癸" };


        private static string[] Zhi = { "子", "丑", "寅", "卯" , "辰" , "巳" , "午" , "未" , "申" , "酉" , "戌" , "亥" };


        //  private static string[] solarTerm = { "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" };


        private static int[] sTermInfo = { 0, 21208, 42467, 63836 , 85337 , 107014 , 128867 , 150921 , 173149 , 195551 , 218072 , 240693 , 263343 , 285989 , 308563 , 331033 , 353350 , 375494 , 397447 , 419210 , 440795 , 462224 , 483532 , 504758 };


        private static string[] solarTermName ={ 
            "小寒", "大寒", "立春", "雨水","惊蛰", "春分", "清明", "谷雨","立夏", "小满", "芒种", "夏至", 
            "小暑", "大暑", "立秋", "处暑","白露", "秋分", "寒露", "霜降","立冬", "小雪", "大雪", "冬至"};




        #endregion


        #region 构造函数


        public ChinaCalendar()
        { InitializeValue(); }


        public ChinaCalendar(DateTime date)
        {
            dtvalue = Convert.ToDateTime(date.ToShortDateString());
            InitializeValue();
        }


        #endregion


        private void InitializeValue()
        {
            TimeSpan timeSpan = dtvalue - baseDate;
            int sumdays = Convert.ToInt32(timeSpan.TotalDays);   //86400000=1000*24*60*60
            int tempdays = 0;


            //计算农历年
            for (chinaYear = 1900; chinaYear < 2050 && sumdays > 0; chinaYear++)
            {
                tempdays = ChinaYearDays(chinaYear);
                sumdays -= tempdays;
            }


            if (sumdays < 0)
            {
                sumdays += tempdays;
                chinaYear--;
            }


            //计算闰月
            doubleMonth = DoubleMonth(chinaYear);
            isLeap = false;


            //计算农历月
            for (chinaMonth = 1; chinaMonth < 13 && sumdays > 0; chinaMonth++)
            {
                //闰月
                if (doubleMonth > 0 && chinaMonth == (doubleMonth + 1) && isLeap == false)
                {
                    --chinaMonth;
                    isLeap = true;
                    tempdays = DoubleMonthDays(chinaYear);
                }
                else
                {
                    tempdays = MonthDays(chinaYear, chinaMonth);
                }


                //解除闰月
                if (isLeap == true && chinaMonth == (doubleMonth + 1))
                {
                    isLeap = false;
                }
                sumdays -= tempdays;
            }


            //计算农历日
            if (sumdays == 0 && doubleMonth > 0 && chinaMonth == doubleMonth + 1)
            {
                if (isLeap)
                {
                    isLeap = false;
                }
                else
                {
                    isLeap = true;
                    --chinaMonth;
                }
            }


            if (sumdays < 0)
            {
                sumdays += tempdays;
                --chinaMonth;
            }


            chinaDay = sumdays + 1;


            //计算节气
            ComputeSolarTerm();
        }


        ///<summary>
        ///返回农历年的总天数
        ///</summary>
        ///<param name="year">农历年</param>
        ///<returns></returns>
        private int ChinaYearDays(int year)
        {
            int i, sum = 348;
            for (i = 0x8000; i > 0x8; i >>= 1)
            {
                sum += ((ChinaCalendarInfo[year - 1900] & i) != 0) ? 1 : 0;
            }
            return (sum + DoubleMonthDays(year));
        }


        ///<summary>
        ///返回农历年闰月月份1-12 , 没闰返回0
        ///</summary>
        ///<param name="year">农历年</param>
        ///<returns></returns>
        private int DoubleMonth(int year)
        {
            return (ChinaCalendarInfo[year - 1900] & 0xf);
        }


        ///<summary>
        ///返回农历年闰月的天数
        ///</summary>
        ///<param name="year">农历年</param>
        ///<returns></returns>
        private int DoubleMonthDays(int year)
        {
            if (DoubleMonth(year) != 0)
                return (((ChinaCalendarInfo[year - 1900] & 0x10000) != 0) ? 30 : 29);
            else
                return (0);
        }


        ///</summary>
        ///返回农历年月份的总天数
        ///</summary>
        ///<param name="year">农历年</param>
        ///<param name="month">农历月</param>
        ///<returns></returns>
        private int MonthDays(int year, int month)
        {
            return (((ChinaCalendarInfo[year - 1900] & (0x10000 >> month)) != 0) ? 30 : 29);
        }


        //计算属相(生肖)
        private string Animal()
        {
            return Animals[(chinaYear - 4) % 60 % 12];
        }


        //生成农历年字符串
        public string ChinaYear()
        {
            return (Gan[(chinaYear - 4) % 60 % 10] + Zhi[(chinaYear - 4) % 60 % 12] +"["+GetAnimal+ "]年");
        }


        //生成农历月字符串
        private string ChinaMonth()
        {
            if (isLeap == true)
            {
                return "闰" + chinaMonthName[chinaMonth - 1];
            }
            else
            {
                return chinaMonthName[chinaMonth - 1];
            }
        }


        //生成农历日字符串
        private string ChinaDay()
        {
            string s;
            switch (chinaDay)
            {
                case 10:
                    s = "初十";
                    break;
                case 20:
                    s = "二十";
                    break;
                case 30:
                    s = "三十";
                    break;
                default:
                    s = dayStr2[chinaDay / 10];
                    s += dayStr1[chinaDay % 10];
                    break;
            }
            return (s);
        }


        #region 节气


        public struct SolarTerm
        {
            /// <summary>
            /// 节气的名称
            /// </summary>
            public string Name;


            /// <summary>
            /// 节气的时间
            /// </summary>
            public DateTime DateTime;
        }


        private SolarTerm[] solarTerm = new SolarTerm[2];


        /// <summary>
        /// 返回指定日期的月份两个节气的名称及时间的SolarTerm数组
        /// </summary>
        public SolarTerm[] GetSolarTerm
        {
            get
            {
                return solarTerm;
            }
        }


        /// <summary>
        /// 返回指定日期的节气名,没有节气名则返回空字符串
        /// </summary>
        public string GetTermName
        {
            get
            {
                foreach (SolarTerm sterm in solarTerm)
                    if (dtvalue.Day == sterm.DateTime.Day)
                    {
                        return sterm.Name;
                    }


                return "";
            }
        }


        // 计算节气
        private void ComputeSolarTerm()
        {
            int year = dtvalue.Year;
            int month = dtvalue.Month;


            for (int n = month * 2 - 1; n <= month * 2; n++)
            {
                double Termdays = Term(year, n, true);
                double mdays = AntiDayDifference(year, Math.Floor(Termdays));
                double sm1 = Math.Floor(mdays / 100);
                int hour = (int)Math.Floor((double)Tail(Termdays) * 24);
                int minute = (int)Math.Floor((double)(Tail(Termdays) * 24 - hour) * 60);
                int tMonth = (int)Math.Ceiling((double)n / 2);
                int day = (int)mdays % 100;


                solarTerm[n - month * 2 + 1].Name = solarTermName[n - 1];
                solarTerm[n - month * 2 + 1].DateTime = new DateTime(year, tMonth, day, hour, minute, 0);
            }
        }




        //返回y年第n个节气(如小寒为1)的日差天数值(pd取值真假,分别表示平气和定气)
        private double Term(int y, int n, bool pd)
        {
            //儒略日
            double juD = y * (365.2423112 - 6.4e-14 * (y - 100) * (y - 100) - 3.047e-8 * (y - 100)) + 15.218427 * n + 1721050.71301;


            //角度
            double tht = 3e-4 * y - 0.372781384 - 0.2617913325 * n;


            //年差实均数
            double yrD = (1.945 * Math.Sin(tht) - 0.01206 * Math.Sin(2 * tht)) * (1.048994 - 2.583e-5 * y);


            //朔差实均数
            double shuoD = -18e-4 * Math.Sin(2.313908653 * y - 0.439822951 - 3.0443 * n);


            double vs = (pd) ? (juD + yrD + shuoD - EquivalentStandardDay(y, 1, 0) - 1721425) : (juD - EquivalentStandardDay(y, 1, 0) - 1721425);
            return vs;
        }




        // 返回阳历y年日差天数为x时所对应的月日数(如y=2000,x=274时,返回1001(表示10月1日,即返回100*m+d))
        private double AntiDayDifference(int y, double x)
        {
            int m = 1;
            for (int j = 1; j <= 12; j++)
            {
                int mL = DayDifference(y, j + 1, 1) - DayDifference(y, j, 1);
                if (x <= mL || j == 12)
                {
                    m = j;
                    break;
                }
                else
                    x -= mL;
            }
            return 100 * m + x;
        }




        // 返回x的小数尾数,若x为负值,则是1-小数尾数
        private double Tail(double x)
        {
            return x - Math.Floor(x);
        }




        // 返回等效标准天数(y年m月d日相应历种的1年1月1日的等效(即对Gregorian历与Julian历是统一的)天数)
        private double EquivalentStandardDay(int y, int m, int d)
        {
            //Julian的等效标准天数
            double v = (y - 1) * 365 + Math.Floor((double)((y - 1) / 4)) + DayDifference(y, m, d) - 2;


            if (y > 1582)
            {//Gregorian的等效标准天数
                v += -Math.Floor((double)((y - 1) / 100)) + Math.Floor((double)((y - 1) / 400)) + 2;
            }
            return v;
        }




        // 返回阳历y年m月d日的日差天数(在y年年内所走过的天数,如2000年3月1日为61)
        private int DayDifference(int y, int m, int d)
        {
            int ifG = IfGregorian(y, m, d, 1);
            int[] monL = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            if (ifG == 1)
                if ((y % 100 != 0 && y % 4 == 0) || (y % 400 == 0))
                    monL[2] += 1;
                else
                    if (y % 4 == 0)
                        monL[2] += 1;
            int v = 0;
            for (int i = 0; i <= m - 1; i++)
            {
                v += monL[i];
            }
            v += d;
            if (y == 1582)
            {
                if (ifG == 1)
                    v -= 10;
                if (ifG == -1)
                    v = 0;  //infinity 
            }
            return v;
        }




        // 判断y年m月(1,2,..,12,下同)d日是Gregorian历还是Julian历
        //(opt=1,2,3分别表示标准日历,Gregorge历和Julian历),是则返回1,是Julian历则返回0,
        // 若是Gregorge历所删去的那10天则返回-1
        private int IfGregorian(int y, int m, int d, int opt)
        {
            if (opt == 1)
            {
                if (y > 1582 || (y == 1582 && m > 10) || (y == 1582 && m == 10 && d > 14))
                    return (1);     //Gregorian
                else
                    if (y == 1582 && m == 10 && d >= 5 && d <= 14)
                        return (-1);  //空
                    else
                        return (0);  //Julian
            }


            if (opt == 2)
                return (1);     //Gregorian
            if (opt == 3)
                return (0);     //Julian
            return (-1);
        }


        #endregion 节气


        #endregion
    }
    #endregion