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

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

作者: 钟志弘 | 来源:发表于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