这几天闲来无聊,就自己做了一个Js版本的农历日历,由于Js的日期是从1970年1月1日开始计时的以偏移量来计算周期的,所以日历就暂时只支持1970年以后的日期。另外查询了一下农历日期的计算方法,发现没有数学模型和公式可循,只能以古历的不规则数组进行提取换算,所以就保存了1970到2050范围内的转换参数,日历支持的上限就就到2050年为止。
效果图如下:
源码如下:
/***************************************** calendar data range from 1900 to 2050 which also is the calendar's limit boundary. *****************************************/ var lunarInfo=new Array( 0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0, 0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,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); var monthName_ch = new Array('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'); var day_of_month = new Array(31,28,31,30,31,30,31,31,30,31,30,31); var lunarDay = new Array('初一','初二','初三','初四','初五','初六','初七','初八','初九','初十','十一','十二','十三','十四','十五','十六','十七','十八','十九', '二十','二十一','二十二','二十三','二十四','二十五','二十六','二十七','二十八','二十九','三十'); var festival = {'1-1':'元旦','2-14':'情人节','3-5':'雷锋纪念日','3-8':'妇女节','3-15':'消费者日','4-1':'愚人节','4-5':'清明节','5-1':'劳动节','6-1':'儿童节','8-1':'建军节','9-10':'教师节','10-1':'国庆节','12-25':'圣诞节'}; var lFestival = {'1-1':'春节','1-15':'元宵节','5-5':'端午节','7-7':'七夕','8-15':'中秋节','9-9':'重阳节','12-8':'腊八','12-30':'除夕'} var currentYear; var currentMonth; var currentDayIndex; function getEl(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements; } element = document.getElementById(element); return element; } function checkLeap(y){ if(y%400==0) return true; else if(y%4==0&&y%100!=0) return true; return false; } /** * @param year * @return how many days in param year **/ function lYearDays(y) { var i, sum=348; for(i=0x8000;i>0x8;i>>=1) sum+=(lunarInfo[y-1900]&i)?1:0; return (sum+leapDays(y)); } /** * @param year * @return number of leap month days of param year **/ function leapDays(y) { if(leapMonth(y)) return ((lunarInfo[y-1900]&0x10000)?30:29); else return 0; } /** * @param year * @return leap month of param year, return 0 if none **/ function leapMonth(y) { return (lunarInfo[y-1900]&0xf); } /** * @param month * @return number of days in param year/month **/ function monthDays(y,m) { return ((lunarInfo[y-1900]&(0x10000>>m))?30:29 ); } /** * constructor of Lunar object * @param current date * @return Lunar with lYear/lMonth/lDay **/ function Lunar(objDate) { var i, leap=0, temp=0; var baseDate = new Date(1900,0,31); var offset = (objDate - baseDate)/86400000; this.nMonth = objDate.getMonth()+1; this.nDay = objDate.getDate(); for(i=1900; i<2050 && offset>0; i++) { temp = lYearDays(i); offset -= temp; } if(offset<0) { offset += temp; i--; } this.year = i; leap = leapMonth(i); //which month leap this.isLeap = false; for(i=1; i<13 && offset>0; i++) { //if leap month if(leap>0 && i==(leap+1) && this.isLeap==false){ --i; this.isLeap = true; temp = leapDays(this.year); }else temp = monthDays(this.year, i); //cancel leap if(this.isLeap==true && i==(leap+1)) this.isLeap = false; offset -= temp; }//end of for if(offset==0 && leap>0 && i==leap+1) if(this.isLeap) this.isLeap = false; else{ this.isLeap = true; --i; } if(offset<0){ offset += temp; --i; } this.month = i; this.day = offset + 1; } /******************* * GUI js core *******************/ function initCal(){ initStyle(); var t = new Date(); currentYear = t.getYear(); currentMonth = t.getMonth(); currentDayIndex = 'cal_tbody_'+(t.getDate()+t.getDay()-1); showCal(); } function showCal(){ var tDate = new Date (); if(currentYear ==tDate.getYear()&¤tMonth==tDate.getMonth()) getEl(currentDayIndex).style.color='orange'; else getEl(currentDayIndex).style.color='white'; var today = new Date(currentYear,currentMonth,1); var month = today.getMonth(); var year = today.getYear(); var week = today.getDay(); var day = today.getDate(); var idIndex = week+1; var dayLength = day_of_month[month]; var i; if(month==1&&checkLeap(year)) dayLength++; for(i=1;i
具体的图片资源和源码文件我已经上传到我的资源了,有兴趣的朋友可以去下载来看看,反复调试过Css的效果之后,发现在火狐浏览器和IE下Div边距的2px问题很令人恼火,而且Dom事件模型也很大区别,所以在火狐里就无法使用了,希望以后有空可以再做一个更通用一点的。