近期在做一个工作日历,想在日历上设置工作日,显示请假、加班等相关信息,显示农历日期信息(包括农历日期、节日

、节气)、公历信息(节假期)。

不能不说,http://www.cnblogs.com/hocylan/archive/2007/11/16/961218.html 这篇博文对我的帮助良多。但是

我也发现了一些问题。包括几下3个点:

首先,就是"0100 除夕"这个节日并不能被显示出来,无论是对于农历12月29是一年最后一天,还是12月30是最后一天。

我的解决方法是将这条数据改为"1230 除夕",然后在获取农历节日信息的时候判断这天和下一天的农历日期的年份是否相等,

如果不等,如一个是2012,一个是2013,那么这天就是“除夕”了。

其次,在判断几月的第几周的周几为某个节日时,

if (Convert.ToInt32(s[1]) == month && Convert.ToInt32(s[2]) == num && Convert.ToInt32(s[2]) == week)
这句应该改成:
if (Convert.ToInt32(s[1]) == month && Convert.ToInt32(s[2]) == num && Convert.ToInt32(s[3]) == week)。

博主可能疏忽了。

最后,我想在提到的这篇博文的基础上补充关于24节气的显示。

    节气指二十四时节和气候,是中国古代发明的一种用来指导农事的历法。中国古代利用土圭实测日晷,
将每年日影最长定为日至(又称日长至、长至、夏至),日影最短为日短至(又称短至、冬至),在春秋两季
各有一天的昼夜时间长短相等,便定为春分和秋分,在商朝时只有四个节气,到了周朝时发展到了八个,
直到西汉时才成为了现在的二十四节气。在史记太史公自序中就有提到阴阳、四时、八位、十二度、二十
四节气的概念。
二十四节气每一个分别相应于太阳在黄道上每运动15°所到达的一定位置。二十四节气又分为12个中气
和12个节气,一一相间。二十四节气反映了太阳的周年视运动,所以在公历中它们的日期是基本固定的,
上半年的节气在6日,中气在21日,下半年的节气在8日,中气在23日,二者前后不差1~2日。将一回归年
的长度等分成24份,从冬至开始,等间隔地依次相同安排各个中气和节气。这种方法叫做平气。由于太阳周
年视运动不均匀,按太阳黄经每移行15°的节气是非等间距的,此法称为定气。定气使用于历法计算中。因
为两个节气的时间长于一个朔望月(见月)的时间,所以可能出现一个月内只有一个节气或一个中气的情况。
从西汉的《太初历》起,规定遇到没有中气的月份定为上月的闰月。这种置闰原则沿用至今。
二十四节气的命名反应了季节、气侯现象、气侯变化三种。反应季节的是立春、春分、立夏、夏至、立
秋、秋分、立冬、冬至,又称八位; 反应气侯现象的是惊蛰、清明、小满、芒种; 反应气侯变化的有雨水、
谷雨、小暑、大暑、处暑、白露、寒露、霜降、小雪、大雪、小寒、大寒。
现代人根据太阳在黄道上的位置,准确地确定了二十四节气的具体时间。 节气的具体时间甚至精确到了几时几分,为了避免不同时间点显示的节气不同,我把节气的时间精确到天而已。
代码如下:

/// <summary>
        /// 计算某一年的节气,返回节气
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        private string ComputeSolarTerm(DateTime dt)
        {
            List<string> solar = new List<string>();
            int year = dt.Year;
            for (int month = 1; month < 13; 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;
                    string jqtime = Convert.ToString(new DateTime(year, tMonth, day, hour, minute, 0).ToString("yyyyMMdd")); //这里把节气的日期精确到天
                    string jqname = solarTerm[n - 1];

solar.Add(jqtime+" "+jqname);
                }
            }

string str = @"(\d{4})(\d{2})(\d{2})([\s\*])(.+)$";     //匹配的正则表达式
            System.Text.RegularExpressions.Regex re = new System.Text.RegularExpressions.Regex(str);
            for (int i = 0; i < solar.Count;i++ )
            {
                string[] s = re.Split(solar[i]);
                if (Convert.ToInt32(s[1]) == dt.Year && Convert.ToInt32(s[2]) == dt.Month && Convert.ToInt32(s[3]) == dt.Day)
                {
                    return s[5];
                }
            }
            return "";
        }

#region 节气计算中用到的方法
        /// <summary>
        /// 返回y年第n个节气(如小寒为1)的日差天数值(pd取值真假,分别表示平气和定气)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="n"></param>
        /// <param name="pd"></param>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// 返回阳历y年日差天数为x时所对应的月日数(如y=2000,x=274时,返回1001(表示10月1日,即返回100*m+d))
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// 返回x的小数尾数,若x为负值,则是1-小数尾数
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private double Tail(double x)
        {
            return x - Math.Floor(x);
        }
        /// <summary>
        /// 返回等效标准天数(y年m月d日相应历种的1年1月1日的等效(即对Gregorian历与Julian历是统一的)天数)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="m"></param>
        /// <param name="d"></param>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// 返回阳历y年m月d日的日差天数(在y年年内所走过的天数,如2000年3月1日为61)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="m"></param>
        /// <param name="d"></param>
        /// <returns></returns>
        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

C#日历上显示节气、阴阳历节假日信息的更多相关文章

  1. iOS:实现MKAnnotation协议,在地图上设置大头针,点击显示具体的位置信息

    如何添加大头针(地标): 通过MapView的addAnnotation方法可以添加一个大头针到地图上 通过MapView的addAnnotations方法可以添加多个大头针到地图上 –(void)a ...

  2. win10+Android(华为)系统原生日历同步方案+Sol日历桌面显示

    前言:本文是参考了其他博客基础上,新增了Android的免费桌面[月试图显示]功能.以及适配于上海交通大学的Canvas教学日历.方便进行多设备同步的日历管理.任务提醒. 目录 1.效果展示 2.方案 ...

  3. 某项目 需要在UITabbar 上显示小红点,在此搜罗了三个方法。

    1.使用系统自带的,并且可以在小红点上显示数字. [itemOne setBadgeValue:@""]; //显示不带数字的小红点 [itemOne setBadgeValue: ...

  4. 在饼图上显示百分比值(报表生成器和 SSRS)

    在饼图上显示百分比值(报表生成器和 SSRS) 默认情况下,图例中显示了类别来标识每个值. 如果使用了类别标签标记饼图,则可能希望在图例中显示百分比. 注意 在 SQL Server Data Too ...

  5. 8位灰度图在LCD上显示

    一.概述 1.灰度 灰度使用黑色调表示物体,即用黑色为基准色,不同的饱和度的黑色来显示图像.每个灰度对象都具有从 0%(白色)到灰度条100%(黑色)的亮度值. 使用黑白或灰度扫描仪生成的图像通常以灰 ...

  6. Winform之跨线程访问控件(在进度条上显示字体)

    此文章对于遇到必须使用线程但是没有办法在线程内操作控件的问题的处理  有很好的解决方案(个人认为的.有更好的方案欢迎交流.) 在做跨线程访问之前我们先了解下我们所做的需要达到的效果: 这个是批量的将x ...

  7. 日历上添加活动通知(Asp.net)

    <div id="calendar_contain"> </div> <script language="javascript" ...

  8. 使用Ajax+jQuery来实现前端收到的数据在console上显示+简单的主页设计与bootstrap插件实现图片轮播

    1.实现前端输入的数据在console上显示 上一篇是解决了在前端的输入信息在cygwin上显示,这次要给前台们能看见的数据,因为数据库里插入的数据少,所以写的语句翻来覆去就那几个词,emmm···当 ...

  9. c# Windows Service 桌面上显示UI

    介绍 本文的目的是说明如何从Windows Vista中的服务正确启动交互式进程,以及演示如何以完全管理员权限启动该进程.交互式过程是能够在桌面上显示UI的过程. 本文介绍如何创建一个名为Loader ...

随机推荐

  1. Rx 入门 示例

    首先写一个观察者模式 public interface Watcher { public void update(String str); } public class ConcreteWatcher ...

  2. 【转】Java学习之Iterator(迭代器)的一般用法 (转)

    [转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...

  3. ExtJs的事件机制Event(学员总结)

    一.事件的三种绑定方式 1.HTML/DHTML 在标签中直接增加属性触发事件 [javascript] view plaincopy <script type="text/javas ...

  4. 更改tabBarItem图片的问题

    代码: UIImage *normal = [[UIImage imageNamed:@"tabbar_home_default"] imageWithRenderingMode: ...

  5. PS纯手式打造不规则颜色的规则方块—学习教程

  6. inline-block(行内区块元素)的详解和应用

    说inline-block(行内区块元素)之前,先说下他另外的2个兄弟 display:inline; 内联元素,简单来说就是在同一行显示.他没有高度,给内联元素设置width和height是没效果的 ...

  7. grails&groovy的IllegalArgument异常

    我在开发的过程中遇到了这样一个异常,总是提示IllegalArgument异常,代码大致如下: if(haomgl.save(flush:true)){ //更新库存:状态为2的位置存煤 def cu ...

  8. getUrlParam,jQuery中的URL参数获取

    大家经常会需要在一段URL中截取到自己所需参数的值,下面的方法也许能帮到您: $.getUrlParam = function(name){ var reg = new RegExp("(^ ...

  9. [PHP学习日志]简单Session的使用

    首先,给出一些Session的解释:目前最实用的网络协议即HTTP超文本传输协议,它是“无状态”的,所谓“无状态”是指它在用户与服务器交互时没有存储需要交互的“状态”.而Session 是在网络应用中 ...

  10. python运维开发之第三天

    一.第二天课程的复习总结 1.列表可以增删改查,元组是不可修改的列表,字符串是不可以修改的. 2.列表,元组是有序的,字典是无序的,字典的key唯一 3.列表字典可以嵌套列表,可以嵌套字典,可以嵌套多 ...