美文网首页
小程序精确到分钟的时间选择器

小程序精确到分钟的时间选择器

作者: 钟志弘 | 来源:发表于2019-10-12 16:18 被阅读0次

为响应业务需求,特写了一个时间选择器。

该时间选择器特点:

  1. 代入一个时间字符串A, 根据这个时间字符串生成未来5年的时间。
  2. 代入一个小时偏移值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
      })

    },

核心代码就是以上了, 以下是组件代码地址:

相关文章

网友评论

      本文标题:小程序精确到分钟的时间选择器

      本文链接:https://www.haomeiwen.com/subject/yhgqmctx.html