$ npm install leave-days-calculator
复制代码
import leaveDaysCalculator form 'leave-days-calculator'
复制代码
const start = '2020-06-22 上午'
const end = '2020-06-24 下午'
let leaveDays = leaveDaysCalculator(start, end) // 3
复制代码
时间的格式只支持: YYYY-MM-DD 上午/下午javascript
自从作了小程序外勤打卡需求后,紧接着继续作请假审批流程的开发,在处理请假表单的时候,有个请假时长的展现。当用户选择了请假的开始时间和结束时间后,能够自动推算出请假时长,听上去需求很常规。可是,哈哈哈,产品要求全部请假都按照半天请,好比说:java
请假的开始时间是6月1号上午,结束是6月2号上午,并非结束时间减去开始时间那么简单。上午到上午的这种状况,多了半天呐。😂😂😂npm
那么问题来了,如何准确的计算请假时长?小程序
按照当前请假,非当前请假两类计算,数组
若是是当天请假:函数
若是是隔天计算: 结束时间 - 开始时间 = gap工具
此方案的核心是须要准确的计算出gap,可使用第三方工具来处理。从计算量上来看,工做量比较小。优化
纯手动计算,按照当天上下午,隔天上下午,隔月上下午,隔年上下午手动计算出请假时长。这个方案的开发时长比较长,在开发周期比较宽裕的状况下我选择了方案,由于我还很想知道具体是这么计算的。给本身找点事干,给枯燥的coding,增添点趣味。ui
基于开始时间和结束时间的格式都是 YYYY-MM-DD 上午/下午
。spa
图一:流程图
算起来有四种计算规则:
须要一些基础工具函数,好比说:
业务公共方法:
如下是请假时长计算器的源码,仅供参考。
/** * @Authors youxiaoxiao (gao0807@foxmail.com) * @Date: 2020-06-1 * @Last Modified by: youxiaoxiao * 请假时长计算器:(经过 (开始时间 + 结束时间)计算请假时长) */
/** * 是不是闰年 * @param {*} year */
function isLeapYear (year) {
return year % 100 !== 0 && year % 4 === 0 || year % 400 === 0
}
/** * 获取每一年每个月的天数 * @param {*} year * @param {*} month */
function getMaxDay (year, month) {
year = parseFloat(year)
month = parseFloat(month)
if (month === 2) {
return isLeapYear(year) ? 29 : 28
}
return [4, 6, 9, 11].indexOf(month) >= 0 ? 30 : 31
}
// 去0
function trimZero (val) {
val = String(val)
val = val ? parseFloat(val.replace(/^0+/g, '')) : ''
val = val || 0
val = val + ''
return val
}
/** * 同一天请假 */
function sameDayLeave(startNoon, endNoon) {
let leaveDays = 0
if (startNoon === endNoon) {
leaveDays = 0.5
}
else if (startNoon === '上午' && endNoon === '下午') {
leaveDays = 1
}
else if (startNoon === '下午' && endNoon === '上午') {
console.log('您选择的时间有误')
}
return leaveDays
}
/** * 隔天请假 */
function nextDayLeave(startDay, endDay, startNoon, endNoon) {
let leaveDays = 0
if (startNoon === '上午' && endNoon === '上午') {
leaveDays = endDay - startDay + 0.5
}
else if (startNoon === '上午' && endNoon === '下午') {
leaveDays = endDay - startDay + 1
}
else if (startNoon === '下午' && endNoon === '上午') {
leaveDays = endDay - startDay
}
else if (startNoon === '下午' && endNoon === '下午') {
leaveDays = endDay - startDay + 0.5
}
return leaveDays
}
/** * 开始月份请假天数 跨月,年才会用到的函数 */
function startMonthLeaveDays (startMonthAllDays, startDay, startNoon) {
let startMonthLeave = 0
if (startNoon === '上午') {
startMonthLeave = Number(startMonthAllDays) - Number(startDay) + 1
} else if (startNoon === '下午') {
startMonthLeave = Number(startMonthAllDays) - Number(startDay) + 0.5
}
return Number(startMonthLeave)
}
/** * 结束月的请假天数 跨月,年才会用到的函数 */
function endMonthLeaveDays(endDay, endNoon) {
let endLeaveDays = 0
if (endNoon === '上午') {
endLeaveDays = endDay - 0.5
} else if (endNoon === '下午') {
endLeaveDays = endDay
}
return Number(endLeaveDays)
}
/** * 经过开始时间和结束时间,计算请假时长 * @param {*} start 【支持:格式 yyyy-mm-dd n】 * @param {*} end 【支持:格式 yyyy-mm-dd n】 */
export default (start, end) => {
if(!start || !end) return 0
const startArr = start.split(' ') // 开始时间
const endArr = end.split(' ') // 结束时间
const startDate = startArr[0] // 开始日期
const endDate = endArr[0] // 结束日期
const startDateArr = startDate.split('-') // 开始日期 数组化
const endDateArr = endDate.split('-') // 结束日期 数组化
const startYear = startDateArr[0] // 开始日期:年
const startMonth = startDateArr[1] // 开始日期:月
const startDay = startDateArr[2] // 开始日期:日
const startNoon = startArr[1] // 开始时间的上下午
const endYear = endDateArr[0] // 结束日期:年
const endMonth = endDateArr[1] // 结束日期:月
const endDay = endDateArr[2] // 结束日期:日
const endNoon = endArr[1] // 结束时间的上下午
// 开始月份的总天数
const startMonthAllDays = getMaxDay(startYear, startMonth)
/** * 中间月份的请假天数计算 */
function centerMonthsLeave() {
// 中间月份天数累加
let leaveDays = 0
let monthArr = [] // 月份数组
for(let i = Number(trimZero(startMonth)); i <= Number(trimZero(endMonth)); i++) {
monthArr.push(i)
}
let everyMonthDays = 0
if (monthArr.length > 2) {
monthArr.pop()
monthArr.shift()
monthArr.forEach(month => {
everyMonthDays = Number(everyMonthDays) + Number(getMaxDay(startYear, month))
})
}
return (Number(leaveDays) + Number(everyMonthDays)).toFixed(1)
}
/** * 开始月份和结束月份请假天数 相邻月请假,或则跨月请假 */
function startEndMonthNext() {
// 开始月份请假天数计算
let startLeaveDays = startMonthLeaveDays(startMonthAllDays, startDay, startNoon)
// 结束月份请假天数计算
let endLeaveDays = endMonthLeaveDays(endDay, endNoon)
// 天数累加
return Number(startLeaveDays) + Number(endLeaveDays) || 0
}
/** * 开始年的请假天数计算 */
function startYearLeaveDays () {
// 开始月份天数计算
let startMonthDays = startMonthLeaveDays(startMonthAllDays, startDay, startNoon)
// 剩下月份的天数
let otherMonthDays = 0
for(let i = Number(trimZero(startMonth)) + 1; i <= 12; i++) {
otherMonthDays = Number(otherMonthDays) + Number(getMaxDay(startYear, i))
}
return Number(startMonthDays) + Number(otherMonthDays) || 0
}
/** * 结束年的请假天数计算 */
function endYearLeaveDays() {
let endYearDays = 0
// 结束月份计算
let endLeaveDays = endMonthLeaveDays(endDay, endNoon)
// 前几个月份天数累加
for(let i = 1; i < trimZero(endMonth); i++) {
endYearDays = Number(endYearDays) + Number(getMaxDay(endYear, i))
}
return Number(endYearDays) + Number(endLeaveDays)
}
/** * 跨年,中间年假期计算 */
function centerYearsLeaveDays () {
let centerYear = 0
if(endYear - startYear > 1) {
let centerYears = []
for(let startYear; startYear < endYear; startYear++) {
centerYears.push(startYear)
}
centerYears.pop()
centerYears.shift()
centerYears.forEach(year => {
for(let month = 1; month <=12; month++) {
centerYear = centerYear + getMaxDay(year, month)
}
})
}
return centerYear
}
// 请假天数
let leaveAllDays = 0
// 是否同年
if (startYear === endYear) {
// 是否同月
if (startMonth === endMonth) {
// 是否同天
if (startDay === endDay) {
leaveAllDays = sameDayLeave(startNoon, endNoon)
// 同年 同月 隔天请假计算
} else if (startDay < endDay) {
leaveAllDays = nextDayLeave(startDay, endDay, startNoon, endNoon)
} else {
console.log('结束时间的天不对')
}
// 同年 不是同月
} else if (startMonth < endMonth) {
// 两个月相邻状况, 开始月份剩余天数,结束月份请假天数 之和
let startEndMonthLeaveDays = startEndMonthNext()
// 中间月份请假的天数
let centerMonthsDays = centerMonthsLeave()
// 请假天数汇总
leaveAllDays = Number(startEndMonthLeaveDays) + Number(centerMonthsDays)
} else {
console.log('结束时间的月份不对')
}
// 不是同年
} else if (startYear < endYear) {
// 开始年的请假天数计算: 开始月剩下的天数 + 剩下月份的天数
let startYearDays = startYearLeaveDays()
// 结束年的请假天数计算: 结束月的天数 + 结束月以前月份的天数
let endYearDays = endYearLeaveDays()
// 中间年份的天数
let centerYear = centerYearsLeaveDays()
// 请假天数汇总累加
leaveAllDays = Number(startYearDays) + Number(endYearDays) + Number(centerYear)
} else {
console.log('结束时间的年份不对')
}
// console.log(leaveAllDays)s
return leaveAllDays
}
复制代码
一个请假时长计算器就开发完了,其实方案一更省事一点,方案二的实现,还有不少能够优化的点。最终封装好的请假时长计算器 npm包:leave-days-calculator。
若是你有其它的方案或者优化实现,欢迎在下方留言交流。