paint-brush
在 JavaScript 中添加时间间隔的简单方法经过@anwarhjg
729 讀數
729 讀數

在 JavaScript 中添加时间间隔的简单方法

经过 AHJ George4m2024/01/13
Read on Terminal Reader

太長; 讀書

您有一个时间表字符串、一个悬停的老板和 JavaScript。 问题:你想把工作时间加起来,让你的老板不再徘徊。 解决方案:不需要巫术。
featured image - 在 JavaScript 中添加时间间隔的简单方法
AHJ George HackerNoon profile picture
0-item

您不需要任何这些巫术用品来完成本教程。图片由作者提供。



唷。一股寒冷的紧绷感顺着你的脊椎蔓延。


哈啊啊。老板冰冷的呼吸像溢出的下水道一样冲刷着你的脖子。但你不能让他们在其他地方盘旋……自从办公室时间跟踪系统崩溃以来,他们就一直像鹰一样监视着你。


现在,它们就在那里……盘旋……呼吸。一怒之下。


您尝试在时间表上写下您的工作时间,但您的老板非常忙于所有这些呼吸。如果他们没有正确计算并错误地添加了您的时间怎么办?


以下是如何使用 JavaScript 将事情掌握在自己手中。哈啊啊啊

问题

您有一个类似于此String内容的时间表:

 const a = `November 30 2023 13:20-15:00, 15:30-16:40 December 4 2023 15:45-16:15, December 5 2023 08:00-08:30, 18:15-19:30, 21:45-22:15, 22:30-23:00 December 6 2023 19:45-21:45 December 7 2023 14:15-14:45, 15:15-15:45, 16:00-16:30, 16:45-17:15, 18:45-20:15, 20:45-22:45 December 13 2023 03:00-03:50 December 15 2023 09:00-09:30 20:30-21:15 21:45-22:30 23:30-24:00 December 16 2023 23:25-23:55 December 17 2023 19:05-19:50 20:30-21:30 22:15-23:45 December 20 2023 23:30-24:00 December 21 2023 02:20-2:50 03:15-03:30 13:40-14:00 16:00-17:15 17:45-18:45 19:20-20:10 21:30-22:20 23:00 - 24:00 December 22 2023 0:00-0:15`;


每行包含一个日期,后跟一些时间间隔。但它们写得不是很干净——有些间隔是用逗号分隔的,有些间隔是不规则的,等等。


考虑到这些不一致之处,最好不要假设有其他保证。例如,谁说所有时间都是同一年的?没有人,就是那个人。您希望尽可能可靠地将时间加在一起。

解决方案

这很容易。我们首先创建几个正则表达式和一个辅助函数。然后,我们就……呼呼!


啊!!老板,去个地方冷静一下吧!


正如我所说,现在我们可以用三步算法来完成任务:


  1. 我们将时间表字符串拆分为单独的行并减少它们以创建对象数组


  2. 对于每次迭代,我们:

    A. 使用yearRegex将年份分割线,记录日期字符串

    B.使用intervalsRegex收集所有时间范围间隔

    C. 减少时间范围,使用parseDate帮助器和步骤 2.A 中的日期字符串将每个时间范围解析为 JavaScript Date 对象


  3. 减少对象数组以找到总小时数


const yearRegex = /(\d{4})/gi; const intervalsRegex = /(\d+\:\d+)\s*-\s*(\d+\:\d+)/gi; const parseDate = (date, time) => Date.parse(`${date} ${time}`); let times = [...a.split("\n")].reduce((arr, entryLine) => { let entryLineSplit = entryLine.split(yearRegex); let o = { date: entryLineSplit[0] + entryLineSplit[1], timeRanges: [...entryLine.matchAll(intervalsRegex)], }; o.hoursForDay = o.timeRanges.reduce((total, [x, start, end]) => { let s = parseDate(o.date, start); let e = parseDate(o.date, end); return total + (e - s) / 1000 / 60 / 60; }, 0); return [...arr, o]; }, []); console.log(times); let totalHours = times.reduce((total, { hoursForDay }) => total + hoursForDay, 0); console.log(totalHours);


如果取消注释console.log(times);语句,您将看到一个包含以下对象的数组:

 { date: 'November 30 2023', timeRanges: [ [ '13:20-15:00', '13:20', '15:00', index: 17, input: 'November 30 2023 13:20-15:00, 15:30-16:40', groups: undefined ], [ '15:30-16:40', '15:30', '16:40', index: 30, input: 'November 30 2023 13:20-15:00, 15:30-16:40', groups: undefined ] ], totalHours: 2.8333333333333335 },

这种方法的好处

与简单地提取时间间隔并将其相加相比,构建对象数组具有一些明显的优点。


  • 它使得事后的遍历变得容易。如果您想做一些诸如绘制每日时间图表之类的事情,这是理想的选择。


  • 保存每条记录的日期字符串允许在调用Date.parse后使用内置的 JS 日期算术方法。


  • 该对象是存储调用String.prototype.split的结果的方便位置,该结果可能不唯一,具体取决于两天是否包含相同的时间间隔。

这种方法的缺点

这个解决方案并不完美:

  • 它需要两次大的遍历——一次遍历分割时间表的结果,然后一次遍历times对象。为了优化此代码,最好对包含totalHourstimes作为字段的空对象使用单个reduce。


  • 它使用正则表达式,格式越复杂,可能会变得越复杂

包起来

您现在知道如何从混乱的时间表中提取时间。只要付出一点额外的努力,您甚至可以构建一个完整的时钟。但那样你就不会花那么多美好的时间去了解你的老板了,不是吗?哈夫。