原创声明,转载请注明出处。
咱先来看看具体效果吧,
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 src="../dist/jquery-3.3.1.min.js" type="text/javascript"></script>
<script src="../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);