为响应业务需求,特写了一个时间选择器。
该时间选择器特点:
- 代入一个时间字符串A, 根据这个时间字符串生成未来5年的时间。
- 代入一个小时偏移值B,该组件会根据B对A进行小时小时,从而计算出默认的选择时间。
Q: 为什么不把小时偏移改成一个时间字符串, 然后在组件计算小时偏移?
A: 因为我当时没想到这个问题
Q:为什么需要时间参照和小时偏移?
A:因为需要所以需要
该组件的核心思想是: 对微信原有的picker-view 进行封装, 捕捉 它的change 时间,然后根据它返回的数组对原有数组重新生成
首先我们需要构造多个获取时间的方法, 例如, 年月日,最难的地方仅仅只是判断该年是否为闰年而已。
const pdarr = [31,28,31,30,31,30,31,31,30,31,30,31]
const ldarr = [31,29,31,30,31,30,31,31,30,31,30,31]
function newDateTime(date, offsetHour) {
console.log(date)
let match = date.match(/^(\d{4})-(\d{2})-(\d{2})\s*(\d{2})\S*(\d{2})/)
console.log(match)
if (match && match.length > 0) {
match.splice(0, 1)
console.log(match)
match = match.map(item => parseInt(item))
console.log("newDateTime: ",match)
return new Date(match[0], match[1] - 1, match[2], match[3] + offsetHour, match[4], 0, 0)
}
return new Date()
}
function genDateStr(date) {
const year = date.getFullYear()
const m = date.getMonth() + 1
console.log("month: ", m)
const month = m > 9 ? m : "0" + m
console.log("month: ", month)
const day = date.getDate() > 9 ? date.getDate() : "0" + date.getDate()
const hour = date.getHours() > 9 ? date.getHours() : "0" + date.getHours()
const minute = date.getMinutes() > 9 ? date.getMinutes() : "0" + date.getMinutes()
const str = `${year}-${month}-${day} ${hour}:${minute}`
return str
}
function judge(date1, date2, j) {
const jy = (d1, d2) => d1[0] == d2[0]
const jm = (d1,d2) => (jy(d1,d2) && d1[1] == d2[1])
const jd = (d1, d2) => (jm(d1,d2) && d1[2] == d2[2])
const jh = (d1, d2) => (jd(d1,d2) && d1[3] == d2[3])
const jmin = (d1,d2) => (jh(d1,d2) && d1[4] == d2[4])
const arr = {
"y": function (date1, date2) {
const d1 = splitDateTime(date1)
const d2 = splitDateTime(date2)
console.log("d1: ",d1, "d2:", d2)
return jy(d1,d2)
// return d1[0] == d2[0]
},
"m": function (date1, date2) {
const d1 = splitDateTime(date1)
const d2 = splitDateTime(date2)
return jm(d1,d2)
},
"d": function(date1, date2) {
const d1 = splitDateTime(date1)
const d2 = splitDateTime(date2)
return jd(d1,d2)
},
"h": function(date1, date2) {
const d1 = splitDateTime(date1)
const d2 = splitDateTime(date2)
return jh(d1,d2)
},
"min": function(date1, date2) {
const d1 = splitDateTime(date1)
const d2 = splitDateTime(date2)
return jmin(d1,d2)
}
}
return arr[j](date1,date2)
}
function splitDateTime(date) {
let match = date.match(/^(\d{4})-(\d{2})-(\d{2})\s*(\d{2})\S*(\d{2})/)
if(!match || match.length <= 0) return []
match.splice(0,1)
match[1] -= 1
match[1] = match[1] > 9 ? match[1] : "0" + match[1]
console.log("splitDateTime: ", match)
return match
}
/**
* @param reference
* reference date
*/
function getYear(reference) {
const d = splitDateTime(reference)
const y = parseInt(d[0])
return [
y,
y + 1,
y + 2,
y + 3,
y + 4,
y + 5
]
}
function getMonth(reference, current) {
// if(judge())
//const m = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const m =["01","02","03","04","05","06","07","08","09","10","11","12"]
console.log("reference: ",reference, ", current: ", current)
if(judge(reference,current, 'y')) {
// const dc = splitDateTime(current)
const c = newDateTime(reference, 0)
m.splice(0, c.getMonth())
}
return m
}
function getDay(reference, current) {
const c = newDateTime(current, 0)
const isLeap = isleap(c.getYear())
console.log(ldarr[c.getMonth()],pdarr[c.getMonth()], c.getMonth())
const dc = isLeap ? ldarr[c.getMonth()] : pdarr[c.getMonth()]
console.log(c)
console.log("dc: ",dc)
const da = []
for(let i = 1; i <= dc; i++) {
da.push(i)
}
console.log(da)
if(judge(reference, current, "m")) {
const rc = newDateTime(reference, 0)
da.splice(0, rc.getDate()-1)
}
return da
}
function getHour(reference, current) {
const ha = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"]
if(judge(reference, current, "d")) {
const d = newDateTime(reference, 0)
ha.splice(0, d.getHours())
}
return ha
}
function getMinute(reference, current) {
const ma = []
for(let i = 0; i < 60; i++) ma.push(i)
if(judge(reference, current, "h")) {
const c = newDateTime(reference ,0)
ma.splice(0, c.getMinutes())
}
return ma
}
function isleap(year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
}
function dayCount(year, month) {
if(isleap(year)) {
return ldarr[month]
}
return pdarr[month]
}
module.exports = {
getYear,
getMonth,
getDay,
getHour,
getMinute,
newDateTime,
genDateStr,
splitDateTime,
dayCount
}
后面就是整体逻辑代码, 需要关注的一点是,当参照值更新之后,需要重新刷新对数组的定位:
'reference':function(e) {
const offset = this.properties.monthOffset
const reference = e
if(!reference || reference == '') return
console.log("reference updated: ",reference)
let pvalue = [0,0,0,0,0]
if(this.properties.freeze){
this.setData({
pvalue
})
return
}
const d = splitDateTime(reference)
let year = 0
let m = parseInt(d[1])
let day = parseInt(d[2])
let hour = parseInt(d[3])
let minute = parseInt(d[4])
let month = 0
let j = false
console.log("hour : ",hour + offset)
if((hour + offset) >= 24 ) {
day =day+ Math.floor((hour+offset) / 24)
hour = (hour + offset) % 24
}else {
j = true
}
let dc = dayCount(year, month + m)
console.log("day: ", day)
if(day > dc) {
// 需要把当天剔除
day = day - 1
do {
month += 1
day -= dc
if(month + m > 11) {
month = 0
m = 0
year += 1
}
dc = dayCount(year, month + m)
}while(day > dc)
console.log(day)
}else {
day = day - d[2]
month = 0
year = 0
}
console.log(year,month, day,hour, 0)
if(!j)
pvalue = [year, month, day, hour, minute]
else
pvalue = [0,0,0,offset, minute]
console.log(pvalue)
this.setData({
pvalue
})
}
当组件要进行显示的时候,需要对生成时间数组:
handleShowPicker(e) {
if(!this.properties.ps) return
const {
reference
} = this.properties
const year = getYear(reference)
let date = new Date(year[this.data.pvalue[0]],0, 1, 0, 0)
let current = genDateStr(date)
const month = getMonth(reference,current)
date = new Date(year[this.data.pvalue[0]],month[this.data.pvalue[1]]-1,1,0,0)
current = genDateStr(date)
console.log("date for day: ",date, this.data.pvalue)
const day = getDay(reference,current)
date = new Date(year[this.data.pvalue[0]],month[this.data.pvalue[1]]-1,day[this.data.pvalue[2]],0,0)
current = genDateStr(date)
console.log("date for hour: ",date,this.data.pvalue)
const hour = getHour(reference,current)
date = new Date(year[this.data.pvalue[0]],month[this.data.pvalue[1]]-1,day[this.data.pvalue[2]],hour[this.data.pvalue[3]],0)
current = genDateStr(date)
console.log("date for minute: ",date)
const minute = getMinute(reference,current)
console.log(year, month, day, hour, minute)
this.setData({
currentYear: year,
currentMonth: month,
currentDay: day,
currentHour: hour,
currentMinute: minute,
show:!this.data.show
})
if(this.data.isSet) return
this.setData({
pvalue: this.data.pvalue
})
},
当组件变更的时候需要对组件状态进行刷新:
handlePickerChange(e){
const arr = e.detail.value
console.log("handlePickerChange: ", e)
this.setData({
pvalue: arr
})
const {
currentYear,
} = this.data
const {
reference
} = this.properties
let date = new Date(currentYear[arr[0]],0, 1, 0, 0)
let current = genDateStr(date)
//
// console.log("1: ",date, current)
console.log(arr)
// const year = getYear(reference)
const month = getMonth(reference, current)
date = new Date(currentYear[arr[0]],month[arr[1]]-1, 1, 0, 0)
current = genDateStr(date)
// console.log(current)
const day = getDay(reference, current)
date = new Date(currentYear[arr[0]],month[arr[1]]-1, day[arr[2]], 0, 0)
current = genDateStr(date)
// console.log(current)
const hour = getHour(reference, current)
date = new Date(currentYear[arr[0]],month[arr[1]]-1, day[arr[2]], hour[arr[3]], 0)
current = genDateStr(date)
// console.log(current)
const minute = getMinute(reference, current)
this.setData({
currentMonth: month,
currentDay: day,
currentHour: hour,
currentMinute: minute
})
},
---不知不觉就写了一些很蠢得代码, 但是谁又没有年轻过呢?
实际上下面这种方法从可读性角度来讲比上面的方法好非常多, 我为盲目写些乱七八糟的代码浪费时间而感到遗憾。
'current': function(v) {
const curStr = v
if( curStr == '') {
console.log("cur str is empty", curStr)
return
}
const refStr = this.properties.reference
if(refStr == '' || refStr == undefined) {
console.log("ref str is empty", refStr)
return
}
const reference = newDateTime(refStr, 0 )
const current = newDateTime(curStr, 0)
console.log("reference: ", reference)
console.log("current: ", current)
const timestamp = (current.getTime() - reference.getTime())
console.log(timestamp)
const m = new Date(timestamp)
const mstr = genDateStr(m)
const marr = splitDateTime(mstr)
console.log(marr)
const year = parseInt(marr[0]) - 1970
const month = parseInt(marr[1])
const day = parseInt(marr[2]) - 1
const hour = parseInt(marr[3]) - 8
const minute = parseInt(marr[4])
let d = splitDateTime(refStr)
let y = 0 + year
let mon = y > 0 ? parseInt(d[1]) :0 + month
let da = mon > 0 ? parseInt(d[2]) - 1 : 0 + day
let ho = da > 0 ? parseInt(d[3]) : 0 + hour
let min = ho > 0 ? parseInt(d[4]) : 0 + minute
console.log(year, mon, da, ho, min)
const pvalue = [year, mon, da, ho, min]
this.setData({
pvalue
})
},
核心代码就是以上了, 以下是组件代码地址: