javascript 商城結算頁面選擇今日或明日送貨時間數組的實現

javascript 商城結算頁面選擇今日或明日送貨時間數組的實現

緣起

今日在開發一個生鮮商城的項目,其中結算頁面有一個需求。大概意思如下,後端會返回該店鋪每日的營業時間,格式是 { startTime: '09.00', endTime: '21.00'} 這樣的倆字段。前端要根據這倆字段來計算當天的和次日的送貨時間段,以半個小時爲間隔。

其中的重點是如果當前時間大於開始時間,則要在輸出的當天送貨時間段的數組中把已經超過的時間給減掉。

最終輸出的數據如下圖所示:
在這裏插入圖片描述

實現代碼

// 數字補零
function patchZero (str) {
  str = isNaN(+str) ? '0' : str
  const prefix = str > 9 ? '' : '0'
  return prefix + str
}
// 根據形如 '9.00' 這樣的字符串,計算該時間對應的時間戳
function calcUnixTime (timeStr, zreoUnix) {
  const [hour, minute] = timeStr.split('.')
  return zreoUnix + hour * 3600 * 1000 + minute * 60 * 1000
}
// 將時間戳輸出爲日期字符串
function calcUnixToDayStr (unix) {
  const time = new Date(unix)
  const Y = time.getFullYear()
  const M = patchZero(time.getMonth() + 1)
  const D = patchZero(time.getDate())
  return `${Y}-${M}-${D}`
}
// 將時間戳輸出爲時間字符串
function calcUnixToTimeStr (unix) {
  const time = new Date(unix)
  const h = patchZero(time.getHours())
  const m = patchZero(time.getMinutes())
  return `${h}:${m}`
}
// 根據開始時間戳和結束時間戳計算結果並輸出爲數組(30分鐘爲間隔)
function calcTimsArr (startUnix, endUinx) {
  const arr = []
  for (let i = startUnix; i <= endUinx; i += 1800000) {
    arr.push(calcUnixToTimeStr(i))
  }
  return assembleArr(arr)
}
// 拼裝最終需要的結果
function assembleArr (arr) {
  arr.map((item, index) => {
    index && (arr[index - 1] += ` - ${item}`)
  })
  arr.length -= 1
  return arr
}
// 計算今天的服務時間
function calcTodayTimes (arr, time) {
  const nextHour = patchZero(time.getHours() + 1)
  const startIndex = arr.findIndex(i => i.slice(0, 2) === nextHour)
  return arr.slice(startIndex, arr.length)
}
// 主函數
function main (startTimeStr, endTimeStr) {
  startTimeStr = startTimeStr || '09.00'
  endTimeStr = endTimeStr || '20.00'
  const startUinx = calcUnixTime(startTimeStr, -28800000)
  const endUinx = calcUnixTime(endTimeStr, -28800000)
  const serviceTimsArr = calcTimsArr(startUinx, endUinx)
  const time = new Date()
  const todayTimesArr = calcTodayTimes(serviceTimsArr, time)
  return {
    today: calcUnixToDayStr(+time),
    tomorrow: calcUnixToDayStr(+time + 86400000),
    todayTimesArr,
    tomorrowTimesArr: serviceTimsArr
  }
}
// 導出主函數
export default main

小結

實現邏輯很簡單

  1. 通過接口返回的小時字符串,計算對應的時間戳。
  2. 然後用這個時間戳以半個小時爲間隔進行循環,構建一個數組。
  3. 對這個數組進行處理,處理成最終需要的數組。
    1. 從第1個數組開始,把[1]的字符串追加到[0]後面,並加上中劃線間隔符。
    2. 把最後一位給刪了。
  4. 根據上面的數組,再用當前的時間來計算當天的服務時間的數組。
  5. 額外把今天和明天的日期返回出去。

踩的坑

一開始沒有深入瞭解需求,以爲要輸出的是帶年月日的格式,於是還搞了一個獲取當天零時時間戳的方法。瞭解到真實需求之後,發現不用計算,只要 -28800000 這個零時時間戳就好了。所以精簡了一下代碼,最終代碼如上。

不過踩坑的代碼也有價值,如下,沒有註釋,有興趣的看看:

// 數字補零
function patchZero (str) {
  str = isNaN(+str) ? '0' : str
  const prefix = str > 9 ? '' : '0'
  return prefix + str
}
// 獲取當天零時時間戳
function getZreoUnix (date) {
  const times = date.getTime()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()
  const zeroUnix = times - hour * 3600 * 1000 - minute * 60 * 1000 - second * 1000
  return zeroUnix
}
// 根據形如 '9.00' 這樣的字符串,計算該時間當天的時間戳
function calcUnixTime (timeStr, zreoUnix) {
  const [hour, minute] = timeStr.split('.')
  return zreoUnix + hour * 3600 * 1000 + minute * 60 * 1000
}
// 計算當天的開始時間 (如 9:00 開始,但當前時間已經是 11:00 了,則要根據當前時間來計算
function calcTodayStartUnixTime (now, zreoUnix, nowUnix, startUinx) {
  let res = zreoUnix
  if (nowUnix > startUinx) {
    const hour = now.getHours() + 1
    res += hour * 3600 * 1000
  } else {
    res = startUinx
  }
  return res
}
// 將時間戳輸出爲日期字符串
function calcUnixToDayStr (unix) {
  const time = new Date(unix)
  const Y = time.getFullYear()
  const M = patchZero(time.getMonth() + 1)
  const D = patchZero(time.getDate())
  return `${Y}-${M}-${D}`
}
// 將時間戳輸出爲時間字符串
function calcUnixToTimeStr (unix) {
  const time = new Date(unix)
  const h = patchZero(time.getHours())
  const m = patchZero(time.getMinutes())
  return `${h}:${m}`
}
// 根據開始時間戳和結束時間戳計算結果並輸出爲數組
function makeTimsArr (realStartUnix, endUinx) {
  const arr = []
  for (let i = realStartUnix; i <= endUinx; i += 1800000) {
    arr.push(calcUnixToTimeStr(i))
  }
  return arr
}
// 拼裝最終需要的結果
function assembleArr (arr) {
  const res = []
  arr.forEach((item, index) => {
    res.push(item)
    if (index) {
      res[index - 1] += ` - ${item}`
    }
  })
  res.length -= 1
  return res
}
// 主函數
function main (startTimeStr, endTimeStr) {
  startTimeStr = startTimeStr || '09.00'
  endTimeStr = endTimeStr || '20.00'
  const now = new Date()
  const zreoUnix = getZreoUnix(now)
  const nowUnix = +now
  // 計算今天
  const startUinx = calcUnixTime(startTimeStr, zreoUnix)
  const endUinx = calcUnixTime(endTimeStr, zreoUnix)
  const realStartUnix = calcTodayStartUnixTime(now, zreoUnix, nowUnix, startUinx)
  const todayTimsArr = makeTimsArr(realStartUnix, endUinx)
  // 計算明天
  const tomorrowStartUnix = startUinx + 86400000
  const tomorrowEndUinx = endUinx + 86400000
  const tomorrowTimsArr = makeTimsArr(tomorrowStartUnix, tomorrowEndUinx)
  // 輸出結果
  return {
    today: calcUnixToDayStr(startUinx),
    tomorrow: calcUnixToDayStr(tomorrowStartUnix),
    todayTimsArr: assembleArr(todayTimsArr),
    tomorrowTimsArr: assembleArr(tomorrowTimsArr)
  }
}
// 導出主函數
export default main

很有意思的代碼,希望對各位看官有所幫助。

本文由 FungLeo 原創,允許轉載,但轉載必須保留首發鏈接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章