置灰函数里的参数current的时分秒取值,是打开日历后,第一次执行置灰函数时刻的时分秒。
项目中需要对日期控件设置禁用日期,禁用规则:不能晚于今日,不能早于(上个工作日与本月第一天的较小者)。
我第一次写的代码是这样的
const disabledDateOfAdd = (current) => {
//获取每月的第一天
let monthFirstDay = dayjs().date(1)
//prevWorkday.value为后台返回的上个工作日,格式是'YYYY-MM-DD',比如‘2023-02-01’
//比较出上个工作日与本月第一天 的较小者
let earlierDay = dayjs(prevWorkday.value) < monthFirstDay ? dayjs(prevWorkday.value) : monthFirstDay
//把晚于今天,或早于earlierDay是日期置灰
return current > dayjs() || current < dayjs(earlierDay).subtract(1,'day')
}
我们看最后一行,置灰早于earlierDay的代码是:current < dayjs(earlierDay).subtract(1,'day')。按理说,早于earlierDay的日期置灰,应该是current < dayjs(earlierDay)。但是我当时试了几次,如果不减去一天(.substract(1,'day')),不该置灰的当月的第一天也会被置灰。
这是因为在当月第一天时,current通常比dayjs().date(1)早几毫秒。current的时分秒以及毫秒,是打开日历后,第一次执行置灰函数时的时分秒和毫秒,而dayjs(earlierDay)是置灰函数执行到此处时的时分秒以及毫秒。
例如,现在是3月6号,这个时候的本月第一天早于上个工作日,因此earlierDay的取值是dayjs().date(1),即2023-03-01 HH:mm:ss.xxx。我们现在(2023-03-06 13:48:54.230)点开上边2023年3月的日历,那么此时日历上的42天会依次执行disabledDateOfAdd函数,而每次执行该函数时,current的时分秒是一样的,都是第一次执行该函数的时分秒,而获取到的dayjs().date(1)是不一样的,是置灰函数执行到此处时的时分秒以及毫秒。2023-03-01的current比dayjs().date(1) 早4毫秒,所以dayjs().date(1)减去一天后,2023-03-01才不会被置灰。见下表
日期 | current | dayjs().date(1) 本月第一天 |
2023-02-27 | 2023-02-27 13:48:54.231 | 2023-03-01 13:48:54.231 |
2023-02-28 | 2023-02-28 13:48:54.231 | 2023-03-01 13:48:54.233 |
2023-03-01 | 2023-03-01 13:48:54.231 | 2023-03-01 13:48:54.235 |
2023-03-02 | 2023-03-02 13:48:54.231 | 2023-03-01 13:48:54.237 |
dayjs(earlierDay)减去一天后,看似可以满足需求。但是这个代码有个bug,当上个工作日和本月第一天为同一天时(例如2023-03-01),本该置灰的上月的最后一天没有置灰。这是因为prevWorkday被dayjs格式话后变成2023-03-01 00:00:00.000,dayjs().date(1).subtract(1,'day')是2023-02-28 13:48:54.235,current < dayjs(earlierDay).subtract(1,'day')不成立,所有这种情况下的2023-02-28不会置灰。
解决以上的问题也很简单,把用于比较的日期全部改为YYYY-MM-DD格式,排除时分秒和毫秒的影响。
修改后的代码如下:
const disabledDateOfAdd = (current) => {
let monthFirstDay = dayjs().date(1).format('YYYY-MM-DD')
prevWorkday.value = dayjs(prevWorkday.value).format('YYYY-MM-DD')
let earlierDay = prevWorkday.value < monthFirstDay ? prevWorkday.value : monthFirstDay
return current > dayjs() || current < dayjs(earlierDay)
}