起源
该问题发现于日期组件增加国家法定假节假日的禁用,通过pickerOptions
属性定义disabledDate方法实现
export default {
data () {
return {
holidayList: [
'2023-01-01',
'2023-01-02',
'2023-01-21',
'2023-01-22',
'2023-01-23',
'2023-01-24',
'2023-01-25',
'2023-01-26',
'2023-01-27',
'2023-04-05',
'2023-04-29',
'2023-04-30',
'2023-05-01',
'2023-05-02',
'2023-05-03',
'2023-06-22',
'2023-06-23',
'2023-06-24',
'2023-09-29',
'2023-09-30',
'2023-10-01',
'2023-10-02',
'2023-10-03',
'2023-10-04',
'2023-10-05',
'2023-10-06'
],
pickerOptions: this.handle(),
value: ''
}
},
methods: {
handle () {
const that = this
return {
disabledDate (time) {
console.log(new Date(time), '666')
if (time==法定节假日) {
return true
} else {
return time.getTime() < Date.now() - 8.64e7
}
}
}
}
}
}
原因
在disabledDate 中打印获得时间全部是使用的零时区时间,并且通.toLocaleString()
转换之后的时间格式为yyyy/MM/dd
为 RFC 2822 日期格式标准
而我们一般时间格式化使用国际标准ISO 8601
规范日期格式为
YYYY-MM-DDThh:mm:ss[.mmm]TZD
东八区,也就是GMT+8,并且.toLocaleString()
转换之后的时间格式为yyyy-MM-dd
两者之间的差别
- 当在不指定时区的情况下,RFC 2822 写法会使用
UTC
时间来解析,而ISO 8601写法则当作本地时区
处理 - RFC2822 相对来说写法更加宽松,甚至可以兼容 Mon, 06 Mar 2017 21:22:23 +0000 这样的写法
- RFC2822 的时区表示用四位数字(+0800),而 ISO 8601 的时区表示用 HH:MM (+08:00)
所以此时我们通过disabledDate 中的 yyyy/MM/dd
格式时间与yyyy-MM-dd
格式时间具有8小时的时间差
解决
统一时间到00:00:00
methods: {
handle () {
const that = this
return {
disabledDate (time) {
if (that.holidayList.find(d => time.getTime() === new Date(d + ' 00:00:00').getTime())) {
return true
} else {
return time.getTime() < Date.now() - 8.64e7
}
}
}
}
}
谁能想到 不同格式化的string日期转Date还有这种操作
参考:前端国际化时间日期概述与业务实践