From 34cf0e494ad7edec0705e41876b20fe8a70afe8d Mon Sep 17 00:00:00 2001 From: 6tail <6tail@6tail.cn> Date: Sat, 23 Jun 2018 17:22:52 +0800 Subject: [PATCH] Initial commit --- .gitignore | 16 + LICENSE | 21 ++ README.md | 38 +++ README_ZH.md | 38 +++ demo.html | 26 ++ lunar.js | 820 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 959 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 README_ZH.md create mode 100644 demo.html create mode 100644 lunar.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8ff194 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.class +target/ + +#idea +.idea/ +/idea/ +*.ipr +*.iml +*.iws + +# temp file +*.log +*.cache +*.diff +*.patch +*.tmp \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..aef6bcb --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 6tail + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2f0d020 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# lunar [![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/6tail/lunar-javascript/blob/master/LICENSE) + +lunar is a calendar library for Solar and Chinese Lunar. + +[简体中文](https://github.com/6tail/lunar-javascript/blob/master/README_ZH.md) + +## Example + +```html + + + + + + + + + + +``` + +Output: + + 2016-09-08 闰年 星期四 处女座 + 丙申年捌月初八 猴年 北方玄武 斗木獬 + +## Documentation + +Please visit [http://6tail.cn/calendar/api.html](http://6tail.cn/calendar/api.html "http://6tail.cn/calendar/api.html") + +## Contact + +lunar + diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 0000000..c3a9975 --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,38 @@ +# lunar [![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/6tail/lunar-javascript/blob/master/LICENSE) + +lunar是一个无依赖的支持阳历和阴历的日历工具库。 + +[English](https://github.com/6tail/lunar-javascript/blob/master/README.md) + +## 示例 + +```html + + + + + + + + + + +``` + +输出结果: + + 2016-09-08 闰年 星期四 处女座 + 丙申年捌月初八 猴年 北方玄武 斗木獬 + +## 文档 + +请移步至 [http://6tail.cn/calendar/api.html](http://6tail.cn/calendar/api.html "http://6tail.cn/calendar/api.html") + +## 联系 + +lunar + diff --git a/demo.html b/demo.html new file mode 100644 index 0000000..2743fe2 --- /dev/null +++ b/demo.html @@ -0,0 +1,26 @@ + + + + + lunar + + + + + + \ No newline at end of file diff --git a/lunar.js b/lunar.js new file mode 100644 index 0000000..d10e108 --- /dev/null +++ b/lunar.js @@ -0,0 +1,820 @@ +(function(W){ + var Solar = (function(){ + var _fromDate = function(date){ + return _fromYmd(date.getFullYear(),date.getMonth()+1,date.getDate()); + }; + var _fromYmd = function(y,m,d){ + var solar = { + _p:{ + year:y, + month:m, + day:d, + calendar:new Date(y+'/'+m+'/'+d) + }, + getYear:function(){ + return this._p.year; + }, + getMonth:function(){ + return this._p.month; + }, + getDay:function(){ + return this._p.day; + }, + getWeek:function(){ + return this._p.calendar.getDay(); + }, + getWeekInChinese:function(){ + return SolarUtil.WEEK[this.getWeek()]; + }, + /** + * 获取当天的阳历周 + * @param start 星期几作为一周的开始,1234560分别代表星期一至星期天 + */ + getSolarWeek:function(start){ + return SolarWeek.fromDate(this._p.calendar,start); + }, + isLeapYear:function(){ + return SolarUtil.isLeapYear(this._p.year); + }, + getFestivals:function(){ + var l = []; + var f = SolarUtil.FESTIVAL[this._p.month+'-'+this._p.day]; + if(f) l.push(f); + var week = this.getWeek(); + var weekInMonth = Math.ceil((this._p.day-week)/7); + if(week>0) weekInMonth++; + f = SolarUtil.WEEK_FESTIVAL[this._p.month+'-'+weekInMonth+'-'+week]; + if(f) l.push(f); + return l; + }, + getXingzuo:function(){ + var index = 11,m = this._p.month,d = this._p.day; + var y = m*100+d; + if(y>=321&&y<=419) index = 0; + else if(y>=420&&y<=520) index = 1; + else if(y>=521&&y<=620) index = 2; + else if(y>=621&&y<=722) index = 3; + else if(y>=723&&y<=822) index = 4; + else if(y>=823&&y<=922) index = 5; + else if(y>=923&&y<=1022) index = 6; + else if(y>=1023&&y<=1121) index = 7; + else if(y>=1122&&y<=1221) index = 8; + else if(y>=1222||y<=119) index = 9; + else if(y<=218) index = 10; + return SolarUtil.XINGZUO[index]; + }, + toString:function(){ + return [this._p.year,(this._p.month<10?'0':'')+this._p.month,(this._p.day<10?'0':'')+this._p.day].join('-'); + }, + toFullString:function(){ + var s = this.toString(); + if(this.isLeapYear()){ + s += ' 闰年'; + } + s += ' 星期'+this.getWeekInChinese(); + var festivals = this.getFestivals(); + for(var i=0,j=festivals.length;ilastDate){ + lunarD -= lastDate; + lunarM = LunarUtil.nextMonth(lunarY,lunarM); + if(lunarM==1) lunarY++; + lastDate = LunarUtil.getDaysOfMonth(lunarY,lunarM); + } + return _fromYmd(lunarY,lunarM,lunarD,solar); + }; + var _fromYmd = function(y,m,d,solar){ + var lunar = { + _p:{ + year:y, + month:m, + day:d, + solar:null + }, + _toSolar:function(){ + var y = LunarUtil.BASE_YEAR; + var m = LunarUtil.BASE_MONTH; + var d = LunarUtil.BASE_DAY; + var diff = LunarUtil.getDaysOfMonth(y,m)-d; + m = LunarUtil.nextMonth(y,m); + while(true){ + diff += LunarUtil.getDaysOfMonth(y,m); + m = LunarUtil.nextMonth(y,m); + if(m==1) y++; + if(y==this._p.year&&m==this._p.month){ + diff += this._p.day; + break; + } + } + var date = new Date(SolarUtil.BASE_YEAR+'/'+SolarUtil.BASE_MONTH+'/'+SolarUtil.BASE_DAY); + date.setDate(date.getDate()+diff); + return Solar.fromDate(date); + }, + getYear:function(){ + return this._p.year; + }, + getMonth:function(){ + return this._p.month; + }, + getDay:function(){ + return this._p.day; + }, + getGan:function(){ + return LunarUtil.GAN[(this._p.year-4)%10+1]; + }, + getZhi:function(){ + return LunarUtil.ZHI[(this._p.year-4)%12+1]; + }, + getShengxiao:function(){ + return LunarUtil.SHENGXIAO[(this._p.year-4)%12+1]; + }, + getMonthInChinese:function(){ + var month = this._p.month; + if(month>0){ + return LunarUtil.MONTH[month]; + }else{ + return '闰'+LunarUtil.MONTH[-month]; + } + }, + getDayInChinese:function(){ + return LunarUtil.DAY[this._p.day]; + }, + getJie:function(){ + var s = '',solar = this._p.solar; + var solarYear = solar.getYear(); + var solarMonth = solar.getMonth(); + var solarDay = solar.getDay(); + var index = 0; + var ry = solarYear-SolarUtil.BASE_YEAR+1; + while(ry>=LunarUtil.JIE_YEAR[solarMonth-1][index]){ + index++; + } + var term = LunarUtil.JIE_MAP[solarMonth-1][4*index+ry%4]; + if(ry==121&&solarMonth==4) term = 5; + if(ry==132&&solarMonth==4) term = 5; + if(ry==194&&solarMonth==6) term = 6; + if(solarDay==term) s = LunarUtil.JIE[solarMonth-1]; + return s; + }, + getQi:function(){ + var s = '',solar = this._p.solar; + var solarYear = solar.getYear(); + var solarMonth = solar.getMonth(); + var solarDay = solar.getDay(); + var index = 0; + var ry = solarYear-SolarUtil.BASE_YEAR+1; + while(ry>=LunarUtil.QI_YEAR[solarMonth-1][index]){ + index++; + } + var term = LunarUtil.QI_MAP[solarMonth-1][4*index+ry%4]; + if(ry==171&&solarMonth==3) term = 21; + if(ry==181&&solarMonth==5) term = 21; + if(solarDay==term) s = LunarUtil.QI[solarMonth-1]; + return s; + }, + getXiu:function(){ + return LunarUtil.XIU[this._p.day-1][this._p.month-1]; + }, + getZheng:function(){ + return LunarUtil.ZHENG[this.getXiu()]; + }, + getAnimal:function(){ + return LunarUtil.ANIMAL[this.getXiu()]; + }, + getGong:function(){ + return LunarUtil.GONG[this.getXiu()]; + }, + getShou:function(){ + return LunarUtil.SHOU[this.getGong()]; + }, + getFestivals:function(){ + var l = []; + var f = LunarUtil.FESTIVAL[this._p.month+'-'+this._p.day]; + if(f) l.push(f); + return l; + }, + getSolar:function(){ + return this._p.solar; + }, + toString:function(){ + return this.getGan()+this.getZhi()+'年'+this.getMonthInChinese()+'月'+this.getDayInChinese(); + }, + toFullString:function(){ + var s = this.toString(); + s += ' '+this.getShengxiao()+'年'; + var festivals = this.getFestivals(); + for(var i=0,j=festivals.length;i0){ + s += ' ['+jieqi+']'; + } + s += ' '+this.getGong()+'方'+this.getShou(); + s += ' '+this.getXiu()+this.getZheng()+this.getAnimal(); + return s; + } + }; + lunar._p.solar = solar?solar:lunar._toSolar(); + return lunar; + }; + return { + fromYmd:function(y,m,d){return _fromYmd(y,m,d);}, + fromDate:function(date){return _fromDate(date);} + }; + })(); + var SolarWeek = (function(){ + var _fromDate = function(date,start){ + return _fromYmd(date.getFullYear(),date.getMonth()+1,date.getDate(),start); + }; + var _fromYmd = function(y,m,d,start){ + var solarWeek = { + _p:{ + year:y, + month:m, + day:d, + start:start, + calendar:new Date(y+'/'+m+'/'+d) + }, + getYear:function(){ + return this._p.year; + }, + getMonth:function(){ + return this._p.month; + }, + getDay:function(){ + return this._p.day; + }, + getStart:function(){ + return this._p.start; + }, + /** + * 获取当前日期是在当月第几周 + * @return 周序号,从1开始 + */ + getIndex:function(){ + var firstDate = new Date(this._p.year+'/'+this._p.month+'/1'); + var firstDayWeek = firstDate.getDay(); + return Math.ceil((this._p.day+firstDayWeek-this._p.start)/7); + }, + /** + * 周推移 + * @param weeks 推移的周数,负数为倒推 + * @param separateMonth 是否按月单独计算 + * @return 推移后的阳历周 + */ + next:function(weeks,separateMonth){ + if(0==weeks){ + return _fromYmd(this._p.year,this._p.month,this._p.day,this._p.start); + } + if(separateMonth){ + var n = weeks; + var date = new Date(this._p.year+'/'+this._p.month+'/'+this._p.day); + var week = _fromDate(date,this._p.start); + var month = this._p.month; + var plus = n>0; + while(0!=n){ + date.setDate(date.getDate()+(plus?7:-7)); + week = _fromDate(date,this._p.start); + var weekMonth = week.getMonth(); + if(month!=weekMonth){ + var index = week.getIndex(); + if(plus){ + if(1==index){ + var firstDay = week.getFirstDay(); + week = _fromYmd(firstDay.getYear(),firstDay.getMonth(),firstDay.getDay(),this._p.start); + weekMonth = week.getMonth(); + }else{ + date = new Date(week.getYear()+'/'+week.getMonth()+'/1'); + week = _fromDate(date,this._p.start); + } + }else{ + var size = SolarUtil.getWeeksOfMonth(week.getYear(),week.getMonth(),this._p.start); + if(size==index){ + var firstDay = week.getFirstDay(); + var lastDay = firstDay.next(6); + week = _fromYmd(lastDay.getYear(),lastDay.getMonth(),lastDay.getDay(),this._p.start); + weekMonth = week.getMonth(); + }else{ + date = new Date(week.getYear()+'/'+week.getMonth()+'/'+SolarUtil.getDaysOfMonth(week.getYear(),week.getMonth())); + week = _fromDate(date,this._p.start); + } + } + month = weekMonth; + } + n-=plus?1:-1; + } + return week; + }else{ + var date = new Date(this._p.year+'/'+this._p.month+'/'+this._p.day); + date.setDate(date.getDate()+weeks*7); + return _fromDate(date,this._p.start); + } + }, + /** + * 获取本周第一天的阳历日期(可能跨月) + * @return 本周第一天的阳历日期 + */ + getFirstDay:function(){ + var date = new Date(this._p.year+'/'+this._p.month+'/'+this._p.day); + var week = date.getDay(); + var prev = week-this._p.start; + if(prev<0){ + prev += 7; + } + date.setDate(date.getDate()-prev); + return Solar.fromDate(date); + }, + /** + * 获取本周第一天的阳历日期(仅限当月) + * @return 本周第一天的阳历日期 + */ + getFirstDayInMonth:function(){ + var days = this.getDays(); + for(var i = 0;i0){ + var index = y-this.BASE_YEAR+this.BASE_INDEX; + var v = this.LUNAR_MONTH[2*index+1]; + v = (v>>4)&0x0F; + if(v==m){ + n = -m; + } + } + if(n==13) n = 1; + return n; + }, + getDaysOfMonth:function(year,month){ + var index = year-this.BASE_YEAR+this.BASE_INDEX; + var v = 0,l = 0,d = 30; + if(1<=month&&month<=8){ + v = this.LUNAR_MONTH[2*index]; + l = month-1; + if(((v>>l)&0x01)==1){ + d = 29; + } + }else if(9<=month&&month<=12){ + v = this.LUNAR_MONTH[2*index+1]; + l = month-9; + if(((v>>l)&0x01)==1){ + d = 29; + } + }else{ + v = this.LUNAR_MONTH[2*index+1]; + v = (v>>4)&0x0F; + if(v!=Math.abs(month)){ + d = 0; + }else{ + d = 29; + for(var i = 0;i