You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

553 lines
18 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 日历库
* 作者tmzdy
* 时间2021-7-27
* 联系zhongjihan@sina.com
*/
class calendar{
value= new Date();
now_day_month = new Date();
start_time = new Date(1900,0,1)
end_time = new Date(2100,11,31)
txtdateArray = [];
/**
* value:初始化时间
* start:开始始间 提供了后会在返回的日历上标记每个日期是否是在start 和 end之间。
* end:结束时间
*/
constructor({value,start,end}) {
if(arguments.length===1){
let arg = arguments[0]
if(arg?.value){
value = value.replace(/-/g,'/');
let dobj = new Date(value);
this.value = new Date(dobj.getFullYear(),dobj.getMonth(),dobj.getDate());
this.now_day_month = this.value;
}
if(arg?.start){
let sv = start;
if(typeof sv ==='string'){
sv = new Date(sv.replace(/-/g,'/'))
}else if(typeof sv === 'object'){
sv = new Date(sv)
}
this.start_time = sv;
}
if(arg?.end){
let sv = end;
if(typeof sv ==='string'){
sv = new Date(sv.replace(/-/g,'/'))
}else if(typeof sv === 'object'){
sv = new Date(sv)
}
this.end_time = sv;
}
}
}
/**
* 日期转化为字符串, 4位年+2位月+2位日
*/
getDateStr(date) {
var _year = date.getFullYear();
var _month = date.getMonth(); // 月从0开始计数
var _d = date.getDate();
_month = (_month > 9) ? ("" + _month) : ("0" + _month);
_d = (_d > 9) ? ("" + _d) : ("0" + _d);
return _year + _month + _d;
}
// 设置当前计算的日历的时间 。格式为时间 格式。
setValue(value){
if(value){
let dobj = new Date();
if(typeof value === 'object'){
dobj = new Date(value);
}else{
value = value.replace(/-/g,'/');
dobj = new Date(value);
}
this.value = new Date(dobj.getFullYear(),dobj.getMonth(),dobj.getDate());
this.now_day_month = this.value;
}
return this;
}
// 未设置
setStart(start){
let sv = start;
if(typeof sv ==='string'){
sv = new Date(sv.replace(/-/g,'/'))
}else if(typeof sv === 'object'){
sv = new Date(sv)
}
this.start_time = sv;
return this;
}
setEnd(end){
let sv = end;
if(typeof sv ==='string'){
sv = new Date(sv.replace(/-/g,'/'))
}else if(typeof sv === 'object'){
sv = new Date(sv)
}
this.end_time = sv;
return this;
}
// 设置文本数据。携带在对象 中。
setTimeArrayText(textArray){
if(!Array.isArray(textArray)) return;
/**
* textArray
* {date:"2021-7-1",text:"你好"}
*/
this.txtdateArray = textArray;
return this;
}
monthDay(year, month) {
var date = new Date(year, month, 1, 0, 0, 0)
var yesterDay = new Date(date - 1000)
return yesterDay.getDate()
}
nongli(year,month,day){
const calendarobj = {
gregorianYear: null, //公历年
gregorianMonth: null, //公历月
gregorianDay: null, //公历日
weekday: null, //星期
hours: null,
minutes: null,
seconds: null,
lunarYear: null, //农历年
lunarMonth: null, //农历月
lunarDay: null, //农历日
lunarYearCn: '', //农历天干地支纪年
lunarMonthCn: '', //农历中文月
lunarDayCn: '', //农历中文日
zodiacYear: '', //农历生肖年
solarTerm: '', //节气
gregorianFestival: '', //公历节日
lunarFestival: '' //农历节日
}
let lunarInfo = [
0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
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]
let zodiacs = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
let Gan = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
let Zhi = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
let weekday = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
let now = new Date()
//用于计算农历年月日的数据
let GY = year
let GM = month
let GD = day
//==== 传入 offset 传回干支, 0=甲子
function cyclical(num) {
return(Gan[num % 10] + Zhi[num % 12])
}
//==== 传回农历 year年的总天数
function lYearDays(year) {
let i, sum = 348
for(i = 0x8000; i > 0x8; i >>= 1) {
sum += (lunarInfo[year - 1900] & i) ? 1: 0
}
return(sum + leapDays(year))
}
//==== 传回农历 year年闰月的天数
function leapDays(year) {
if(leapMonth(year)) {
return((lunarInfo[year-1900] & 0x10000)? 30: 29)
}
else {
return 0
}
}
//==== 传回农历 year年闰哪个月 1-12 , 没闰传回 0
function leapMonth(year) {
return(lunarInfo[year - 1900] & 0xf)
}
//==== 传回农历 year年month月的总天数
function monthDays(year, month) {
return( (lunarInfo[year - 1900] & (0x10000 >> month))? 30: 29 )
}
//==== 算出农历, 传入日期对象, 传回农历日期对象
// 该对象属性有 农历年year 农历月month 农历日day 是否闰年isLeap yearCyl dayCyl monCyl
function Lunar(objDate) {
let i, temp = 0
let baseDate = new Date(1900,0,31)
let offset = Math.floor((objDate - baseDate)/86400000)
let dayCyl = offset + 40
let monCyl = 14
for(i = 1900; i < 2050 && offset > 0; i++) {
temp = lYearDays(i)
offset -= temp
monCyl += 12
}
if(offset < 0) {
offset += temp;
i--;
monCyl -= 12
}
//农历年
let year = i
let yearCyl = i-1864
let leap = leapMonth(i) //闰哪个月
let isLeap = false //是否闰年
for(i=1; i<13 && offset>0; i++) {
//闰月
if(leap>0 && i === (leap+1) && isLeap === false) {
--i; isLeap = true; temp = leapDays(year);
}
else {
temp = monthDays(year, i);
}
//解除闰月
if(isLeap === true && i === (leap + 1)) {
isLeap = false
}
offset -= temp
if(isLeap === false) {
monCyl ++
}
}
if(offset === 0 && leap>0 && i===leap+1)
if(isLeap) {
isLeap = false
}
else {
isLeap = true
--i
--monCyl
}
if(offset<0){
offset += temp
--i
--monCyl
}
//农历月
let month = i
//农历日
let day = offset + 1
return {
year: year,
month: month,
day: day,
isLeap: isLeap,
leap: leap,
yearCyl: yearCyl,
dayCyl: dayCyl,
monCyl: monCyl
}
}
//==== 中文日期 m为传入月份d为传入日期
function cDay(m, d){
let nStr1 = ['日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
let nStr2 = ['初', '十', '廿', '卅', '']
//农历中文月
let lunarMonthCn
//农历中文日
let lunarDayCn
if (m > 10){
lunarMonthCn = '十' + nStr1[m - 10]
} else {
lunarMonthCn = nStr1[m]
}
lunarMonthCn += '月'
switch (d) {
case 10: lunarDayCn = '初十'; break;
case 20: lunarDayCn = '二十'; break;
case 30: lunarDayCn = '三十'; break;
default: lunarDayCn = nStr2[Math.floor(d/10)] + nStr1[d % 10]
}
return {
lunarMonthCn: lunarMonthCn,
lunarDayCn: lunarDayCn
}
}
//节气
function getSolarTerm() {
let sTermInfo = [
0, 21208, 42467, 63836, 85337, 107014,
128867, 150921, 173149, 195551, 218072, 240693,
263343, 285989, 308563, 331033, 353350, 375494,
397447, 419210, 440795, 462224, 483532, 504758
]
let solarTerm = [
'小寒', '大寒', '立春', '雨水', '惊蛰', '春分',
'清明', '谷雨', '立夏', '小满', '芒种', '夏至',
'小暑', '大暑', '立秋', '处暑', '白露', '秋分',
'寒露', '霜降', '立冬', '小雪', '大雪', '冬至'
]
let solarTerms = ''
let tmp1 = new Date(
(31556925974.7 * (GY - 1900) + sTermInfo[(GM-1) * 2 + 1] * 60000) + Date.UTC(1900,0,6,2,5)
)
let tmp2 = tmp1.getUTCDate()
if (tmp2 === GD) solarTerms = solarTerm[(GM-1) * 2 + 1]
tmp1 = new Date(
(31556925974.7 * (GY - 1900) + sTermInfo[(GM-1) * 2] * 60000) + Date.UTC(1900,0,6,2,5)
)
tmp2= tmp1.getUTCDate()
if (tmp2 === GD) solarTerms = solarTerm[(GM-1) * 2]
return solarTerms
}
//==== 中文日期 m为传入月份d为传入日期
function cDay(m ,d ){
let nStr1 = ['日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
let nStr2 = ['初', '十', '廿', '卅', '']
//农历中文月
let lunarMonthCn
//农历中文日
let lunarDayCn
if (m > 10){
lunarMonthCn = '十' + nStr1[m - 10]
} else {
lunarMonthCn = nStr1[m]
}
lunarMonthCn += '月'
switch (d) {
case 10: lunarDayCn = '初十'; break;
case 20: lunarDayCn = '二十'; break;
case 30: lunarDayCn = '三十'; break;
default: lunarDayCn = nStr2[Math.floor(d/10)] + nStr1[d % 10]
}
return {
lunarMonthCn: lunarMonthCn,
lunarDayCn: lunarDayCn
}
}
//去掉时分秒的日期
let sDObj = new Date(GY, GM-1, GD);
let lDObj = new Lunar(sDObj);
//节气
// calendar.solarTerm = getSolarTerm()
let n = cDay(lDObj.month,lDObj.day);
let y = cyclical( GY - 1900 + 36);
return {
year:y,
month:n.lunarMonthCn,
day:n.lunarDayCn,
shengxiao:zodiacs[(GY - 4) % 12],
jieqi:getSolarTerm()
};
}
//下个月,可以一直操作
nextMonth(){
this.value = new Date(this.value.getFullYear(),this.value.getMonth()+1,1);
return this;
}
//上个月,可以一直操作
prevMonth(){
this.value = new Date(this.value.getFullYear(),this.value.getMonth()-1,1);
return this;
}
//下一年
nexYear(){
this.value = new Date(this.value.getFullYear()+1,this.value.getMonth(),this.value.getDate());
return this;
}
//上一年
prevYear(){
this.value = new Date(this.value.getFullYear()-1,this.value.getMonth(),this.value.getDate());
return this;
}
// 把之前设置的上一年,下一年,上一月下一月等数据清除,恢复 到最原始的月份年份数据。
setInit(){
this.value = this.now_day_month;
return this;
}
// 返回初始化时的月份
getNowData(){
// 当前时间 。
let week = [7,1,2,3,4,5,6]
let text_week = ['周日','周一','周二','周三','周四','周五','周六']
let _thisdateStr = this.now_day_month.toLocaleString();
let _thisMothn = this.now_day_month.getMonth();//当前月
let _thisDay = this.now_day_month.getDate();//当前日
let _thisYear = this.now_day_month.getFullYear();//当前年
let _thisWeek = this.now_day_month.getDay();//当前周
let _thisMothn_day = new Date(_thisYear,_thisMothn,1) ; ///当月第一天数据。
let _thisDayDate = new Date(_thisYear,_thisMothn,_thisDay);
let months = [31,this.monthDay(_thisYear,_thisMothn),31,30,31,30,31,31,30,31,30,31];
let _thisMothn_lastDay = new Date(_thisYear,_thisMothn,months[_thisMothn]) ; ///当月最后数据。
let dateArray = [];//当前日历表数据。
let llineDate = [];//行数据。
let j=1;
let ishs = true //如果第一排没有本月数据需要切换模式。把本月放第一位。
for(let i=1 ;i <8;i++){
let tdy = new Date(_thisYear, _thisMothn, i - 6 - _thisMothn_day.getDay()); //当前循环日期。
if(i==7){
let tf = tdy.getTime()>= _thisMothn_day.getTime() && tdy.getTime() <= _thisMothn_lastDay.getTime() ?true:false;
if(!tf){
ishs = false;
break;
}
}
}
for(let i=1 ;i <43;i++){
var Day = null;
if(!ishs){
Day = new Date(_thisYear, _thisMothn, i + 1 - _thisMothn_day.getDay()); //当前循环日期。
}else{
Day = new Date(_thisYear, _thisMothn, i - 6 - _thisMothn_day.getDay()); //当前循环日期。
}
dateArray.push({
year:Day.getFullYear(),//年
month:Day.getMonth()+1,//月1-12
week:week[Day.getDay()],//周的数字1~7
week_text:text_week[Day.getDay()],//周的中文
day:Day.getDate(),//几号
prevMoth: Day.getTime() < _thisMothn_day.getTime() ?true:false,//是否是上月。
nowMonth: Day.getTime()>= _thisMothn_day.getTime() && Day.getTime() <= _thisMothn_lastDay.getTime() ?true:false,//是否当月
nowDay:Day.getTime() == _thisDayDate.getTime() ?true:false,//是否是当天。
nowYear:0,//是否当年
nextMoth: Day.getTime() > _thisMothn_lastDay.getTime()?true:false,//是否下月
beginEnd: Day.getTime() >= this.start_time.getTime() && Day.getTime() <= this.end_time.getTime()?true:false,//是否在开始和结束区间范围内。
nongli:this.nongli(Day.getFullYear(),Day.getMonth()+1,Day.getDate())
})
}
return dateArray;
}
// 返回当前选中月的日历数组。如果你不设置value和数据getNowData和getData相等。
/**
* 返回当前月数据。
* @return {
beginEnd: false,//是否在规定范围时间内
day: 16,//日
month: 7,//月
nextMoth: false,//是否下月
nowDay: false,//是否当天
nowMonth: true,//是否当月
prevMoth: false,/是否下月
week: 5,//周1-7
week_text: "周五",//同上
year: 2021,//年
nongli:{ //农历
day: "初七",//日
jieqi: "",//节气
month: "六月",//月
shengxiao: "牛",//生肖
year: "辛丑" //农历年
}
}
*/
getData(){
// 当前时间 。
let week = [7,1,2,3,4,5,6]
let text_week = ['周日','周一','周二','周三','周四','周五','周六']
let _thisdateStr = this.value.toLocaleString();
let _thisMothn = this.value.getMonth();//当前月
let _thisDay = this.value.getDate();//当前日
let _thisYear = this.value.getFullYear();//当前年
let _thisWeek = this.value.getDay();//当前周
let _thisMothn_day = new Date(_thisYear,_thisMothn,1) ; ///当月第一天数据。
let _thisDayDate = new Date(_thisYear,_thisMothn,_thisDay);
let months = [31,this.monthDay(_thisYear,_thisMothn),31,30,31,30,31,31,30,31,30,31];
let _thisMothn_lastDay = new Date(_thisYear,_thisMothn,months[_thisMothn]) ; ///当月最后数据。
let dateArray = [];//当前日历表数据。
let llineDate = [];//行数据。
let j=1;
let ishs = true //如果第一排没有本月数据需要切换模式。把本月放第一位。
for(let i=1 ;i <8;i++){
let tdy = new Date(_thisYear, _thisMothn, i - 6 - _thisMothn_day.getDay()); //当前循环日期。
if(i==7){
let tf = tdy.getTime()>= _thisMothn_day.getTime() && tdy.getTime() <= _thisMothn_lastDay.getTime() ?true:false;
if(!tf){
ishs = false;
break;
}
}
}
for(let i=1 ;i <43;i++){
var Day = null;
if(!ishs){
Day = new Date(_thisYear, _thisMothn, i + 1 - _thisMothn_day.getDay()); //当前循环日期。
}else{
Day = new Date(_thisYear, _thisMothn, i - 6 - _thisMothn_day.getDay()); //当前循环日期。
}
let dstr = Day.getFullYear() + "-" + (Day.getMonth()+1) + "-" + Day.getDate();
let TxtIndex = this.txtdateArray.findIndex(item=>{
return item.date == dstr
})
dateArray.push({
year:Day.getFullYear(),//年
month:Day.getMonth()+1,//月1-12
week:week[Day.getDay()],//周的数字1~7
week_text:text_week[Day.getDay()],//周的中文
day:Day.getDate(),//几号
prevMoth: Day.getTime() < _thisMothn_day.getTime() ?true:false,//是否是上月。
nowMonth: Day.getTime()>= _thisMothn_day.getTime() && Day.getTime() <= _thisMothn_lastDay.getTime() ?true:false,//是否当月
nowDay:Day.getTime() == _thisDayDate.getTime() ?true:false,//是否是当天。
nextMoth: Day.getTime() > _thisMothn_lastDay.getTime()?true:false,//是否下月
beginEnd: Day.getTime() >= this.start_time.getTime() && Day.getTime() <= this.end_time.getTime()?true:false,//是否在开始和结束区间范围内。
nongli:this.nongli(Day.getFullYear(),Day.getMonth()+1,Day.getDate()),
text:TxtIndex>-1? this.txtdateArray[TxtIndex]['text']:""
})
}
return dateArray;
}
}
export default calendar;