专栏首页地方网络工作室的专栏javascript 商城结算页面选择今日或明日送货时间数组的实现

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 原创,允许转载,但转载必须保留首发链接。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 原生JS自己构建一个0-1之间的随机小数

    原生JS自己构建一个0-1之间的随机小数 前言 我们都知道使用Math.random()来得到一个随机数。但是很多人都没有深入的思考过,如何这个随机数是怎么来的...

    FungLeo
  • 打造前端 Deepin Linux 工作环境——开机自动加载 ~/.bash_profile 文件

    打造前端 Deepin Linux 工作环境——开机自动加载 ~/.bash_profile 文件 这个事情非常搞笑,当我把系统根据我的配置搞好之后,我就关机重...

    FungLeo
  • Python 打造基于百度翻译的命令行翻译工具

    版权声明:本文为 FengCms FungLeo 原创文章,允许转载,但转载必须注明出处并附带首发链接 ...

    FungLeo
  • Effective C++条款3 我可以不使用const?

    const是C++中用得非常频繁的一个关键字,但是如果你不使用这个关键字,对程序的运行结果影响不大,那么,我可以不使用const吗?

    ACM算法日常
  • C++primer学习笔记(一)

    震八方紫面昆仑侠
  • QMap容器小知识

    Qt君
  • 学习c++中的小问题总结

    徐飞机
  • const 详解

    http://blog.csdn.net/hackbuteer1/article/details/7459212

    bear_fish
  • C++雾中风景3:const用法的小结

    const关键字,翻译成中文是常量,常数的意思。所以在绝大多数场合之中,const是来定义常量的,定义常量也是好的编程习惯。在C类语言之中,定义常量通常会使用宏...

    HappenLee
  • 初级程序员面试不靠谱指南(二)

    3.read-only的const。如果你突然冒出一句看似很高深的话但又不解释一般都是装逼,就像前面提到过const准确的应该理解为一个read-only的变量...

    一心一怿

扫码关注云+社区

领取腾讯云代金券