确定月份和天数的slide及index
这里比起年份要相对复杂,因为年份一但确定下来就不会改变,无论年月日怎么切换年份是不会变的。
但是月份首先每个月的天数都不一样,而且在最大年最小年时会有限制。
根据初始年的类型确定月份slide及index
首先要对用户输入的初始年份进行判断,是最小年还是最大年还是处于中间,在针对这三种情况对月份和天数进行分别处理。
例如从当天2022-06-26回推十个月为2021-08-26,那么当用户输入了一个2021年的日期时月份就应该是8月到12月,当输入2022年时月份为1月到6月,天数同理。
let monthSlideInit = [];
let daySlideInit = [];
let monthIndexInit = 0;
let dayIndexInit = 0;
if(initYear === minYear) {
// 初始年是最小年,这时的月份为最小月到12月,index与年份同理为初始月减去最小月
monthSlideInit = generateSlide('month', 12, minMonth);
monthIndexInit = initMonth - minMonth;
} else if(initYear === maxYear) {
// 初始年是最大年,这时的月份为1月到最大月,index由于默认是从零开始的所以要减1
monthSlideInit = generateSlide('month', maxMonth, 1);
monthIndexInit = initMonth - 1;
} else {
// 初始年是普通年,这时月份为满月即1-12,index从0开始所以减1即可
monthSlideInit = generateSlide('month');
monthIndexInit = initMonth - 1;
}
计算对应年份对应月份总共多少天
在计算天数slide时,不同月份的天数不同,2月根据年份的不同天数也不同。因此需要一个函数来计算正常情况下,对应年份的对应月份总共有多少天。
/**
* 根据年份和月份计算当年当月的最大天数
* @param {number} year
* @param {number} month
*/
function maxDays(year, month) {
let days = 0;
if(month === 2) {
days = (year % 4 === 0) && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28;
} else if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
days = 31;
} else {
days = 30;
}
return days;
}
根据初始月的类型确定天数slide及index
确定天数时与月份同理,最小年最小月时的天数slide和最大年最大月的天数slide需要进行特殊处理,因此在确定天数时需要判断月份。
if(initYear === minYear) {
if(initMonth === minMonth) {
// 最小年最小月情况下,天数为最小天到这个月的最后一天,index同上
daySlideInit = generateSlide('day', maxDays(minYear, minMonth), minDay);
dayIndexInit = initDay - minDay;
} else {
// 最小年的其他月份就是普通月份,从1到该月最后一天,index从零开始所以减1
daySlideInit = generateSlide('day', maxDays(minYear, initMonth));
dayIndexInit = initDay - 1; // 例如16日的index为15,以下月份同理
}
} else if(initYear === maxYear) {
// 初始年是最大年,月份为最大月时天数为从1到最大的天数,当不是最大月时按照普通月份处理。
// 无论那种情况,index由于默认是从零开始的所以要减1
daySlideInit = initMonth === maxMonth ? generateSlide('day', maxDay, 1) : generateSlide('day', maxDay(initYear, initMonth));
dayIndexInit = initDay - 1;
} else {
// 既不是最小月也不是最大月时,为普通情况
daySlideInit = generateSlide('day', maxDays(initYear, initMonth));
dayIndexInit = initDay - 1;
}
Before模式下的月份天数处理
在before模式下月份和天数在原有基础上更加复杂。
当before的类型为年份时例如2年前、5年前,这时的月份和天数变化和默认模式是相同的。
但是当before的类型为月份时,会出现2月前、24月前这两种情况,也就是月份前置后是否会跨年。
如果跨年的话那么就与前面默认模式的几年前是相同的,但是如果不跨年的话就都在当年,那么他的月份就既不是从1-12,也不是从1-最大月,也不是从最小月-12,而是从最小月到最大月。
判断是否跨年
根据上述我们需要判断当为before模式,传入的type为"month"时最小年与当前年份是否存在跨年现象。
例如2022年6月,当输入的value为5时为五月前即2022年1月,不会跨年。而输入为6时就变为2021年12月会跨年。
因此判断跨年的条件为:最大月份减去传入的value是否大于0。
if(maxMonth - value > 0) {
// 跨年
} else {
// 不跨年
}
before模式下type等于month时的月份天数处理
经过上述分析后,我们首先在最小年中判断是否跨年,如果跨年就和默认模式相同。如果没跨年,那么此时年份就为一个年份,即最小年、初始年、最大年皆为同一年。所以此时按照代码逻辑根本不会进入到后面最大年和其他普通年份的if else,只会进第一个最小年。
当等于最小年时
// 判断年份
if(initYear === minYear) {
//判断before类型,如果是年份和默认模式逻辑一样
if(type === 'year') {
// 和默认模式一样
} else if(type === 'month') {
// 判断是否跨年
if(maxMonth - value > 0) {
monthSlideInit = generateSlide('month', maxMonth, minMonth);
monthIndexInit = initMonth - minMonth;
if(initMonth === minMonth) {
daySlideInit = generateSlide('day', maxDays(minYear, minMonth), minDay);
dayIndexInit = initDay - minDay;
} else if(initMonth === maxMonth) {
daySlideInit = generateSlide('day', maxDay, 1);
dayIndexInit = initDay - 1;
} else {
daySlideInit = generateSlide('day', maxDays(minYear, initMonth));
dayIndexInit = initDay - 1;
}
} else {
// 此处为跨年模式与默认模式相同
}
}
}
当等于最大年和其他年时
按照我们if else 最小年、最大年、其他年的顺序,如果代码走入了最大年或其他年而没有进最小年,那么说明最小年和最大年不是同一年,即跨年了。
此时还是默认的逻辑,所以不用做处理。