为了账号安全,请及时绑定邮箱和手机立即绑定

看到百度的那个万年历了吗,咱们也来做一个吧。(代码篇)

原创声明,转载请注明出处。
咱先来看看具体效果吧,
https://dorsey.oss-cn-hangzhou.aliyuncs.com/PC/module/module/calendar.html`
具体的说明呢,请看这:原理介绍
这里只有代码
html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>万年历(带农历)</title>
    <link rel="stylesheet" href="../dist/dorsey-ui.css">
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../dist/jquery-3.3.1.min.js" type="text/javascript"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../dist/dorsey-ui.js" type="text/javascript"></script>
    <style>
        body{background:linear-gradient(to left, #56655f, #000000);}
        .dc_calendar{
            width:500px;
            height:430px;
            margin:50px auto 0;
            color:#ccc;
        }
    </style>
    <script>
        $(function(){
            dorseyUI.dcCalendar($('.dcCalendarAddLunar'));
            /*万年历*/
            // dorseyUI.dcCalendar($('#dcCalendar'));
        });
    </script>
</head>
<body>
<!--<div class="calendar"></div>-->

<div class="dc_calendar">
    <div class="dcCalendarAddLunar" id="dcCalendar"></div>
</div>
</body>
</html>

css

html,body,div,ol,ul,li,p,h1,h2,h3,h4,h5,h6,table,tr,td,dt,dd,span,img{margin:0;padding:0}ul,li{list-style:none}a{text-decoration:none}.dc_left{float:left}.dc_right{float:right}.dc_pointer{cursor:pointer}.dc_clear{content:"";display:block;clear:both}.dc_mar_bottom{margin-bottom:20px}.dc_p_center{position:absolute;top:0;bottom:0;left:0;right:0;margin:auto}.dc_c_red{color:#f00}.dc_c_aaa{color:#aaa}.dcCalendar{width:100%;height:100%;min-height:230px;padding:10px;box-sizing:border-box;position:relative;box-shadow:-2px 2px 10px #fff;-webkit-box-shadow:-2px 2px 10px #fff;-moz-box-shadow:-2px 2px 10px #fff;-o-box-shadow:-2px 2px 10px #fff}.dcCalendar .calendarBtn{width:100%;height:20%}.dcCalendar .calendarBtn .dcCalendarValues{width:50%;height:3em;box-shadow:-2px 2px 10px #fff;-webkit-box-shadow:-2px 2px 10px #fff;-moz-box-shadow:-2px 2px 10px #fff;-o-box-shadow:-2px 2px 10px #fff;float:left;font-size:1em;border-radius:1.5em 1.5em 1.5em 1.5em;-webkit-border-radius:1.5em 1.5em 1.5em 1.5em;-moz-border-radius:1.5em 1.5em 1.5em 1.5em;text-align:center;line-height:3em}.dcCalendar .calendarBtn .mBtn,.dcCalendar .calendarBtn .yBtn{text-align:center;float:left;border-radius:50% 50% 50% 50%;-webkit-border-radius:50% 50% 50% 50%;-moz-border-radius:50% 50% 50% 50%;font-size:1em;box-shadow:-1px 1px 2px #fff;-webkit-box-shadow:-1px 1px 2px #fff;-moz-box-shadow:-1px 1px 2px #fff;-o-box-shadow:-1px 1px 2px #fff;cursor:pointer;margin:0 .5%}.dcCalendar .calendarBtn .yBtn{width:13%;height:3em;line-height:3em}.dcCalendar .calendarBtn .mBtn{width:10%;height:2em;line-height:2em;margin-top:.5em}.dcCalendar .calendarTable{width:100%;height:75%;margin-top:5%;padding:10px;box-sizing:border-box;text-align:center}.dcCalendar .calendarTable th{text-align:center}.dcCalendar .calendarTable td{cursor:pointer;transition:.1s}.dcCalendar .dcDateDetail{display:none;width:150px;height:80px;font:1em "Times New Roman";padding:5px;position:absolute;top:0;left:0;background:rgba(0,0,0,0.9)}.dcCalendarAddLunar{width:100%;height:100%;min-height:230px;padding:10px 0;box-sizing:border-box;position:relative;box-shadow:-2px 2px 10px #fff;-webkit-box-shadow:-2px 2px 10px #fff;-moz-box-shadow:-2px 2px 10px #fff;-o-box-shadow:-2px 2px 10px #fff;border-radius:5px 5px 5px 5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px}.dcCalendarAddLunar .calendarBtn{width:100%;padding:0 2%;box-sizing:border-box}.dcCalendarAddLunar .calendarBtn .dcCalendarValues{width:50%;height:3em;float:left;font-size:1em;text-align:center;line-height:3em}.dcCalendarAddLunar .calendarBtn .mBtn,.dcCalendarAddLunar .calendarBtn .yBtn{text-align:center;float:left;border-radius:50% 50% 50% 50%;-webkit-border-radius:50% 50% 50% 50%;-moz-border-radius:50% 50% 50% 50%;font-size:1em;box-shadow:-1px 1px 2px #fff;-webkit-box-shadow:-1px 1px 2px #fff;-moz-box-shadow:-1px 1px 2px #fff;-o-box-shadow:-1px 1px 2px #fff;cursor:pointer;margin:0 .5%}.dcCalendarAddLunar .calendarBtn .yBtn{width:13%;height:3em;line-height:3em}.dcCalendarAddLunar .calendarBtn .mBtn{width:10%;height:2em;line-height:2em;margin-top:.5em}.dcCalendarAddLunar .calendarBtn:after{content:"";display:block;clear:both}.dcCalendarAddLunar .calendarTable{width:100%;margin-top:10px;padding:10px;box-sizing:border-box;text-align:center}.dcCalendarAddLunar .calendarTable th{text-align:center}.dcCalendarAddLunar .calendarTable td{cursor:pointer;transition:.1s;padding:5px 0}.dcCalendarAddLunar .calendarTable td p{font-size:.3rem}.dcCalendarAddLunar .calendarTable td .solarValue{font-size:20px}.dcCalendarAddLunar .calendarTable td .lMonth{display:none}.dcCalendarAddLunar .dcDateDetail{display:none;width:150px;height:80px;font:1em "Times New Roman";padding:5px;position:absolute;top:0;left:0;background:rgba(0,0,0,0.9)}.calendarMouseMove{box-shadow:-1px 1px 5px #fff;-webkit-box-shadow:-1px 1px 5px #fff;-moz-box-shadow:-1px 1px 5px #fff;-o-box-shadow:-1px 1px 5px #fff;transform:translate3d(2px, -2px, 0)}.dcCalendar:after{content:"";display:block;clear:both}.dcAccordion{background:linear-gradient(#1d1d1d, #35ff10);width:100%;text-align:center;font:18px "华文楷体";line-height:40px}.dcAccordion a{width:100%;display:inline-block;color:#fff}.dcAccordion li ul{font:12px "微软雅黑";line-height:30px;height:0;overflow:hidden;background:rgba(255,255,255,0.2);transition:all .3s}.dcAccordion a:hover{background:rgba(255,255,255,0.3)}.dcAccordionAddAnimate{background:linear-gradient(#1d1d1d, #35ff10);width:100%;text-align:center;font:18px "华文楷体";line-height:40px}.dcAccordionAddAnimate a{width:100%;display:inline-block;color:#fff}.dcAccordionAddAnimate li ul{font:12px "微软雅黑";line-height:30px;height:0;overflow:hidden;background:rgba(255,255,255,0.2);transition:all .3s}.dcAccordionAddAnimate a:hover{background:rgba(255,255,255,0.3)}

js

/**
 * @author-dorseyCh  1092240376@qq.com;
 * @my-personal-card  Chasing Dream.
 * I'm from China,I love my country and our mother language,so all of my functions explain were use Chinese!
 * */
;(function(win){ //前面这分号别去掉哦,防止多个js文件合并压缩时因上一个js文件末尾少";"而带来的问题。

    "use strict"; //严格模式,一般写自己类库的时候最好加上,减少一些代码不规范引起的错误。

    /**
     * 模块说明:dorseyUI作为一切处理函数的入口,需要注意的是部分函数调用到dorseyHf函数处理,故而需要引入dorsey-handle-function文件,
     *           且该文件的位置需要放置在dorsey-ui.js之前。
     * */
    var dc_self;
    var dorseyUI=function(){
        return new dorseyUI.fn.init();
    };
    dorseyUI.fn=dorseyUI.prototype={
        constructor:dorseyUI, //接口名:是dorsey-ui的缩写。意为函数处理
        init:function(){
            dc_self=this;
            return this;
        },
        /*组件1、万年历*/
        dcCalendar:function(obj){
            /**
             *  创建日历对象
             * */
            var calendar = {
                /**
                 *  农历数据
                 * */
                lunarData : [
                    0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909
                    0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919
                    0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929
                    0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939
                    0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949
                    0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959
                    0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969
                    0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979
                    0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989
                    0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,//1990-1999
                    0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009
                    0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019
                    0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029
                    0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039
                    0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049
                    0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50,0x06b20,0x1a6c4,0x0aae0,//2050-2059
                    0x0a2e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069
                    0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079
                    0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089
                    0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099
                    0x0d520],//2100
                /**
                 *  二十四节气数据
                 * */
                sTermDate :[
                    0,21208,42467,63836,85337,107014,
                    128867,150921,173149,195551,218072,240693,
                    263343,285989,308563,331033,353350,375494,
                    397447,419210,440795,462224,483532,504758
                ],
                /**
                 *  二十四节气——中文
                 * */
                sTermChinese :[
                    "立春","雨水","惊蛰","春分","清明","谷雨",
                    "立夏","小满","芒种","夏至","小暑","大暑",
                    "立秋","处暑","白露","秋分","寒露","霜降",
                    "立冬","小雪","大雪","冬至","小寒","大寒"
                ],
                /**
                 *  阳历节日对象——中文
                 * */
                festivalChinese : {
                    //第一季度
                    "0101":"元旦",
                    "0214":"情人节",
                    "0308":"妇女节",
                    "0312":"植树节",
                    "0315":"消费者权益日",
                    "0321":"世界森林日、世界儿歌日",

                    //第二季度
                    "0401":"愚人节",
                    "0407":"世界卫生日",
                    "0422":"世界地球日",
                    "0501":"劳动节",
                    "0504":"青年节",
                    "0505":"碘缺乏病防治日",
                    "0508":"世界红十字日",
                    "0512":"国际护士节",
                    "0515":"国际家庭日",
                    "0517":"世界电信日",
                    "0518":"国际博物馆日",
                    "0520":"520情人节",
                    "0523":"国际牛奶日",
                    "0531":"世界无烟日",
                    "0601":"儿童节",
                    "0605":"世界环境日",
                    "0606":"全国爱眼日",
                    "0616":"防治荒漠化和干旱日",
                    "0623":"国际奥林匹克日",
                    "0625":"全国土地日",
                    "0626":"国际反毒品日",

                    //第三季度
                    "0701":"建党节 香港回归纪念 国际建筑日",
                    "0707":"中国人民抗日战争纪念日",
                    "0711":"世界人口日",
                    "0801":"建军节",
                    "0908":"国际扫盲日",
                    "0909":"毛泽东逝世纪念",
                    "0910":"教师节",
                    "0916":"国际臭氧层保护日",
                    "0920":"国际爱牙日",
                    "0927":"世界旅游日",
                    "0928":"孔子诞辰",

                    //第四季度
                    "1001":"国庆节 国际音乐日",
                    "1004":"世界动物日",
                    "1006":"老人节",
                    "1008":"全国高血压日 世界视觉日",
                    "1009":"世界邮政日",
                    "1015":"国际盲人节",
                    "1016":"世界粮食日",
                    "1017":"世界消除贫困日",
                    "1024":"联合国日",
                    "1108":"中国记者日",
                    "1109":"消防宣传日",
                    "1112":"孙中山诞辰纪念",
                    "1114":"世界糖尿病日",
                    "1117":"国际大学生节",
                    "1201":"世界艾滋病日",
                    "1203":"世界残疾人日",
                    "1209":"世界足球日",
                    "1220":"澳门回归纪念",
                    "1225":"圣诞节",
                    "1226":"毛泽东诞辰纪念",
                    "1229":"国际生物多样性日"
                },
                /**
                 *  农历节日对象——中文
                 * */
                lFestivalChinese : {
                    "0101" : "春节",
                    "0202" : "头牙",
                    "0115" : "元宵节",
                    "0505" : "端午节",
                    "0707" : "七巧节",
                    "0715" : "中元节",
                    "0815" : "中秋节",
                    "0909" : "重阳节",
                    "1208" : "腊八节",
                    "1216" : "尾牙",
                    "1223" : "小年",
                    "0100" : "除夕"
                },
                /**
                 *  农历日十位
                 * */
                lDecade : ["初","十","廿","三"],
                /**
                 *  农历日各位
                 * */
                lDate : ["一","二","三","四","五","六","七","八","九","十"],
                /**
                 *  农历月
                 * */
                lMonthArr : ["正","二","三","四","五","六","七","八","九","十","冬","腊"],
                /**
                 *  十天干
                 * */
                heavenlyStems : ["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"],
                /**
                 *  十二地支:分别对应十二时辰
                 * */
                terrestrialBranch : ["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"],
                /**
                 *  十二生肖
                 * */
                animals : ["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"],
                /**
                 *  用一个函数继承下时间函数
                 * */
                dateFunction : function(){
                    return new Date();
                },
                /**
                 *  返回当前时间数组
                 *  @example:console.log(this.thisTime()); //当前时间函数
                 * */
                thisTime : function(){
                    var _self = this;
                    var year = _self.dateFunction().getFullYear(),//获取年
                        month = _self.dateFunction().getMonth(),//获取月
                        today = _self.dateFunction().getDate(),//获取日
                        weekNum = _self.dateFunction().getDay(),//获取星期
                        hour = _self.dateFunction().getHours(),//获取小时
                        minute = _self.dateFunction().getMinutes(),//获取分钟
                        second = _self.dateFunction().getSeconds();//获取秒
                    return [year,month,today,weekNum,hour,minute,second]; //返回所需数据
                },
                /**
                 *  公历(阳历)相关函数
                 *
                 *  1、返回该年是否是闰年,是返回1,不是返回0
                 *  @example:console.log(this.isLeapYear(2100));//0
                 * */
                isLeapYear : function(year){
                    var flag;
                    year%4===0?(year%100!==0?flag=1:(year%400===0?flag=1:flag=0)):flag=0;//闰年处理
                    return flag;
                },
                monthDates : function(y){
                    return [31,28+this.isLeapYear(y),31,30,31,30,31,31,30,31,30,31];
                },
                week : ['日','一','二','三','四','五','六'],
                /**
                 *  农历(阴历)相关函数
                 *
                 *  1、解析农历数据,返回一个二进制对象
                 * */
                lunarTran : function(y){

                    var lunarData=this.lunarData[y-1900];

                    var hexadecimal=lunarData.toString(16),
                        head=Math.floor(lunarData/65536).toString(2), //头部说明闰月是大月还是小月
                        center=Math.floor((lunarData%65536)/16).toString(2),//中部说明哪个月是大月哪个是小月的二进制数
                        end=lunarData%16; //尾部说明哪个月是闰月,没有闰月则为0
                    //字符串补全处理
                    if(center.length < 12){
                        var i = 12-center.length;
                        while(i--){
                            center = "0"+center;
                        }
                    }
                    hexadecimal.length !== 5 ? hexadecimal="0x0"+hexadecimal : hexadecimal="0x"+hexadecimal;//16进制数
                    var bigMonthNum=(center+head).match(new RegExp('1','g')).length,//输出大月个数
                        monthDetail=center.split(''); //把二进制整合成一个数组

                    end !== 0 ? monthDetail.splice(end,0,head) : end ; //把尾部是否为闰月的月份插回去

                    var everyMonthDays = []; //用于输出每一年所有月份的天数,包括闰月
                    for(var i=0;i<monthDetail.length;i++){
                        if(monthDetail[i] === "1"){
                            everyMonthDays.push(30);
                        }
                        else{
                            everyMonthDays.push(29);
                        }
                    }
                    return {
                        thisYear : y,   //这一年是哪一年
                        lunarData : hexadecimal, //该年的农历数据,16进制的数据,即我们上面那个数据表,如:ox04bd8
                        isBigLeadMonth : parseInt(head), //头部数据,表示闰月是否为大月,是为1,否为0,没有闰月则返回0
                        monthBinaryData : center, //中部数据,2进制数据,为除了闰月其他1-12月的月份是否为大月,如:010010111101 表示1月是29天,2月是30天,依次类推
                        monthDetail : monthDetail, //月份详情,返回一个数组,若有闰月则自动添加进对应的月份之后。
                        everyMonthDays : everyMonthDays, //返回一年中所有月份的天数包括闰月
                        bigMonthNum : bigMonthNum, //这一年里大月(30天)的数量
                        whichIsLeadMonth : end //尾部数据,返回若是闰月,是哪个月为闰月
                    };
                },
                /*
                * 2、输入一个数,返回农历值,比如:输入 19 返回 廿十 ,输入0 返回初一
                * @example: console.log(this.numToLunar(19)) //"廿十"
                * */
                numToLunar : function(num){
                    var _self = this,
                        num1 = num;
                    num1 === 9? num1-=1:null; //由于输入9的时候显示是十十,这里做点小修正,下面有个test函数可以测试
                    return _self.lDecade[Math.floor((num1+1)/10)]+_self.lDate[(num)%10];
                },
                /**
                 *  3、解析农历数据,返回某一年的总农历天数
                 *  @example : console.log(this.daysInYear(1900)); //384
                 * */
                daysInYear : function(y){
                    var obj = this.lunarTran(y);
                    return obj.monthDetail.length*29+obj.bigMonthNum;
                },
                /**
                 *  4、解析农历数据,返回某一年某一月总农历天数
                 *     闰年多出的那一个月这里暂时不管,因为上面已有一个封好的对象,到时转化时直接调用即可
                 *  @example:console.log(this.daysInMonth(2018,7)); //30//代表2018年农历7月份有30天
                 * */
                daysInMonth : function(y,m){
                    return (this.lunarData[y-1900] & (0x10000 >> (m+1))) ? 30 : 29;
                },
                /**
                 *  5、返回任意月上个月的农历天数,包括上一年的闰12月也都可以,当然了,一年里两个12月的上面的数据好像是没有的,不过呢
                 *     这种情况咱还是要考虑进去哈,既然是程序公式嘛肯定得通用,考虑所有可能出现的情况。
                 *     为什么要做这个?因为我们后面得到的偏移量有正也有负,正值好办,但负值我们需要知道上个月的天数
                 *
                 *     console.log("本月:"+this.daysInPreMonth(2078,1)); //这两者的返回值相同 这里的2078,1是指2078年第一个农历月
                 *     console.log("上个月:"+this.daysInMonth(2077,12)); //这里跟上面的也是一样的
                 * */
                daysInPreMonth : function(y,m){
                    var _self = this,
                        obj = _self.lunarTran(y);  //获取今年日历对象
                    var days;

                    //分两种情况进行讨论,上个月在今年跟上个月在上一年
                    if(m > 0){
                        if(obj.isBigLeadMonth === "1" && m === obj.whichIsLeadMonth+1){ //如果该年是闰年且m为闰年后第一个月,则
                            return (obj.isBigLeadMonth === 0 ? 29 : 30);
                        }
                        else {
                            return _self.daysInMonth(y,m-1);
                        }
                    }
                    else{
                        var objPre = _self.lunarTran(y-1); //获取上一年日历对象
                        return objPre.everyMonthDays[objPre.everyMonthDays.length-1];
                    }
                    //上面的比较啰嗦,这是简化版,你把这里注释掉用上面的也是可以哈,相对比较直观明了。
                    // m > 0 ? ((obj.isBigLeadMonth === "1" && m === obj.whichIsLeadMonth+1)? days =(obj.isBigLeadMonth === 0 ? 29 : 30) :
                    //     days =_self.daysInMonth(y,m-1)) : days = objPre.everyMonthDays[objPre.everyMonthDays.length-1];
                    //
                    // return days;
                },
                /**
                 *  6、通过1900年1月31日确定公历每年的第一天也就是xx年1月1日的农历偏移量
                 *  @example :
                 *  for(var i = 1900;i<2100;i++){
                 *      console.log(this.lFirstDayInEveryYears(i));
                 *  }
                 * */
                lFirstDayInEveryYears : function(y){
                    var _self = this;
                    //我们需要计算任意一天距离1900年1月31日的偏移量,单位(天);
                    var baseDate =new Date(1900,0,31).getTime(),
                        offset = Math.floor((new Date(y,0,1).getTime()-baseDate)/86400000),//计算偏移量
                        mOffset=2;//月份偏移量:比如说1月1号是落在农历的11月份还是12月份
                    if(y === 1900){
                        offset = 0;
                        mOffset = 1;
                    }
                    else{
                        for(var i=1900;i<y;i++){
                            offset -= _self.daysInYear(i);
                        }
                        /**
                         *  这里呢,为了简化算法,咱用了点取巧的方式,我们通过查询万年历可以得知农历的正月初一不会出现在元旦(1月1号)之前,
                         * */
                        //也不会出现在3月之后,这就给我们的算法提供了方便,当然啦,其实这种方式呢我虽然这么做了,但我个人的鄙视的= =,假如
                        // 说农历的正月初一出现在三月或者春节之前,那我们这算法就废了,当然了,这种情况不可能。
                        if(offset < 0){
                            // //这里呢,咱防一手闰12月的哈,实际上是没有这个可能的,不过这样的程序看起来比较严谨一点
                            if((_self.lunarTran(y).lunarData & 0x0000c) === 12){
                                // console.log("if-if,my name is ChenDuoXin,my English name is dorseyCh.");
                                offset += (_self.daysInPreMonth(y,0)+_self.daysInMonth(y-1,11));
                            }
                            else{
                                offset += _self.daysInPreMonth(y,0);
                                offset < 0 ? offset += _self.daysInPreMonth(y-1,11): mOffset=1;
                            }
                        }
                    }
                    return {
                        thisYear : y,
                        offset : offset,
                        mOffset : mOffset
                    };
                },
                /**
                 *  7、输入y年m月,输出这个月1号的偏移量,或者说是农历值(阳历转农历)
                 *
                 *  1900年1月31日正好对应农历的正月初一。
                 *
                 *  输入y年m月,输出这个月1号的偏移量,或者说是农历值,思路非常简单,到这一步的时候我们知道什么呢?
                 *  知道每一年1月1号所对应的农历值对吧?然后要到每一个月,但是呢,阳历的月份跟农历的月份天数是不对应的,所以还
                 *  需要做下面的事:
                 *      1、计算当前阳历时间距离同年1月1号的天数间隔
                 *      2、我们知道每一年1月1号这一天是已经跟农历对照好了的。
                 *      3、知道了这个间隔,那我们就可以推出:过了这个间隔之后,农历的偏移量做了多少的改变
                 * */
                solarToLunar : function(y,m){

                    var _self = this;
                    // console.log(y+"年"+(m+1)+"月1日");
                    //年份的我们可以不用管,但月份的需要知道一个,什么呢?就是你想输入的那个月的前面的月份可能会有包含一个闰月
                    var offsetObj =  _self.lFirstDayInEveryYears(y),//获取当年阳历1月1号所对应的农历值,包括日偏移与月偏移
                        obj = _self.lunarTran(y),
                        monthDates = this.monthDates(y),
                        offset=offsetObj.offset;
                    //计算每个月1号的偏移量
                    if(y === 1900){
                        for(var i=0;i<m;i++){
                            i < 1 ? offset +=monthDates[i]-30 : offset += monthDates[i]-obj.everyMonthDays[i-1];
                        }
                    }
                    else{
                        var objPre = _self.lunarTran(y-1);
                        for(var i=0;i<m;i++){
                            if(i<offsetObj.mOffset){
                                offset += (monthDates[i]-objPre.everyMonthDays[objPre.everyMonthDays.length-1-i]);
                            }
                            else{
                                offset += (monthDates[i]-obj.everyMonthDays[i-offsetObj.mOffset]);
                            }
                        }
                    }
                    return [offset,offsetObj.mOffset];
                },
                /**
                 *  8、通过世界时以及节气年返回year年第n个节气所对应为该月第几天
                 *  31556925974.7:是一个节气年,24个节气合起来总计多少ms。
                 *  Date.UTC(1900,0,6,2,5):1900年1月6日2时5分为小寒节气开始,从这里开始,记得是以小寒开始,且历法的精确度仅仅到分钟
                 *  @example : console.log(this.sTermToDate(2018, 2)); //2018立春是月份的4号,打印出了4
                 **/
                sTermToDate : function(year,n){
                    var offDate = new Date( ( 31556925974.7*(year-1900) + this.sTermDate[n]*60000 )
                        + Date.UTC(1900,0,6,2,5) );
                    return(offDate.getUTCDate());
                },

                /**
                 *  测试函数
                 * */
                test : function(){

                    console.log(this.thisTime()); //当前时间函数

                    /**
                     *  公历相关
                     * */
                    // console.log(this.isLeapYear(2100)); //判断该年是否是闰年

                    /**
                     *  农历相关
                     * */
                    // console.log(this.numToLunar(19)); //数据转农历中文日期
                    // console.log(this.lunarTran(2017)); //农历数据解析函数,返回一个二进制对象
                    // console.log(this.daysInYear(1900)); //返回该年的农历总天数
                    // console.log(this.sTermToDate(2018, 2)); //2018立春是月份的4号,打印出了4
                    // for(var i = 1900;i<2100;i++){  //返回每一年1月1号的偏移量
                    //     console.log(this.lFirstDayInEveryYears(i));
                    // }
                    // this.solarToLunar(2017,3); //初五
                    // this.solarToLunar(1900,3);//1900比较特殊因为它是最前面,没有上一年
                    // for(var i=0;i<12;i++){
                    //     console.log(this.solarToLunar(2018, i));
                    // }
                    // console.log("本月1:"+this.daysInPreMonth(2017,0));
                    // console.log("本月2:"+this.daysInPreMonth(2017,0)+"上个月1:"+this.daysInMonth(2016,12));
                }
            };
            // calendar.test();
            /**
             *  日历开始
             * */

            var thisTime=calendar.thisTime(),
                rel,detailX,detailY,
                year = thisTime[0],
                month = thisTime[1],
                today = thisTime[2],
                weekNum = thisTime[3],
                week = calendar.week,
                monthDates = calendar.monthDates(year),
                lMonthArr = calendar.lMonthArr;
            /*==============================@start js日期表格创建=======================================*/
            //放置上层按钮及日期显示
            var btn=$('<div class="calendarBtn">' +
                '<span class="yBtn">-</span>' +
                '<span class="mBtn">-</span>' +
                '<div class="dcCalendarValues">'+year+'年'+(month+1)+'月'+today+'日 <span>星期'+week[weekNum]+'</span></div>'+
                '<span class="mBtn">+</span>' +
                '<span class="yBtn">+</span>' +
                '</div>');
            obj.append(btn);
            /*放在下层的日历*/
            var table=$('<table class="calendarTable"><thead><tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr></thead>' +
                '<tbody class="calendarTbody">' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>' +
                '</tbody></table>');
            obj.append(table);
            obj.append($('<div class="dcDateDetail"></div>'));
            /*==============================@end js日期表格创建=======================================*/
            var $tBody=$('.calendarTbody'),//万年历每张日历表的容器<tbody></tbody>
                $dateDetail=$('.dcDateDetail'),//每个日期对应的详情页,显示农历节日等等
                $CalendarValues=$('.dcCalendarValues');//日历上方当前日期简介
            /*更新函数,即无论是点击还是查看,页面的html重新写入都用这个函数*/
            var update=function(){
                var firstDay=new Date(year,month,1),//获取每个月的第一天
                    dayOfWeek=firstDay.getDay();//这个月第一天的世界时去转换成星期几

                var arr=calendar.solarToLunar(year,month);
                    // lMonth = month-arr[1]; //农历的月份

                $tBody.find('td').css("color","").css("opacity","");//清空原有样式
                for(var j=0;j<6;j++){
                    for(var i=0;i<7;i++){
                        rel=j*7+i-dayOfWeek+1;//rel就是原本的1~42,减掉第一天对应的星期数再后续做判断
                        if(rel<=0){
                            var month0=month-1;
                            month0<0?month0=11:month0;
                            $tBody.find('tr').eq(j).find('td').eq(i).html(rel+monthDates[month0]).css("opacity","0.3");
                        }
                        else if(rel>monthDates[month]){
                            $tBody.find('tr').eq(j).find('td').eq(i).html(rel-monthDates[month]).css("opacity","0.3");
                        }
                        else{
                            // // 1对应农历十八,这部分的算法非常的渣,不过呢,写到这我已经有点精疲力尽了,让我歇会吧。

                            var a=rel+arr[0]-1;
                            var m=month-arr[1]+1,
                                y=year;
                            if(m<0){
                                m+=12;
                                y--;
                            }
                            a%=calendar.daysInPreMonth(y,m);
                            var b=calendar.numToLunar(a);
                            // lMonth < 0 ? lMonth +=calendar.lunarTran(year).everyMonthDays.length : lMonth;
                            // lMonth %= calendar.lunarTran(year).everyMonthDays.length;
                            $tBody.find('tr').eq(j).find('td').eq(i).html("<p class='solarValue'>"+rel+"</p>"+"<p>"+b+"</p>");

                            if(rel===thisTime[2]&&year===thisTime[0]&&month===thisTime[1]){
                                $tBody.find('tr').eq(j).find('td').eq(i).css("color","red");
                            }
                        }
                    }
                }
                $CalendarValues.html(year+'年'+(month+1)+'月'+today+'日 <span class="weekAdapt">星期'+week[weekNum]+'</span>');//每次更新重写日期简介
            };
            update();//初始化
            /*4个按钮功能函数*/
            $('.calendarBtn span').click(function(){
                // console.log($(this).index());
                switch($(this).index()){
                    case 0 : year-=1;break;
                    case 1 : {
                        month-=1;
                        if(month<0){month=11;year-=1;}
                        break;
                    }
                    case 3 : {
                        month+=1;
                        if(month>11){month=0;year+=1;}
                        break;
                    }
                    case 4: year+=1;break;
                }
                update();
            });
            /*鼠标移入显示详情,移出隐藏详情*/
            $tBody.mouseover(function(){
                $dateDetail.css("display","block");
            });
            $tBody.mouseout(function(){
                $dateDetail.css("display","none");
            });
            /*每一天鼠标滑动显示详情*/
            $tBody.find('td').each(function(){
                $(this).mousemove(function(e){
                    e=e||window.event;
                    detailX=e.pageX-$tBody.offset().left;
                    detailY=e.pageY-obj.offset().top;
                    $dateDetail.css({
                        left:(detailX+30)+"px",
                        top:(detailY)+"px"
                    });
                    if($(this).css("opacity")==="1"){
                        $CalendarValues.html(year+'年'+(month+1)+'月'+$(this).children('.solarValue').html()+'日 <span class="weekAdapt">星期'+week[$(this).index()%7]+'</span>');
                        $tBody.find('td').removeClass('calendarMouseMove');
                        $(this).addClass('calendarMouseMove');
                        /*================@start 阳历节日嵌入===============*/
                        var festivalDate;//阳历节日变量
                        var fm=month+1,
                            dm=$(this).children('.solarValue').html();
                        fm<10?fm="0"+fm:fm;
                        dm<10?dm="0"+dm:dm;
                        if(calendar.festivalChinese[fm+dm]!==undefined){
                            festivalDate=calendar.festivalChinese[fm+dm];
                        }
                        else{
                            festivalDate="";
                        }
                        /*================@end 阳历节日嵌入===============*/
                        $dateDetail.html($CalendarValues.html()+"<p>"+festivalDate+"</p>");

                    }
                });
            });

            /*自适应判定*/
            if(obj.width()<270){
                obj.css("font-size","5px");
                obj.find(".dcCalendarValues").find('span').css("display","none");
            }
        }
    };
    dorseyUI=dorseyUI.fn.init.fn=dorseyUI.fn;
    win.dorseyUI=dorseyUI;
})(window);
点击查看更多内容
13人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
1.3万
获赞与收藏
1519

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消