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

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

该时间选择器特点:

  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
      })

    },

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342